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.
28 #include <gpxe/vsprintf.h>
29 #include <gpxe/dhcp.h>
30 #include <gpxe/uuid.h>
32 #include <gpxe/settings.h>
36 * Configuration settings
40 /** Registered settings */
41 static struct setting settings
[0]
42 __table_start ( struct setting
, settings
);
43 static struct setting settings_end
[0]
44 __table_end ( struct setting
, settings
);
46 /** Registered setting types */
47 static struct setting_type setting_types
[0]
48 __table_start ( struct setting_type
, setting_types
);
49 static struct setting_type setting_types_end
[0]
50 __table_end ( struct setting_type
, setting_types
);
52 /** Registered settings applicators */
53 static struct settings_applicator settings_applicators
[0]
54 __table_start ( struct settings_applicator
, settings_applicators
);
55 static struct settings_applicator settings_applicators_end
[0]
56 __table_end ( struct settings_applicator
, settings_applicators
);
58 /******************************************************************************
60 * Registered settings blocks
62 ******************************************************************************
66 * Store value of simple setting
68 * @v options DHCP option block
69 * @v setting Setting to store
70 * @v data Setting data, or NULL to clear setting
71 * @v len Length of setting data
72 * @ret rc Return status code
74 int simple_settings_store ( struct settings
*settings
, struct setting
*setting
,
75 const void *data
, size_t len
) {
76 struct simple_settings
*simple
=
77 container_of ( settings
, struct simple_settings
, settings
);
78 return dhcpopt_extensible_store ( &simple
->dhcpopts
, setting
->tag
,
83 * Fetch value of simple setting
85 * @v options DHCP option block
86 * @v setting Setting to fetch
87 * @v data Buffer to fill with setting data
88 * @v len Length of buffer
89 * @ret len Length of setting data, or negative error
91 int simple_settings_fetch ( struct settings
*settings
, struct setting
*setting
,
92 void *data
, size_t len
) {
93 struct simple_settings
*simple
=
94 container_of ( settings
, struct simple_settings
, settings
);
95 return dhcpopt_fetch ( &simple
->dhcpopts
, setting
->tag
, data
, len
);
98 /** Simple settings operations */
99 struct settings_operations simple_settings_operations
= {
100 .store
= simple_settings_store
,
101 .fetch
= simple_settings_fetch
,
104 /** Root simple settings block */
105 struct simple_settings simple_settings_root
= {
110 LIST_HEAD_INIT ( simple_settings_root
.settings
.siblings
),
112 LIST_HEAD_INIT ( simple_settings_root
.settings
.children
),
113 .op
= &simple_settings_operations
,
117 /** Root settings block */
118 #define settings_root simple_settings_root.settings
123 * @ret rc Return status code
125 static int apply_settings ( void ) {
126 struct settings_applicator
*applicator
;
129 /* Call all settings applicators */
130 for ( applicator
= settings_applicators
;
131 applicator
< settings_applicators_end
; applicator
++ ) {
132 if ( ( rc
= applicator
->apply() ) != 0 ) {
133 DBG ( "Could not apply settings using applicator "
134 "%p: %s\n", applicator
, strerror ( rc
) );
143 * Reprioritise settings
145 * @v settings Settings block
147 * Reorders the settings block amongst its siblings according to its
150 static void reprioritise_settings ( struct settings
*settings
) {
151 struct settings
*parent
= settings
->parent
;
153 struct settings
*tmp
;
156 /* Stop when we reach the top of the tree */
160 /* Read priority, if present */
161 priority
= fetch_intz_setting ( settings
, &priority_setting
);
163 /* Remove from siblings list */
164 list_del ( &settings
->siblings
);
166 /* Reinsert after any existing blocks which have a higher priority */
167 list_for_each_entry ( tmp
, &parent
->children
, siblings
) {
168 tmp_priority
= fetch_intz_setting ( tmp
, &priority_setting
);
169 if ( priority
> tmp_priority
)
172 list_add_tail ( &settings
->siblings
, &tmp
->siblings
);
174 /* Recurse up the tree */
175 reprioritise_settings ( parent
);
179 * Register settings block
181 * @v settings Settings block
182 * @v parent Parent settings block, or NULL
183 * @ret rc Return status code
185 int register_settings ( struct settings
*settings
, struct settings
*parent
) {
186 struct settings
*old_settings
;
188 /* NULL parent => add to settings root */
189 assert ( settings
!= NULL
);
190 if ( parent
== NULL
)
191 parent
= &settings_root
;
193 /* Remove any existing settings with the same name */
194 if ( ( old_settings
= find_child_settings ( parent
, settings
->name
) ))
195 unregister_settings ( old_settings
);
197 /* Add to list of settings */
198 ref_get ( settings
->refcnt
);
199 ref_get ( parent
->refcnt
);
200 settings
->parent
= parent
;
201 list_add_tail ( &settings
->siblings
, &parent
->children
);
202 DBGC ( settings
, "Settings %p registered\n", settings
);
204 /* Fix up settings priority */
205 reprioritise_settings ( settings
);
207 /* Apply potentially-updated settings */
214 * Unregister settings block
216 * @v settings Settings block
218 void unregister_settings ( struct settings
*settings
) {
220 /* Remove from list of settings */
221 ref_put ( settings
->refcnt
);
222 ref_put ( settings
->parent
->refcnt
);
223 settings
->parent
= NULL
;
224 list_del ( &settings
->siblings
);
225 DBGC ( settings
, "Settings %p unregistered\n", settings
);
227 /* Apply potentially-updated settings */
232 * Find child named settings block
234 * @v parent Parent settings block
235 * @v name Name within this parent
236 * @ret settings Settings block, or NULL
238 struct settings
* find_child_settings ( struct settings
*parent
,
240 struct settings
*settings
;
243 /* NULL parent => add to settings root */
244 if ( parent
== NULL
)
245 parent
= &settings_root
;
247 /* Look for a child whose name matches the initial component */
248 list_for_each_entry ( settings
, &parent
->children
, siblings
) {
249 len
= strlen ( settings
->name
);
250 if ( strncmp ( name
, settings
->name
, len
) != 0 )
252 if ( name
[len
] == 0 )
254 if ( name
[len
] == '.' )
255 return find_child_settings ( settings
,
256 ( name
+ len
+ 1 ) );
263 * Find named settings block
266 * @ret settings Settings block, or NULL
268 struct settings
* find_settings ( const char *name
) {
270 /* If name is empty, use the root */
272 return &settings_root
;
274 return find_child_settings ( &settings_root
, name
);
277 /******************************************************************************
279 * Core settings routines
281 ******************************************************************************
285 * Store value of setting
287 * @v settings Settings block, or NULL
288 * @v setting Setting to store
289 * @v data Setting data, or NULL to clear setting
290 * @v len Length of setting data
291 * @ret rc Return status code
293 int store_setting ( struct settings
*settings
, struct setting
*setting
,
294 const void *data
, size_t len
) {
297 /* NULL settings implies storing into the global settings root */
299 settings
= &settings_root
;
302 if ( ( rc
= settings
->op
->store ( settings
, setting
,
306 /* Reprioritise settings if necessary */
307 if ( setting_cmp ( setting
, &priority_setting
) == 0 )
308 reprioritise_settings ( settings
);
310 /* If these settings are registered, apply potentially-updated
313 for ( ; settings
; settings
= settings
->parent
) {
314 if ( settings
== &settings_root
) {
315 if ( ( rc
= apply_settings() ) != 0 )
325 * Fetch value of setting
327 * @v settings Settings block, or NULL to search all blocks
328 * @v setting Setting to fetch
329 * @v data Buffer to fill with setting data
330 * @v len Length of buffer
331 * @ret len Length of setting data, or negative error
333 * The actual length of the setting will be returned even if
334 * the buffer was too small.
336 int fetch_setting ( struct settings
*settings
, struct setting
*setting
,
337 void *data
, size_t len
) {
338 struct settings
*child
;
341 /* Avoid returning uninitialised data on error */
342 memset ( data
, 0, len
);
344 /* NULL settings implies starting at the global settings root */
346 settings
= &settings_root
;
348 /* Try this block first */
349 if ( ( ret
= settings
->op
->fetch ( settings
, setting
,
353 /* Recurse into each child block in turn */
354 list_for_each_entry ( child
, &settings
->children
, siblings
) {
355 if ( ( ret
= fetch_setting ( child
, setting
,
364 * Fetch length of setting
366 * @v settings Settings block, or NULL to search all blocks
367 * @v setting Setting to fetch
368 * @ret len Length of setting data, or negative error
370 * This function can also be used as an existence check for the
373 int fetch_setting_len ( struct settings
*settings
, struct setting
*setting
) {
374 return fetch_setting ( settings
, setting
, NULL
, 0 );
378 * Fetch value of string setting
380 * @v settings Settings block, or NULL to search all blocks
381 * @v setting Setting to fetch
382 * @v data Buffer to fill with setting string data
383 * @v len Length of buffer
384 * @ret len Length of string setting, or negative error
386 * The resulting string is guaranteed to be correctly NUL-terminated.
387 * The returned length will be the length of the underlying setting
390 int fetch_string_setting ( struct settings
*settings
, struct setting
*setting
,
391 char *data
, size_t len
) {
392 memset ( data
, 0, len
);
393 return fetch_setting ( settings
, setting
, data
,
394 ( ( len
> 0 ) ? ( len
- 1 ) : 0 ) );
398 * Fetch value of string setting
400 * @v settings Settings block, or NULL to search all blocks
401 * @v setting Setting to fetch
402 * @v data Buffer to allocate and fill with setting string data
403 * @ret len Length of string setting, or negative error
405 * The resulting string is guaranteed to be correctly NUL-terminated.
406 * The returned length will be the length of the underlying setting
407 * data. The caller is responsible for eventually freeing the
410 int fetch_string_setting_copy ( struct settings
*settings
,
411 struct setting
*setting
,
416 len
= fetch_setting_len ( settings
, setting
);
420 *data
= malloc ( len
+ 1 );
424 fetch_string_setting ( settings
, setting
, *data
, ( len
+ 1 ) );
425 assert ( check_len
== len
);
430 * Fetch value of IPv4 address setting
432 * @v settings Settings block, or NULL to search all blocks
433 * @v setting Setting to fetch
434 * @v inp IPv4 address to fill in
435 * @ret len Length of setting, or negative error
437 int fetch_ipv4_setting ( struct settings
*settings
, struct setting
*setting
,
438 struct in_addr
*inp
) {
441 len
= fetch_setting ( settings
, setting
, inp
, sizeof ( *inp
) );
444 if ( len
< ( int ) sizeof ( *inp
) )
450 * Fetch value of signed integer setting
452 * @v settings Settings block, or NULL to search all blocks
453 * @v setting Setting to fetch
454 * @v value Integer value to fill in
455 * @ret len Length of setting, or negative error
457 int fetch_int_setting ( struct settings
*settings
, struct setting
*setting
,
460 uint8_t u8
[ sizeof ( long ) ];
461 int8_t s8
[ sizeof ( long ) ];
466 /* Avoid returning uninitialised data on error */
469 /* Fetch raw (network-ordered, variable-length) setting */
470 len
= fetch_setting ( settings
, setting
, &buf
, sizeof ( buf
) );
473 if ( len
> ( int ) sizeof ( buf
) )
476 /* Convert to host-ordered signed long */
477 *value
= ( ( buf
.s8
[0] >= 0 ) ? 0 : -1L );
478 for ( i
= 0 ; i
< len
; i
++ ) {
479 *value
= ( ( *value
<< 8 ) | buf
.u8
[i
] );
486 * Fetch value of unsigned integer setting
488 * @v settings Settings block, or NULL to search all blocks
489 * @v setting Setting to fetch
490 * @v value Integer value to fill in
491 * @ret len Length of setting, or negative error
493 int fetch_uint_setting ( struct settings
*settings
, struct setting
*setting
,
494 unsigned long *value
) {
498 /* Avoid returning uninitialised data on error */
501 /* Fetch as a signed long */
502 len
= fetch_int_setting ( settings
, setting
, &svalue
);
506 /* Mask off sign-extended bits */
507 *value
= ( svalue
& ( -1UL >> ( sizeof ( long ) - len
) ) );
513 * Fetch value of signed integer setting, or zero
515 * @v settings Settings block, or NULL to search all blocks
516 * @v setting Setting to fetch
517 * @ret value Setting value, or zero
519 long fetch_intz_setting ( struct settings
*settings
, struct setting
*setting
){
522 fetch_int_setting ( settings
, setting
, &value
);
527 * Fetch value of unsigned integer setting, or zero
529 * @v settings Settings block, or NULL to search all blocks
530 * @v setting Setting to fetch
531 * @ret value Setting value, or zero
533 unsigned long fetch_uintz_setting ( struct settings
*settings
,
534 struct setting
*setting
) {
537 fetch_uint_setting ( settings
, setting
, &value
);
542 * Fetch value of UUID setting
544 * @v settings Settings block, or NULL to search all blocks
545 * @v setting Setting to fetch
546 * @v uuid UUID to fill in
547 * @ret len Length of setting, or negative error
549 int fetch_uuid_setting ( struct settings
*settings
, struct setting
*setting
,
553 len
= fetch_setting ( settings
, setting
, uuid
, sizeof ( *uuid
) );
556 if ( len
!= sizeof ( *uuid
) )
562 * Compare two settings
564 * @v a Setting to compare
565 * @v b Setting to compare
566 * @ret 0 Settings are the same
567 * @ret non-zero Settings are not the same
569 int setting_cmp ( struct setting
*a
, struct setting
*b
) {
571 /* If the settings have tags, compare them */
572 if ( a
->tag
&& ( a
->tag
== b
->tag
) )
575 /* Otherwise, compare the names */
576 return strcmp ( a
->name
, b
->name
);
579 /******************************************************************************
581 * Formatted setting routines
583 ******************************************************************************
587 * Store value of typed setting
589 * @v settings Settings block
590 * @v setting Setting to store
591 * @v type Settings type
592 * @v value Formatted setting data, or NULL
593 * @ret rc Return status code
595 int storef_setting ( struct settings
*settings
, struct setting
*setting
,
596 const char *value
) {
598 /* NULL value implies deletion. Avoid imposing the burden of
599 * checking for NULL values on each typed setting's storef()
603 return delete_setting ( settings
, setting
);
605 return setting
->type
->storef ( settings
, setting
, value
);
612 * @ret setting Named setting, or NULL
614 static struct setting
* find_setting ( const char *name
) {
615 struct setting
*setting
;
617 for ( setting
= settings
; setting
< settings_end
; setting
++ ) {
618 if ( strcmp ( name
, setting
->name
) == 0 )
628 * @ret type Setting type, or NULL
630 static struct setting_type
* find_setting_type ( const char *name
) {
631 struct setting_type
*type
;
633 for ( type
= setting_types
; type
< setting_types_end
; type
++ ) {
634 if ( strcmp ( name
, type
->name
) == 0 )
643 * @v name Name of setting
644 * @v settings Settings block to fill in
645 * @v setting Setting to fill in
646 * @ret rc Return status code
648 * Interprets a name of the form
649 * "[settings_name/]tag_name[:type_name]" and fills in the appropriate
652 static int parse_setting_name ( const char *name
, struct settings
**settings
,
653 struct setting
*setting
) {
654 char tmp_name
[ strlen ( name
) + 1 ];
658 struct setting
*named_setting
;
662 *settings
= &settings_root
;
663 memset ( setting
, 0, sizeof ( *setting
) );
664 setting
->type
= &setting_type_hex
;
666 /* Split name into "[settings_name/]setting_name[:type_name]" */
667 memcpy ( tmp_name
, name
, sizeof ( tmp_name
) );
668 if ( ( setting_name
= strchr ( tmp_name
, '/' ) ) != NULL
) {
669 *(setting_name
++) = 0;
670 settings_name
= tmp_name
;
672 setting_name
= tmp_name
;
673 settings_name
= NULL
;
675 if ( ( type_name
= strchr ( setting_name
, ':' ) ) != NULL
)
678 /* Identify settings block, if specified */
679 if ( settings_name
) {
680 *settings
= find_settings ( settings_name
);
681 if ( *settings
== NULL
) {
682 DBG ( "Unrecognised settings block \"%s\" in \"%s\"\n",
683 settings_name
, name
);
688 /* Identify tag number */
689 if ( ( named_setting
= find_setting ( setting_name
) ) != NULL
) {
690 memcpy ( setting
, named_setting
, sizeof ( *setting
) );
692 /* Unrecognised name: try to interpret as a tag number */
695 setting
->tag
= ( ( setting
->tag
<< 8 ) |
696 strtoul ( tmp
, &tmp
, 0 ) );
700 DBG ( "Invalid setting \"%s\" in \"%s\"\n",
701 setting_name
, name
);
706 setting
->tag
|= (*settings
)->tag_magic
;
709 /* Identify setting type, if specified */
711 setting
->type
= find_setting_type ( type_name
);
712 if ( setting
->type
== NULL
) {
713 DBG ( "Invalid setting type \"%s\" in \"%s\"\n",
723 * Parse and store value of named setting
725 * @v name Name of setting
726 * @v value Formatted setting data, or NULL
727 * @ret rc Return status code
729 int storef_named_setting ( const char *name
, const char *value
) {
730 struct settings
*settings
;
731 struct setting setting
;
734 if ( ( rc
= parse_setting_name ( name
, &settings
, &setting
) ) != 0 )
736 return storef_setting ( settings
, &setting
, value
);
740 * Fetch and format value of named setting
742 * @v name Name of setting
743 * @v buf Buffer to contain formatted value
744 * @v len Length of buffer
745 * @ret len Length of formatted value, or negative error
747 int fetchf_named_setting ( const char *name
, char *buf
, size_t len
) {
748 struct settings
*settings
;
749 struct setting setting
;
752 if ( ( rc
= parse_setting_name ( name
, &settings
, &setting
) ) != 0 )
754 return fetchf_setting ( settings
, &setting
, buf
, len
);
757 /******************************************************************************
761 ******************************************************************************
765 * Parse and store value of string setting
767 * @v settings Settings block
768 * @v setting Setting to store
769 * @v value Formatted setting data
770 * @ret rc Return status code
772 static int storef_string ( struct settings
*settings
, struct setting
*setting
,
773 const char *value
) {
774 return store_setting ( settings
, setting
, value
, strlen ( value
) );
778 * Fetch and format value of string setting
780 * @v settings Settings block, or NULL to search all blocks
781 * @v setting Setting to fetch
782 * @v buf Buffer to contain formatted value
783 * @v len Length of buffer
784 * @ret len Length of formatted value, or negative error
786 static int fetchf_string ( struct settings
*settings
, struct setting
*setting
,
787 char *buf
, size_t len
) {
788 return fetch_string_setting ( settings
, setting
, buf
, len
);
791 /** A string setting type */
792 struct setting_type setting_type_string __setting_type
= {
794 .storef
= storef_string
,
795 .fetchf
= fetchf_string
,
799 * Parse and store value of URI-encoded string setting
801 * @v settings Settings block
802 * @v setting Setting to store
803 * @v value Formatted setting data
804 * @ret rc Return status code
806 static int storef_uristring ( struct settings
*settings
,
807 struct setting
*setting
,
808 const char *value
) {
809 char buf
[ strlen ( value
) + 1 ]; /* Decoding never expands string */
812 len
= uri_decode ( value
, buf
, sizeof ( buf
) );
813 return store_setting ( settings
, setting
, buf
, len
);
817 * Fetch and format value of URI-encoded string setting
819 * @v settings Settings block, or NULL to search all blocks
820 * @v setting Setting to fetch
821 * @v buf Buffer to contain formatted value
822 * @v len Length of buffer
823 * @ret len Length of formatted value, or negative error
825 static int fetchf_uristring ( struct settings
*settings
,
826 struct setting
*setting
,
827 char *buf
, size_t len
) {
830 /* We need to always retrieve the full raw string to know the
831 * length of the encoded string.
833 raw_len
= fetch_setting ( settings
, setting
, NULL
, 0 );
838 char raw_buf
[ raw_len
+ 1 ];
840 fetch_string_setting ( settings
, setting
, raw_buf
,
841 sizeof ( raw_buf
) );
842 return uri_encode ( raw_buf
, buf
, len
);
846 /** A URI-encoded string setting type */
847 struct setting_type setting_type_uristring __setting_type
= {
849 .storef
= storef_uristring
,
850 .fetchf
= fetchf_uristring
,
854 * Parse and store value of IPv4 address setting
856 * @v settings Settings block
857 * @v setting Setting to store
858 * @v value Formatted setting data
859 * @ret rc Return status code
861 static int storef_ipv4 ( struct settings
*settings
, struct setting
*setting
,
862 const char *value
) {
865 if ( inet_aton ( value
, &ipv4
) == 0 )
867 return store_setting ( settings
, setting
, &ipv4
, sizeof ( ipv4
) );
871 * Fetch and format value of IPv4 address setting
873 * @v settings Settings block, or NULL to search all blocks
874 * @v setting Setting to fetch
875 * @v buf Buffer to contain formatted value
876 * @v len Length of buffer
877 * @ret len Length of formatted value, or negative error
879 static int fetchf_ipv4 ( struct settings
*settings
, struct setting
*setting
,
880 char *buf
, size_t len
) {
884 if ( ( raw_len
= fetch_ipv4_setting ( settings
, setting
, &ipv4
) ) < 0)
886 return snprintf ( buf
, len
, "%s", inet_ntoa ( ipv4
) );
889 /** An IPv4 address setting type */
890 struct setting_type setting_type_ipv4 __setting_type
= {
892 .storef
= storef_ipv4
,
893 .fetchf
= fetchf_ipv4
,
897 * Parse and store value of integer setting
899 * @v settings Settings block
900 * @v setting Setting to store
901 * @v value Formatted setting data
902 * @v size Integer size, in bytes
903 * @ret rc Return status code
905 static int storef_int ( struct settings
*settings
, struct setting
*setting
,
906 const char *value
, unsigned int size
) {
913 u
.num
= htonl ( strtoul ( value
, &endp
, 0 ) );
916 return store_setting ( settings
, setting
,
917 &u
.bytes
[ sizeof ( u
) - size
], size
);
921 * Parse and store value of 8-bit integer setting
923 * @v settings Settings block
924 * @v setting Setting to store
925 * @v value Formatted setting data
926 * @v size Integer size, in bytes
927 * @ret rc Return status code
929 static int storef_int8 ( struct settings
*settings
, struct setting
*setting
,
930 const char *value
) {
931 return storef_int ( settings
, setting
, value
, 1 );
935 * Parse and store value of 16-bit integer setting
937 * @v settings Settings block
938 * @v setting Setting to store
939 * @v value Formatted setting data
940 * @v size Integer size, in bytes
941 * @ret rc Return status code
943 static int storef_int16 ( struct settings
*settings
, struct setting
*setting
,
944 const char *value
) {
945 return storef_int ( settings
, setting
, value
, 2 );
949 * Parse and store value of 32-bit integer setting
951 * @v settings Settings block
952 * @v setting Setting to store
953 * @v value Formatted setting data
954 * @v size Integer size, in bytes
955 * @ret rc Return status code
957 static int storef_int32 ( struct settings
*settings
, struct setting
*setting
,
958 const char *value
) {
959 return storef_int ( settings
, setting
, value
, 4 );
963 * Fetch and format value of signed integer setting
965 * @v settings Settings block, or NULL to search all blocks
966 * @v setting Setting to fetch
967 * @v buf Buffer to contain formatted value
968 * @v len Length of buffer
969 * @ret len Length of formatted value, or negative error
971 static int fetchf_int ( struct settings
*settings
, struct setting
*setting
,
972 char *buf
, size_t len
) {
976 if ( ( rc
= fetch_int_setting ( settings
, setting
, &value
) ) < 0 )
978 return snprintf ( buf
, len
, "%ld", value
);
982 * Fetch and format value of unsigned integer setting
984 * @v settings Settings block, or NULL to search all blocks
985 * @v setting Setting to fetch
986 * @v buf Buffer to contain formatted value
987 * @v len Length of buffer
988 * @ret len Length of formatted value, or negative error
990 static int fetchf_uint ( struct settings
*settings
, struct setting
*setting
,
991 char *buf
, size_t len
) {
995 if ( ( rc
= fetch_uint_setting ( settings
, setting
, &value
) ) < 0 )
997 return snprintf ( buf
, len
, "%#lx", value
);
1000 /** A signed 8-bit integer setting type */
1001 struct setting_type setting_type_int8 __setting_type
= {
1003 .storef
= storef_int8
,
1004 .fetchf
= fetchf_int
,
1007 /** A signed 16-bit integer setting type */
1008 struct setting_type setting_type_int16 __setting_type
= {
1010 .storef
= storef_int16
,
1011 .fetchf
= fetchf_int
,
1014 /** A signed 32-bit integer setting type */
1015 struct setting_type setting_type_int32 __setting_type
= {
1017 .storef
= storef_int32
,
1018 .fetchf
= fetchf_int
,
1021 /** An unsigned 8-bit integer setting type */
1022 struct setting_type setting_type_uint8 __setting_type
= {
1024 .storef
= storef_int8
,
1025 .fetchf
= fetchf_uint
,
1028 /** An unsigned 16-bit integer setting type */
1029 struct setting_type setting_type_uint16 __setting_type
= {
1031 .storef
= storef_int16
,
1032 .fetchf
= fetchf_uint
,
1035 /** An unsigned 32-bit integer setting type */
1036 struct setting_type setting_type_uint32 __setting_type
= {
1038 .storef
= storef_int32
,
1039 .fetchf
= fetchf_uint
,
1043 * Parse and store value of hex string setting
1045 * @v settings Settings block
1046 * @v setting Setting to store
1047 * @v value Formatted setting data
1048 * @ret rc Return status code
1050 static int storef_hex ( struct settings
*settings
, struct setting
*setting
,
1051 const char *value
) {
1052 char *ptr
= ( char * ) value
;
1053 uint8_t bytes
[ strlen ( value
) ]; /* cannot exceed strlen(value) */
1054 unsigned int len
= 0;
1057 bytes
[len
++] = strtoul ( ptr
, &ptr
, 16 );
1060 return store_setting ( settings
, setting
, bytes
, len
);
1071 * Fetch and format value of hex string setting
1073 * @v settings Settings block, or NULL to search all blocks
1074 * @v setting Setting to fetch
1075 * @v buf Buffer to contain formatted value
1076 * @v len Length of buffer
1077 * @ret len Length of formatted value, or negative error
1079 static int fetchf_hex ( struct settings
*settings
, struct setting
*setting
,
1080 char *buf
, size_t len
) {
1086 raw_len
= fetch_setting_len ( settings
, setting
);
1091 uint8_t raw
[raw_len
];
1093 check_len
= fetch_setting ( settings
, setting
, raw
,
1095 if ( check_len
< 0 )
1097 assert ( check_len
== raw_len
);
1100 buf
[0] = 0; /* Ensure that a terminating NUL exists */
1101 for ( i
= 0 ; i
< raw_len
; i
++ ) {
1102 used
+= ssnprintf ( ( buf
+ used
), ( len
- used
),
1103 "%s%02x", ( used
? ":" : "" ),
1110 /** A hex-string setting */
1111 struct setting_type setting_type_hex __setting_type
= {
1113 .storef
= storef_hex
,
1114 .fetchf
= fetchf_hex
,
1118 * Parse and store value of UUID setting
1120 * @v settings Settings block
1121 * @v setting Setting to store
1122 * @v value Formatted setting data
1123 * @ret rc Return status code
1125 static int storef_uuid ( struct settings
*settings __unused
,
1126 struct setting
*setting __unused
,
1127 const char *value __unused
) {
1132 * Fetch and format value of UUID setting
1134 * @v settings Settings block, or NULL to search all blocks
1135 * @v setting Setting to fetch
1136 * @v buf Buffer to contain formatted value
1137 * @v len Length of buffer
1138 * @ret len Length of formatted value, or negative error
1140 static int fetchf_uuid ( struct settings
*settings
, struct setting
*setting
,
1141 char *buf
, size_t len
) {
1145 if ( ( raw_len
= fetch_uuid_setting ( settings
, setting
, &uuid
) ) < 0)
1147 return snprintf ( buf
, len
, "%s", uuid_ntoa ( &uuid
) );
1150 /** UUID setting type */
1151 struct setting_type setting_type_uuid __setting_type
= {
1153 .storef
= storef_uuid
,
1154 .fetchf
= fetchf_uuid
,
1157 /******************************************************************************
1161 ******************************************************************************
1164 /** Hostname setting */
1165 struct setting hostname_setting __setting
= {
1167 .description
= "Host name",
1168 .tag
= DHCP_HOST_NAME
,
1169 .type
= &setting_type_string
,
1172 /** Filename setting */
1173 struct setting filename_setting __setting
= {
1175 .description
= "Boot filename",
1176 .tag
= DHCP_BOOTFILE_NAME
,
1177 .type
= &setting_type_string
,
1180 /** Root path setting */
1181 struct setting root_path_setting __setting
= {
1182 .name
= "root-path",
1183 .description
= "NFS/iSCSI root path",
1184 .tag
= DHCP_ROOT_PATH
,
1185 .type
= &setting_type_string
,
1188 /** Username setting */
1189 struct setting username_setting __setting
= {
1191 .description
= "User name",
1192 .tag
= DHCP_EB_USERNAME
,
1193 .type
= &setting_type_string
,
1196 /** Password setting */
1197 struct setting password_setting __setting
= {
1199 .description
= "Password",
1200 .tag
= DHCP_EB_PASSWORD
,
1201 .type
= &setting_type_string
,
1204 /** Priority setting */
1205 struct setting priority_setting __setting
= {
1207 .description
= "Priority of these settings",
1208 .tag
= DHCP_EB_PRIORITY
,
1209 .type
= &setting_type_int8
,