Adding debian version 3.70~pre8+dfsg-1.
[syslinux-debian/hramrach.git] / gpxe / src / core / settings.c
blob752531864d8f811276407a358e439d24eaf96b86
1 /*
2 * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 #include <stdint.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <strings.h>
24 #include <byteswap.h>
25 #include <errno.h>
26 #include <assert.h>
27 #include <gpxe/in.h>
28 #include <gpxe/vsprintf.h>
29 #include <gpxe/dhcp.h>
30 #include <gpxe/uuid.h>
31 #include <gpxe/settings.h>
33 /** @file
35 * Configuration settings
39 /** Registered settings */
40 static struct setting settings[0]
41 __table_start ( struct setting, settings );
42 static struct setting settings_end[0]
43 __table_end ( struct setting, settings );
45 /** Registered setting types */
46 static struct setting_type setting_types[0]
47 __table_start ( struct setting_type, setting_types );
48 static struct setting_type setting_types_end[0]
49 __table_end ( struct setting_type, setting_types );
51 /** Registered settings applicators */
52 static struct settings_applicator settings_applicators[0]
53 __table_start ( struct settings_applicator, settings_applicators );
54 static struct settings_applicator settings_applicators_end[0]
55 __table_end ( struct settings_applicator, settings_applicators );
57 /******************************************************************************
59 * Registered settings blocks
61 ******************************************************************************
64 /**
65 * Store value of simple setting
67 * @v options DHCP option block
68 * @v setting Setting to store
69 * @v data Setting data, or NULL to clear setting
70 * @v len Length of setting data
71 * @ret rc Return status code
73 int simple_settings_store ( struct settings *settings, struct setting *setting,
74 const void *data, size_t len ) {
75 struct simple_settings *simple =
76 container_of ( settings, struct simple_settings, settings );
77 return dhcpopt_extensible_store ( &simple->dhcpopts, setting->tag,
78 data, len );
81 /**
82 * Fetch value of simple setting
84 * @v options DHCP option block
85 * @v setting Setting to fetch
86 * @v data Buffer to fill with setting data
87 * @v len Length of buffer
88 * @ret len Length of setting data, or negative error
90 int simple_settings_fetch ( struct settings *settings, struct setting *setting,
91 void *data, size_t len ) {
92 struct simple_settings *simple =
93 container_of ( settings, struct simple_settings, settings );
94 return dhcpopt_fetch ( &simple->dhcpopts, setting->tag, data, len );
97 /** Simple settings operations */
98 struct settings_operations simple_settings_operations = {
99 .store = simple_settings_store,
100 .fetch = simple_settings_fetch,
103 /** Root simple settings block */
104 struct simple_settings simple_settings_root = {
105 .settings = {
106 .refcnt = NULL,
107 .name = "",
108 .siblings =
109 LIST_HEAD_INIT ( simple_settings_root.settings.siblings ),
110 .children =
111 LIST_HEAD_INIT ( simple_settings_root.settings.children ),
112 .op = &simple_settings_operations,
116 /** Root settings block */
117 #define settings_root simple_settings_root.settings
120 * Apply all settings
122 * @ret rc Return status code
124 static int apply_settings ( void ) {
125 struct settings_applicator *applicator;
126 int rc;
128 /* Call all settings applicators */
129 for ( applicator = settings_applicators ;
130 applicator < settings_applicators_end ; applicator++ ) {
131 if ( ( rc = applicator->apply() ) != 0 ) {
132 DBG ( "Could not apply settings using applicator "
133 "%p: %s\n", applicator, strerror ( rc ) );
134 return rc;
138 return 0;
142 * Reprioritise settings
144 * @v settings Settings block
146 * Reorders the settings block amongst its siblings according to its
147 * priority.
149 static void reprioritise_settings ( struct settings *settings ) {
150 struct settings *parent = settings->parent;
151 long priority;
152 struct settings *tmp;
153 long tmp_priority;
155 /* Stop when we reach the top of the tree */
156 if ( ! parent )
157 return;
159 /* Read priority, if present */
160 priority = fetch_intz_setting ( settings, &priority_setting );
162 /* Remove from siblings list */
163 list_del ( &settings->siblings );
165 /* Reinsert after any existing blocks which have a higher priority */
166 list_for_each_entry ( tmp, &parent->children, siblings ) {
167 tmp_priority = fetch_intz_setting ( tmp, &priority_setting );
168 if ( priority > tmp_priority )
169 break;
171 list_add_tail ( &settings->siblings, &tmp->siblings );
173 /* Recurse up the tree */
174 reprioritise_settings ( parent );
178 * Register settings block
180 * @v settings Settings block
181 * @v parent Parent settings block, or NULL
182 * @ret rc Return status code
184 int register_settings ( struct settings *settings, struct settings *parent ) {
186 /* NULL parent => add to settings root */
187 assert ( settings != NULL );
188 if ( parent == NULL )
189 parent = &settings_root;
191 /* Add to list of settings */
192 ref_get ( settings->refcnt );
193 ref_get ( parent->refcnt );
194 settings->parent = parent;
195 list_add_tail ( &settings->siblings, &parent->children );
196 DBGC ( settings, "Settings %p registered\n", settings );
198 /* Fix up settings priority */
199 reprioritise_settings ( settings );
201 /* Apply potentially-updated settings */
202 apply_settings();
204 return 0;
208 * Unregister settings block
210 * @v settings Settings block
212 void unregister_settings ( struct settings *settings ) {
214 /* Remove from list of settings */
215 ref_put ( settings->refcnt );
216 ref_put ( settings->parent->refcnt );
217 settings->parent = NULL;
218 list_del ( &settings->siblings );
219 DBGC ( settings, "Settings %p unregistered\n", settings );
221 /* Apply potentially-updated settings */
222 apply_settings();
226 * Find child named settings block
228 * @v parent Parent settings block
229 * @v name Name within this parent
230 * @ret settings Settings block, or NULL
232 struct settings * find_child_settings ( struct settings *parent,
233 const char *name ) {
234 struct settings *settings;
235 size_t len;
237 /* NULL parent => add to settings root */
238 if ( parent == NULL )
239 parent = &settings_root;
241 /* Look for a child whose name matches the initial component */
242 list_for_each_entry ( settings, &parent->children, siblings ) {
243 len = strlen ( settings->name );
244 if ( strncmp ( name, settings->name, len ) != 0 )
245 continue;
246 if ( name[len] == 0 )
247 return settings;
248 if ( name[len] == '.' )
249 return find_child_settings ( settings,
250 ( name + len + 1 ) );
253 return NULL;
257 * Find named settings block
259 * @v name Name
260 * @ret settings Settings block, or NULL
262 struct settings * find_settings ( const char *name ) {
264 /* If name is empty, use the root */
265 if ( ! *name )
266 return &settings_root;
268 return find_child_settings ( &settings_root, name );
271 /******************************************************************************
273 * Core settings routines
275 ******************************************************************************
279 * Store value of setting
281 * @v settings Settings block
282 * @v setting Setting to store
283 * @v data Setting data, or NULL to clear setting
284 * @v len Length of setting data
285 * @ret rc Return status code
287 int store_setting ( struct settings *settings, struct setting *setting,
288 const void *data, size_t len ) {
289 int rc;
291 /* Sanity check */
292 if ( ! settings )
293 return -ENODEV;
295 /* Store setting */
296 if ( ( rc = settings->op->store ( settings, setting,
297 data, len ) ) != 0 )
298 return rc;
300 /* Reprioritise settings if necessary */
301 if ( setting_cmp ( setting, &priority_setting ) == 0 )
302 reprioritise_settings ( settings );
304 /* If these settings are registered, apply potentially-updated
305 * settings
307 for ( ; settings ; settings = settings->parent ) {
308 if ( settings == &settings_root ) {
309 if ( ( rc = apply_settings() ) != 0 )
310 return rc;
311 break;
315 return 0;
319 * Fetch value of setting
321 * @v settings Settings block, or NULL to search all blocks
322 * @v setting Setting to fetch
323 * @v data Buffer to fill with setting data
324 * @v len Length of buffer
325 * @ret len Length of setting data, or negative error
327 * The actual length of the setting will be returned even if
328 * the buffer was too small.
330 int fetch_setting ( struct settings *settings, struct setting *setting,
331 void *data, size_t len ) {
332 struct settings *child;
333 int ret;
335 /* NULL settings implies starting at the global settings root */
336 if ( ! settings )
337 settings = &settings_root;
339 /* Try this block first */
340 if ( ( ret = settings->op->fetch ( settings, setting,
341 data, len ) ) >= 0 )
342 return ret;
344 /* Recurse into each child block in turn */
345 list_for_each_entry ( child, &settings->children, siblings ) {
346 if ( ( ret = fetch_setting ( child, setting,
347 data, len ) ) >= 0 )
348 return ret;
351 return -ENOENT;
355 * Fetch length of setting
357 * @v settings Settings block, or NULL to search all blocks
358 * @v setting Setting to fetch
359 * @ret len Length of setting data, or negative error
361 * This function can also be used as an existence check for the
362 * setting.
364 int fetch_setting_len ( struct settings *settings, struct setting *setting ) {
365 return fetch_setting ( settings, setting, NULL, 0 );
369 * Fetch value of string setting
371 * @v settings Settings block, or NULL to search all blocks
372 * @v setting Setting to fetch
373 * @v data Buffer to fill with setting string data
374 * @v len Length of buffer
375 * @ret len Length of string setting, or negative error
377 * The resulting string is guaranteed to be correctly NUL-terminated.
378 * The returned length will be the length of the underlying setting
379 * data.
381 int fetch_string_setting ( struct settings *settings, struct setting *setting,
382 char *data, size_t len ) {
383 memset ( data, 0, len );
384 return fetch_setting ( settings, setting, data, ( len - 1 ) );
388 * Fetch value of IPv4 address setting
390 * @v settings Settings block, or NULL to search all blocks
391 * @v setting Setting to fetch
392 * @v inp IPv4 address to fill in
393 * @ret len Length of setting, or negative error
395 int fetch_ipv4_setting ( struct settings *settings, struct setting *setting,
396 struct in_addr *inp ) {
397 int len;
399 len = fetch_setting ( settings, setting, inp, sizeof ( *inp ) );
400 if ( len < 0 )
401 return len;
402 if ( len < ( int ) sizeof ( *inp ) )
403 return -ERANGE;
404 return len;
408 * Fetch value of signed integer setting
410 * @v settings Settings block, or NULL to search all blocks
411 * @v setting Setting to fetch
412 * @v value Integer value to fill in
413 * @ret len Length of setting, or negative error
415 int fetch_int_setting ( struct settings *settings, struct setting *setting,
416 long *value ) {
417 union {
418 long value;
419 uint8_t u8[ sizeof ( long ) ];
420 int8_t s8[ sizeof ( long ) ];
421 } buf;
422 int len;
423 int i;
425 buf.value = 0;
426 len = fetch_setting ( settings, setting, &buf, sizeof ( buf ) );
427 if ( len < 0 )
428 return len;
429 if ( len > ( int ) sizeof ( buf ) )
430 return -ERANGE;
432 *value = ( ( buf.s8[0] >= 0 ) ? 0 : -1L );
433 for ( i = 0 ; i < len ; i++ ) {
434 *value = ( ( *value << 8 ) | buf.u8[i] );
437 return len;
441 * Fetch value of unsigned integer setting
443 * @v settings Settings block, or NULL to search all blocks
444 * @v setting Setting to fetch
445 * @v value Integer value to fill in
446 * @ret len Length of setting, or negative error
448 int fetch_uint_setting ( struct settings *settings, struct setting *setting,
449 unsigned long *value ) {
450 long svalue;
451 int len;
453 len = fetch_int_setting ( settings, setting, &svalue );
454 if ( len < 0 )
455 return len;
457 *value = ( svalue & ( -1UL >> ( sizeof ( long ) - len ) ) );
459 return len;
463 * Fetch value of signed integer setting, or zero
465 * @v settings Settings block, or NULL to search all blocks
466 * @v setting Setting to fetch
467 * @ret value Setting value, or zero
469 long fetch_intz_setting ( struct settings *settings, struct setting *setting ){
470 long value = 0;
472 fetch_int_setting ( settings, setting, &value );
473 return value;
477 * Fetch value of unsigned integer setting, or zero
479 * @v settings Settings block, or NULL to search all blocks
480 * @v setting Setting to fetch
481 * @ret value Setting value, or zero
483 unsigned long fetch_uintz_setting ( struct settings *settings,
484 struct setting *setting ) {
485 unsigned long value = 0;
487 fetch_uint_setting ( settings, setting, &value );
488 return value;
492 * Fetch value of UUID setting
494 * @v settings Settings block, or NULL to search all blocks
495 * @v setting Setting to fetch
496 * @v uuid UUID to fill in
497 * @ret len Length of setting, or negative error
499 int fetch_uuid_setting ( struct settings *settings, struct setting *setting,
500 union uuid *uuid ) {
501 int len;
503 len = fetch_setting ( settings, setting, uuid, sizeof ( *uuid ) );
504 if ( len < 0 )
505 return len;
506 if ( len != sizeof ( *uuid ) )
507 return -ERANGE;
508 return len;
512 * Compare two settings
514 * @v a Setting to compare
515 * @v b Setting to compare
516 * @ret 0 Settings are the same
517 * @ret non-zero Settings are not the same
519 int setting_cmp ( struct setting *a, struct setting *b ) {
521 /* If the settings have tags, compare them */
522 if ( a->tag && ( a->tag == b->tag ) )
523 return 0;
525 /* Otherwise, compare the names */
526 return strcmp ( a->name, b->name );
529 /******************************************************************************
531 * Formatted setting routines
533 ******************************************************************************
537 * Store value of typed setting
539 * @v settings Settings block
540 * @v setting Setting to store
541 * @v type Settings type
542 * @v value Formatted setting data, or NULL
543 * @ret rc Return status code
545 int storef_setting ( struct settings *settings, struct setting *setting,
546 const char *value ) {
548 /* NULL value implies deletion. Avoid imposing the burden of
549 * checking for NULL values on each typed setting's storef()
550 * method.
552 if ( ! value )
553 return delete_setting ( settings, setting );
555 return setting->type->storef ( settings, setting, value );
559 * Find named setting
561 * @v name Name
562 * @ret setting Named setting, or NULL
564 static struct setting * find_setting ( const char *name ) {
565 struct setting *setting;
567 for ( setting = settings ; setting < settings_end ; setting++ ) {
568 if ( strcmp ( name, setting->name ) == 0 )
569 return setting;
571 return NULL;
575 * Find setting type
577 * @v name Name
578 * @ret type Setting type, or NULL
580 static struct setting_type * find_setting_type ( const char *name ) {
581 struct setting_type *type;
583 for ( type = setting_types ; type < setting_types_end ; type++ ) {
584 if ( strcmp ( name, type->name ) == 0 )
585 return type;
587 return NULL;
591 * Parse setting name
593 * @v name Name of setting
594 * @v settings Settings block to fill in
595 * @v setting Setting to fill in
596 * @ret rc Return status code
598 * Interprets a name of the form
599 * "[settings_name/]tag_name[:type_name]" and fills in the appropriate
600 * fields.
602 static int parse_setting_name ( const char *name, struct settings **settings,
603 struct setting *setting ) {
604 char tmp_name[ strlen ( name ) + 1 ];
605 char *settings_name;
606 char *setting_name;
607 char *type_name;
608 struct setting *named_setting;
609 char *tmp;
611 /* Set defaults */
612 *settings = &settings_root;
613 memset ( setting, 0, sizeof ( *setting ) );
614 setting->type = &setting_type_hex;
616 /* Split name into "[settings_name/]setting_name[:type_name]" */
617 memcpy ( tmp_name, name, sizeof ( tmp_name ) );
618 if ( ( setting_name = strchr ( tmp_name, '/' ) ) != NULL ) {
619 *(setting_name++) = 0;
620 settings_name = tmp_name;
621 } else {
622 setting_name = tmp_name;
623 settings_name = NULL;
625 if ( ( type_name = strchr ( setting_name, ':' ) ) != NULL )
626 *(type_name++) = 0;
628 /* Identify settings block, if specified */
629 if ( settings_name ) {
630 *settings = find_settings ( settings_name );
631 if ( *settings == NULL ) {
632 DBG ( "Unrecognised settings block \"%s\" in \"%s\"\n",
633 settings_name, name );
634 return -ENODEV;
638 /* Identify tag number */
639 if ( ( named_setting = find_setting ( setting_name ) ) != NULL ) {
640 memcpy ( setting, named_setting, sizeof ( *setting ) );
641 } else {
642 /* Unrecognised name: try to interpret as a tag number */
643 tmp = setting_name;
644 while ( 1 ) {
645 setting->tag = ( ( setting->tag << 8 ) |
646 strtoul ( tmp, &tmp, 0 ) );
647 if ( *tmp == 0 )
648 break;
649 if ( *tmp != '.' ) {
650 DBG ( "Invalid setting \"%s\" in \"%s\"\n",
651 setting_name, name );
652 return -ENOENT;
654 tmp++;
658 /* Identify setting type, if specified */
659 if ( type_name ) {
660 setting->type = find_setting_type ( type_name );
661 if ( setting->type == NULL ) {
662 DBG ( "Invalid setting type \"%s\" in \"%s\"\n",
663 type_name, name );
664 return -ENOTSUP;
668 return 0;
672 * Parse and store value of named setting
674 * @v name Name of setting
675 * @v value Formatted setting data, or NULL
676 * @ret rc Return status code
678 int storef_named_setting ( const char *name, const char *value ) {
679 struct settings *settings;
680 struct setting setting;
681 int rc;
683 if ( ( rc = parse_setting_name ( name, &settings, &setting ) ) != 0 )
684 return rc;
685 return storef_setting ( settings, &setting, value );
689 * Fetch and format value of named setting
691 * @v name Name of setting
692 * @v buf Buffer to contain formatted value
693 * @v len Length of buffer
694 * @ret len Length of formatted value, or negative error
696 int fetchf_named_setting ( const char *name, char *buf, size_t len ) {
697 struct settings *settings;
698 struct setting setting;
699 int rc;
701 if ( ( rc = parse_setting_name ( name, &settings, &setting ) ) != 0 )
702 return rc;
703 return fetchf_setting ( settings, &setting, buf, len );
706 /******************************************************************************
708 * Setting types
710 ******************************************************************************
714 * Parse and store value of string setting
716 * @v settings Settings block
717 * @v setting Setting to store
718 * @v value Formatted setting data
719 * @ret rc Return status code
721 static int storef_string ( struct settings *settings, struct setting *setting,
722 const char *value ) {
723 return store_setting ( settings, setting, value, strlen ( value ) );
727 * Fetch and format value of string setting
729 * @v settings Settings block, or NULL to search all blocks
730 * @v setting Setting to fetch
731 * @v buf Buffer to contain formatted value
732 * @v len Length of buffer
733 * @ret len Length of formatted value, or negative error
735 static int fetchf_string ( struct settings *settings, struct setting *setting,
736 char *buf, size_t len ) {
737 return fetch_string_setting ( settings, setting, buf, len );
740 /** A string setting type */
741 struct setting_type setting_type_string __setting_type = {
742 .name = "string",
743 .storef = storef_string,
744 .fetchf = fetchf_string,
748 * Parse and store value of IPv4 address setting
750 * @v settings Settings block
751 * @v setting Setting to store
752 * @v value Formatted setting data
753 * @ret rc Return status code
755 static int storef_ipv4 ( struct settings *settings, struct setting *setting,
756 const char *value ) {
757 struct in_addr ipv4;
759 if ( inet_aton ( value, &ipv4 ) == 0 )
760 return -EINVAL;
761 return store_setting ( settings, setting, &ipv4, sizeof ( ipv4 ) );
765 * Fetch and format value of IPv4 address setting
767 * @v settings Settings block, or NULL to search all blocks
768 * @v setting Setting to fetch
769 * @v buf Buffer to contain formatted value
770 * @v len Length of buffer
771 * @ret len Length of formatted value, or negative error
773 static int fetchf_ipv4 ( struct settings *settings, struct setting *setting,
774 char *buf, size_t len ) {
775 struct in_addr ipv4;
776 int raw_len;
778 if ( ( raw_len = fetch_ipv4_setting ( settings, setting, &ipv4 ) ) < 0)
779 return raw_len;
780 return snprintf ( buf, len, "%s", inet_ntoa ( ipv4 ) );
783 /** An IPv4 address setting type */
784 struct setting_type setting_type_ipv4 __setting_type = {
785 .name = "ipv4",
786 .storef = storef_ipv4,
787 .fetchf = fetchf_ipv4,
791 * Parse and store value of integer setting
793 * @v settings Settings block
794 * @v setting Setting to store
795 * @v value Formatted setting data
796 * @v size Integer size, in bytes
797 * @ret rc Return status code
799 static int storef_int ( struct settings *settings, struct setting *setting,
800 const char *value, unsigned int size ) {
801 union {
802 uint32_t num;
803 uint8_t bytes[4];
804 } u;
805 char *endp;
807 u.num = htonl ( strtoul ( value, &endp, 0 ) );
808 if ( *endp )
809 return -EINVAL;
810 return store_setting ( settings, setting,
811 &u.bytes[ sizeof ( u ) - size ], size );
815 * Parse and store value of 8-bit integer setting
817 * @v settings Settings block
818 * @v setting Setting to store
819 * @v value Formatted setting data
820 * @v size Integer size, in bytes
821 * @ret rc Return status code
823 static int storef_int8 ( struct settings *settings, struct setting *setting,
824 const char *value ) {
825 return storef_int ( settings, setting, value, 1 );
829 * Parse and store value of 16-bit integer setting
831 * @v settings Settings block
832 * @v setting Setting to store
833 * @v value Formatted setting data
834 * @v size Integer size, in bytes
835 * @ret rc Return status code
837 static int storef_int16 ( struct settings *settings, struct setting *setting,
838 const char *value ) {
839 return storef_int ( settings, setting, value, 2 );
843 * Parse and store value of 32-bit integer setting
845 * @v settings Settings block
846 * @v setting Setting to store
847 * @v value Formatted setting data
848 * @v size Integer size, in bytes
849 * @ret rc Return status code
851 static int storef_int32 ( struct settings *settings, struct setting *setting,
852 const char *value ) {
853 return storef_int ( settings, setting, value, 4 );
857 * Fetch and format value of signed integer setting
859 * @v settings Settings block, or NULL to search all blocks
860 * @v setting Setting to fetch
861 * @v buf Buffer to contain formatted value
862 * @v len Length of buffer
863 * @ret len Length of formatted value, or negative error
865 static int fetchf_int ( struct settings *settings, struct setting *setting,
866 char *buf, size_t len ) {
867 long value;
868 int rc;
870 if ( ( rc = fetch_int_setting ( settings, setting, &value ) ) < 0 )
871 return rc;
872 return snprintf ( buf, len, "%ld", value );
876 * Fetch and format value of unsigned integer setting
878 * @v settings Settings block, or NULL to search all blocks
879 * @v setting Setting to fetch
880 * @v buf Buffer to contain formatted value
881 * @v len Length of buffer
882 * @ret len Length of formatted value, or negative error
884 static int fetchf_uint ( struct settings *settings, struct setting *setting,
885 char *buf, size_t len ) {
886 unsigned long value;
887 int rc;
889 if ( ( rc = fetch_uint_setting ( settings, setting, &value ) ) < 0 )
890 return rc;
891 return snprintf ( buf, len, "%#lx", value );
894 /** A signed 8-bit integer setting type */
895 struct setting_type setting_type_int8 __setting_type = {
896 .name = "int8",
897 .storef = storef_int8,
898 .fetchf = fetchf_int,
901 /** A signed 16-bit integer setting type */
902 struct setting_type setting_type_int16 __setting_type = {
903 .name = "int16",
904 .storef = storef_int16,
905 .fetchf = fetchf_int,
908 /** A signed 32-bit integer setting type */
909 struct setting_type setting_type_int32 __setting_type = {
910 .name = "int32",
911 .storef = storef_int32,
912 .fetchf = fetchf_int,
915 /** An unsigned 8-bit integer setting type */
916 struct setting_type setting_type_uint8 __setting_type = {
917 .name = "uint8",
918 .storef = storef_int8,
919 .fetchf = fetchf_uint,
922 /** An unsigned 16-bit integer setting type */
923 struct setting_type setting_type_uint16 __setting_type = {
924 .name = "uint16",
925 .storef = storef_int16,
926 .fetchf = fetchf_uint,
929 /** An unsigned 32-bit integer setting type */
930 struct setting_type setting_type_uint32 __setting_type = {
931 .name = "uint32",
932 .storef = storef_int32,
933 .fetchf = fetchf_uint,
937 * Parse and store value of hex string setting
939 * @v settings Settings block
940 * @v setting Setting to store
941 * @v value Formatted setting data
942 * @ret rc Return status code
944 static int storef_hex ( struct settings *settings, struct setting *setting,
945 const char *value ) {
946 char *ptr = ( char * ) value;
947 uint8_t bytes[ strlen ( value ) ]; /* cannot exceed strlen(value) */
948 unsigned int len = 0;
950 while ( 1 ) {
951 bytes[len++] = strtoul ( ptr, &ptr, 16 );
952 switch ( *ptr ) {
953 case '\0' :
954 return store_setting ( settings, setting, bytes, len );
955 case ':' :
956 ptr++;
957 break;
958 default :
959 return -EINVAL;
965 * Fetch and format value of hex string setting
967 * @v settings Settings block, or NULL to search all blocks
968 * @v setting Setting to fetch
969 * @v buf Buffer to contain formatted value
970 * @v len Length of buffer
971 * @ret len Length of formatted value, or negative error
973 static int fetchf_hex ( struct settings *settings, struct setting *setting,
974 char *buf, size_t len ) {
975 int raw_len;
976 int check_len;
977 int used = 0;
978 int i;
980 raw_len = fetch_setting_len ( settings, setting );
981 if ( raw_len < 0 )
982 return raw_len;
985 uint8_t raw[raw_len];
987 check_len = fetch_setting ( settings, setting, raw,
988 sizeof ( raw ) );
989 assert ( check_len == raw_len );
991 if ( len )
992 buf[0] = 0; /* Ensure that a terminating NUL exists */
993 for ( i = 0 ; i < raw_len ; i++ ) {
994 used += ssnprintf ( ( buf + used ), ( len - used ),
995 "%s%02x", ( used ? ":" : "" ),
996 raw[i] );
998 return used;
1002 /** A hex-string setting */
1003 struct setting_type setting_type_hex __setting_type = {
1004 .name = "hex",
1005 .storef = storef_hex,
1006 .fetchf = fetchf_hex,
1010 * Parse and store value of UUID setting
1012 * @v settings Settings block
1013 * @v setting Setting to store
1014 * @v value Formatted setting data
1015 * @ret rc Return status code
1017 static int storef_uuid ( struct settings *settings __unused,
1018 struct setting *setting __unused,
1019 const char *value __unused ) {
1020 return -ENOTSUP;
1024 * Fetch and format value of UUID setting
1026 * @v settings Settings block, or NULL to search all blocks
1027 * @v setting Setting to fetch
1028 * @v buf Buffer to contain formatted value
1029 * @v len Length of buffer
1030 * @ret len Length of formatted value, or negative error
1032 static int fetchf_uuid ( struct settings *settings, struct setting *setting,
1033 char *buf, size_t len ) {
1034 union uuid uuid;
1035 int raw_len;
1037 if ( ( raw_len = fetch_uuid_setting ( settings, setting, &uuid ) ) < 0)
1038 return raw_len;
1039 return snprintf ( buf, len, "%s", uuid_ntoa ( &uuid ) );
1042 /** UUID setting type */
1043 struct setting_type setting_type_uuid __setting_type = {
1044 .name = "uuid",
1045 .storef = storef_uuid,
1046 .fetchf = fetchf_uuid,
1049 /******************************************************************************
1051 * Settings
1053 ******************************************************************************
1056 /** Hostname setting */
1057 struct setting hostname_setting __setting = {
1058 .name = "hostname",
1059 .description = "Host name",
1060 .tag = DHCP_HOST_NAME,
1061 .type = &setting_type_string,
1064 /** Filename setting */
1065 struct setting filename_setting __setting = {
1066 .name = "filename",
1067 .description = "Boot filename",
1068 .tag = DHCP_BOOTFILE_NAME,
1069 .type = &setting_type_string,
1072 /** Root path setting */
1073 struct setting root_path_setting __setting = {
1074 .name = "root-path",
1075 .description = "NFS/iSCSI root path",
1076 .tag = DHCP_ROOT_PATH,
1077 .type = &setting_type_string,
1080 /** Username setting */
1081 struct setting username_setting __setting = {
1082 .name = "username",
1083 .description = "User name",
1084 .tag = DHCP_EB_USERNAME,
1085 .type = &setting_type_string,
1088 /** Password setting */
1089 struct setting password_setting __setting = {
1090 .name = "password",
1091 .description = "Password",
1092 .tag = DHCP_EB_PASSWORD,
1093 .type = &setting_type_string,
1096 /** Priority setting */
1097 struct setting priority_setting __setting = {
1098 .name = "priority",
1099 .description = "Priority of these settings",
1100 .tag = DHCP_EB_PRIORITY,
1101 .type = &setting_type_int8,