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/settings.h>
34 * Configuration settings
38 /** Registered setting types */
39 static struct setting_type setting_types[0]
40 __table_start ( struct setting_type, setting_types );
41 static struct setting_type setting_types_end[0]
42 __table_end ( struct setting_type, setting_types );
44 /** Registered named settings */
45 static struct named_setting named_settings[0]
46 __table_start ( struct named_setting, named_settings );
47 static struct named_setting named_settings_end[0]
48 __table_end ( struct named_setting, named_settings );
50 /** Registered settings applicators */
51 static struct settings_applicator settings_applicators[0]
52 __table_start ( struct settings_applicator, settings_applicators );
53 static struct settings_applicator settings_applicators_end[0]
54 __table_end ( struct settings_applicator, settings_applicators );
57 * Obtain printable version of a settings tag number
59 * @v tag Settings tag number
60 * @ret name String representation of the tag
62 static inline char * setting_tag_name ( unsigned int tag ) {
65 if ( DHCP_IS_ENCAP_OPT ( tag ) ) {
66 snprintf ( name, sizeof ( name ), "%d.%d",
67 DHCP_ENCAPSULATOR ( tag ),
68 DHCP_ENCAPSULATED ( tag ) );
70 snprintf ( name, sizeof ( name ), "%d", tag );
75 /******************************************************************************
77 * Registered settings blocks
79 ******************************************************************************
82 // Dummy routine just for testing
83 int simple_settings_store ( struct settings *settings, unsigned int tag,
84 const void *data, size_t len ) {
85 DBGC ( settings, "Settings %p: store %s to:\n",
86 settings, setting_tag_name ( tag ) );
87 DBGC_HD ( settings, data, len );
91 // Dummy routine just for testing
92 int simple_settings_fetch ( struct settings *settings, unsigned int tag,
93 void *data, size_t len ) {
96 DBGC ( settings, "Settings %p: fetch %s\n",
97 settings, setting_tag_name ( tag ) );
98 for ( i = 0 ; i < len ; i++ )
99 *( ( ( uint8_t * ) data ) + i ) = i;
100 return ( len ? len : 8 );
103 /** Simple settings operations */
104 struct settings_operations simple_settings_operations = {
105 .store = simple_settings_store,
106 .fetch = simple_settings_fetch,
109 /** Root settings block */
110 struct settings settings_root = {
113 .siblings = LIST_HEAD_INIT ( settings_root.siblings ),
114 .children = LIST_HEAD_INIT ( settings_root.children ),
115 .op = &simple_settings_operations,
121 * @ret rc Return status code
123 static int apply_settings ( void ) {
124 struct settings_applicator *applicator;
127 /* Call all settings applicators */
128 for ( applicator = settings_applicators ;
129 applicator < settings_applicators_end ; applicator++ ) {
130 if ( ( rc = applicator->apply() ) != 0 ) {
131 DBG ( "Could not apply settings using applicator "
132 "%p: %s\n", applicator, strerror ( rc ) );
141 * Reprioritise settings
143 * @v settings Settings block
145 * Reorders the settings block amongst its siblings according to its
148 static void reprioritise_settings ( struct settings *settings ) {
149 struct settings *parent = settings->parent;
151 struct settings *tmp;
154 /* Stop when we reach the top of the tree */
158 /* Read priority, if present */
159 priority = fetch_intz_setting ( settings, DHCP_EB_PRIORITY );
161 /* Remove from siblings list */
162 list_del ( &settings->siblings );
164 /* Reinsert after any existing blocks which have a higher priority */
165 list_for_each_entry ( tmp, &parent->children, siblings ) {
166 tmp_priority = fetch_intz_setting ( tmp, DHCP_EB_PRIORITY );
167 if ( priority > tmp_priority )
170 list_add_tail ( &settings->siblings, &tmp->siblings );
172 /* Recurse up the tree */
173 reprioritise_settings ( parent );
177 * Register settings block
179 * @v settings Settings block
180 * @v parent Parent settings block, or NULL
181 * @ret rc Return status code
183 int register_settings ( struct settings *settings, struct settings *parent ) {
185 /* NULL parent => add to settings root */
186 assert ( settings != NULL );
187 if ( parent == NULL )
188 parent = &settings_root;
190 /* Add to list of settings */
191 ref_get ( settings->refcnt );
192 ref_get ( parent->refcnt );
193 settings->parent = parent;
194 list_add_tail ( &settings->siblings, &parent->children );
195 DBGC ( settings, "Settings %p registered\n", settings );
197 /* Fix up settings priority */
198 reprioritise_settings ( settings );
200 /* Apply potentially-updated settings */
207 * Unregister settings block
209 * @v settings Settings block
211 void unregister_settings ( struct settings *settings ) {
213 /* Remove from list of settings */
214 ref_put ( settings->refcnt );
215 ref_put ( settings->parent->refcnt );
216 list_del ( &settings->siblings );
217 DBGC ( settings, "Settings %p unregistered\n", settings );
219 /* Apply potentially-updated settings */
224 * Find child named settings block
226 * @v parent Parent settings block
227 * @v name Name within this parent
228 * @ret settings Settings block, or NULL
230 struct settings * find_child_settings ( struct settings *parent,
232 struct settings *settings;
235 /* Look for a child whose name matches the initial component */
236 list_for_each_entry ( settings, &parent->children, siblings ) {
237 len = strlen ( settings->name );
238 if ( strncmp ( name, settings->name, len ) != 0 )
240 if ( name[len] == 0 )
242 if ( name[len] == '.' )
243 return find_child_settings ( settings,
244 ( name + len + 1 ) );
251 * Find named settings block
254 * @ret settings Settings block, or NULL
256 struct settings * find_settings ( const char *name ) {
258 /* If name is empty, use the root */
260 return &settings_root;
262 return find_child_settings ( &settings_root, name );
265 /******************************************************************************
267 * Core settings routines
269 ******************************************************************************
273 * Store value of setting
275 * @v settings Settings block
276 * @v tag Setting tag number
277 * @v data Setting data, or NULL to clear setting
278 * @v len Length of setting data
279 * @ret rc Return status code
281 int store_setting ( struct settings *settings, unsigned int tag,
282 const void *data, size_t len ) {
286 if ( ( rc = settings->op->store ( settings, tag, data, len ) ) != 0 )
289 /* Reprioritise settings if necessary */
290 if ( tag == DHCP_EB_PRIORITY )
291 reprioritise_settings ( settings );
293 /* Apply potentially-updated setting */
294 if ( ( rc = apply_settings() ) != 0 )
301 * Fetch value of setting
303 * @v settings Settings block, or NULL to search all blocks
304 * @v tag Setting tag number
305 * @v data Buffer to fill with setting data
306 * @v len Length of buffer
307 * @ret len Length of setting data, or negative error
309 * The actual length of the setting will be returned even if
310 * the buffer was too small.
312 int fetch_setting ( struct settings *settings, unsigned int tag,
313 void *data, size_t len ) {
314 struct settings *child;
317 /* NULL settings implies starting at the global settings root */
319 settings = &settings_root;
321 /* Try this block first */
322 if ( ( ret = settings->op->fetch ( settings, tag, data, len ) ) >= 0)
325 /* Recurse into each child block in turn */
326 list_for_each_entry ( child, &settings->children, siblings ) {
327 if ( ( ret = fetch_setting ( settings, tag, data, len ) ) >= 0)
335 * Fetch length of setting
337 * @v settings Settings block, or NULL to search all blocks
338 * @v tag Setting tag number
339 * @ret len Length of setting data, or negative error
341 * This function can also be used as an existence check for the
344 int fetch_setting_len ( struct settings *settings, unsigned int tag ) {
345 return fetch_setting ( settings, tag, NULL, 0 );
349 * Fetch value of string setting
351 * @v settings Settings block, or NULL to search all blocks
352 * @v tag Setting tag number
353 * @v data Buffer to fill with setting string data
354 * @v len Length of buffer
355 * @ret len Length of string setting, or negative error
357 * The resulting string is guaranteed to be correctly NUL-terminated.
358 * The returned length will be the length of the underlying setting
361 int fetch_string_setting ( struct settings *settings, unsigned int tag,
362 char *data, size_t len ) {
363 memset ( data, 0, len );
364 return fetch_setting ( settings, tag, data, ( len - 1 ) );
368 * Fetch value of IPv4 address setting
370 * @v settings Settings block, or NULL to search all blocks
371 * @v tag Setting tag number
372 * @v inp IPv4 address to fill in
373 * @ret len Length of setting, or negative error
375 int fetch_ipv4_setting ( struct settings *settings, unsigned int tag,
376 struct in_addr *inp ) {
379 len = fetch_setting ( settings, tag, inp, sizeof ( *inp ) );
382 if ( len < ( int ) sizeof ( *inp ) )
388 * Fetch value of signed integer setting
390 * @v settings Settings block, or NULL to search all blocks
391 * @v tag Setting tag number
392 * @v value Integer value to fill in
393 * @ret len Length of setting, or negative error
395 int fetch_int_setting ( struct settings *settings, unsigned int tag,
399 uint8_t u8[ sizeof ( long ) ];
400 int8_t s8[ sizeof ( long ) ];
406 len = fetch_setting ( settings, tag, &buf, sizeof ( buf ) );
409 if ( len > ( int ) sizeof ( buf ) )
412 *value = ( ( buf.s8[0] >= 0 ) ? 0 : -1L );
413 for ( i = 0 ; i < len ; i++ ) {
414 *value = ( ( *value << 8 ) | buf.u8[i] );
421 * Fetch value of unsigned integer setting
423 * @v settings Settings block, or NULL to search all blocks
424 * @v tag Setting tag number
425 * @v value Integer value to fill in
426 * @ret len Length of setting, or negative error
428 int fetch_uint_setting ( struct settings *settings, unsigned int tag,
429 unsigned long *value ) {
433 len = fetch_int_setting ( settings, tag, &svalue );
437 *value = ( svalue & ( -1UL >> ( sizeof ( long ) - len ) ) );
443 * Fetch value of signed integer setting, or zero
445 * @v settings Settings block, or NULL to search all blocks
446 * @v tag Setting tag number
447 * @ret value Setting value, or zero
449 long fetch_intz_setting ( struct settings *settings, unsigned int tag ) {
452 fetch_int_setting ( settings, tag, &value );
457 * Fetch value of unsigned integer setting, or zero
459 * @v settings Settings block, or NULL to search all blocks
460 * @v tag Setting tag number
461 * @ret value Setting value, or zero
463 unsigned long fetch_uintz_setting ( struct settings *settings,
465 unsigned long value = 0;
467 fetch_uint_setting ( settings, tag, &value );
471 /******************************************************************************
473 * Named and typed setting routines
475 ******************************************************************************
479 * Store value of typed setting
481 * @v settings Settings block
482 * @v tag Setting tag number
483 * @v type Settings type
484 * @v value Formatted setting data, or NULL
485 * @ret rc Return status code
487 int store_typed_setting ( struct settings *settings,
488 unsigned int tag, struct setting_type *type,
489 const char *value ) {
491 /* NULL value implies deletion. Avoid imposing the burden of
492 * checking for NULL values on each typed setting's storef()
496 return delete_setting ( settings, tag );
498 return type->storef ( settings, tag, value );
505 * @ret setting Named setting, or NULL
507 static struct named_setting * find_named_setting ( const char *name ) {
508 struct named_setting *setting;
510 for ( setting = named_settings ; setting < named_settings_end ;
512 if ( strcmp ( name, setting->name ) == 0 )
522 * @ret type Setting type, or NULL
524 static struct setting_type * find_setting_type ( const char *name ) {
525 struct setting_type *type;
527 for ( type = setting_types ; type < setting_types_end ; type++ ) {
528 if ( strcmp ( name, type->name ) == 0 )
537 * @v name Name of setting
538 * @ret settings Settings block, or NULL
539 * @ret tag Setting tag number
540 * @ret type Setting type
541 * @ret rc Return status code
543 * Interprets a name of the form
544 * "[settings_name/]tag_name[:type_name]" and fills in the appropriate
547 static int parse_setting_name ( const char *name, struct settings **settings,
549 struct setting_type **type ) {
550 char tmp_name[ strlen ( name ) + 1 ];
554 struct named_setting *named_setting;
558 *settings = &settings_root;
560 *type = &setting_type_hex;
562 /* Split name into "[settings_name/]tag_name[:type_name]" */
563 memcpy ( tmp_name, name, sizeof ( tmp_name ) );
564 if ( ( tag_name = strchr ( tmp_name, '/' ) ) != NULL ) {
566 settings_name = tmp_name;
569 settings_name = NULL;
571 if ( ( type_name = strchr ( tag_name, ':' ) ) != NULL )
574 /* Identify settings block, if specified */
575 if ( settings_name ) {
576 *settings = find_settings ( settings_name );
577 if ( *settings == NULL ) {
578 DBG ( "Unrecognised settings block \"%s\" in \"%s\"\n",
579 settings_name, name );
584 /* Identify tag number */
585 if ( ( named_setting = find_named_setting ( tag_name ) ) != NULL ) {
586 *tag = named_setting->tag;
587 *type = named_setting->type;
589 /* Unrecognised name: try to interpret as a tag number */
592 *tag = ( ( *tag << 8 ) | strtoul ( tmp, &tmp, 0 ) );
596 DBG ( "Invalid tag number \"%s\" in \"%s\"\n",
604 /* Identify setting type, if specified */
606 *type = find_setting_type ( type_name );
607 if ( *type == NULL ) {
608 DBG ( "Invalid setting type \"%s\" in \"%s\"\n",
618 * Parse and store value of named setting
620 * @v name Name of setting
621 * @v value Formatted setting data, or NULL
622 * @ret rc Return status code
624 int store_named_setting ( const char *name, const char *value ) {
625 struct settings *settings;
627 struct setting_type *type;
630 if ( ( rc = parse_setting_name ( name, &settings, &tag,
633 return store_typed_setting ( settings, tag, type, value );
637 * Fetch and format value of named setting
639 * @v name Name of setting
640 * @v buf Buffer to contain formatted value
641 * @v len Length of buffer
642 * @ret len Length of formatted value, or negative error
644 int fetch_named_setting ( const char *name, char *buf, size_t len ) {
645 struct settings *settings;
647 struct setting_type *type;
650 if ( ( rc = parse_setting_name ( name, &settings, &tag,
653 return fetch_typed_setting ( settings, tag, type, buf, len );
656 /******************************************************************************
660 ******************************************************************************
664 * Parse and store value of string setting
666 * @v settings Settings block
667 * @v tag Setting tag number
668 * @v value Formatted setting data
669 * @ret rc Return status code
671 static int storef_string ( struct settings *settings, unsigned int tag,
672 const char *value ) {
673 return store_setting ( settings, tag, value, strlen ( value ) );
677 * Fetch and format value of string setting
679 * @v settings Settings block, or NULL to search all blocks
680 * @v tag Setting tag number
681 * @v buf Buffer to contain formatted value
682 * @v len Length of buffer
683 * @ret len Length of formatted value, or negative error
685 static int fetchf_string ( struct settings *settings, unsigned int tag,
686 char *buf, size_t len ) {
687 return fetch_string_setting ( settings, tag, buf, len );
690 /** A string setting type */
691 struct setting_type setting_type_string __setting_type = {
693 .storef = storef_string,
694 .fetchf = fetchf_string,
698 * Parse and store value of IPv4 address setting
700 * @v settings Settings block
701 * @v tag Setting tag number
702 * @v value Formatted setting data
703 * @ret rc Return status code
705 static int storef_ipv4 ( struct settings *settings, unsigned int tag,
706 const char *value ) {
709 if ( inet_aton ( value, &ipv4 ) == 0 )
711 return store_setting ( settings, tag, &ipv4, sizeof ( ipv4 ) );
715 * Fetch and format value of IPv4 address setting
717 * @v settings Settings block, or NULL to search all blocks
718 * @v tag Setting tag number
719 * @v buf Buffer to contain formatted value
720 * @v len Length of buffer
721 * @ret len Length of formatted value, or negative error
723 static int fetchf_ipv4 ( struct settings *settings, unsigned int tag,
724 char *buf, size_t len ) {
728 if ( ( rc = fetch_ipv4_setting ( settings, tag, &ipv4 ) ) < 0 )
730 return snprintf ( buf, len, inet_ntoa ( ipv4 ) );
733 /** An IPv4 address setting type */
734 struct setting_type setting_type_ipv4 __setting_type = {
736 .storef = storef_ipv4,
737 .fetchf = fetchf_ipv4,
741 * Parse and store value of integer setting
743 * @v settings Settings block
744 * @v tag Setting tag number
745 * @v value Formatted setting data
746 * @v size Integer size, in bytes
747 * @ret rc Return status code
749 static int storef_int ( struct settings *settings, unsigned int tag,
750 const char *value, unsigned int size ) {
757 u.num = htonl ( strtoul ( value, &endp, 0 ) );
760 return store_setting ( settings, tag,
761 &u.bytes[ sizeof ( u ) - size ], size );
765 * Parse and store value of 8-bit integer setting
767 * @v settings Settings block
768 * @v tag Setting tag number
769 * @v value Formatted setting data
770 * @v size Integer size, in bytes
771 * @ret rc Return status code
773 static int storef_int8 ( struct settings *settings, unsigned int tag,
774 const char *value ) {
775 return storef_int ( settings, tag, value, 1 );
779 * Parse and store value of 16-bit integer setting
781 * @v settings Settings block
782 * @v tag Setting tag number
783 * @v value Formatted setting data
784 * @v size Integer size, in bytes
785 * @ret rc Return status code
787 static int storef_int16 ( struct settings *settings, unsigned int tag,
788 const char *value ) {
789 return storef_int ( settings, tag, value, 2 );
793 * Parse and store value of 32-bit integer setting
795 * @v settings Settings block
796 * @v tag Setting tag number
797 * @v value Formatted setting data
798 * @v size Integer size, in bytes
799 * @ret rc Return status code
801 static int storef_int32 ( struct settings *settings, unsigned int tag,
802 const char *value ) {
803 return storef_int ( settings, tag, value, 4 );
807 * Fetch and format value of signed integer setting
809 * @v settings Settings block, or NULL to search all blocks
810 * @v tag Setting tag number
811 * @v buf Buffer to contain formatted value
812 * @v len Length of buffer
813 * @ret len Length of formatted value, or negative error
815 static int fetchf_int ( struct settings *settings, unsigned int tag,
816 char *buf, size_t len ) {
820 if ( ( rc = fetch_int_setting ( settings, tag, &value ) ) < 0 )
822 return snprintf ( buf, len, "%ld", value );
826 * Fetch and format value of unsigned integer setting
828 * @v settings Settings block, or NULL to search all blocks
829 * @v tag Setting tag number
830 * @v buf Buffer to contain formatted value
831 * @v len Length of buffer
832 * @ret len Length of formatted value, or negative error
834 static int fetchf_uint ( struct settings *settings, unsigned int tag,
835 char *buf, size_t len ) {
839 if ( ( rc = fetch_uint_setting ( settings, tag, &value ) ) < 0 )
841 return snprintf ( buf, len, "%#lx", value );
844 /** A signed 8-bit integer setting type */
845 struct setting_type setting_type_int8 __setting_type = {
847 .storef = storef_int8,
848 .fetchf = fetchf_int,
851 /** A signed 16-bit integer setting type */
852 struct setting_type setting_type_int16 __setting_type = {
854 .storef = storef_int16,
855 .fetchf = fetchf_int,
858 /** A signed 32-bit integer setting type */
859 struct setting_type setting_type_int32 __setting_type = {
861 .storef = storef_int32,
862 .fetchf = fetchf_int,
865 /** An unsigned 8-bit integer setting type */
866 struct setting_type setting_type_uint8 __setting_type = {
868 .storef = storef_int8,
869 .fetchf = fetchf_uint,
872 /** An unsigned 16-bit integer setting type */
873 struct setting_type setting_type_uint16 __setting_type = {
875 .storef = storef_int16,
876 .fetchf = fetchf_uint,
879 /** An unsigned 32-bit integer setting type */
880 struct setting_type setting_type_uint32 __setting_type = {
882 .storef = storef_int32,
883 .fetchf = fetchf_uint,
887 * Parse and store value of hex string setting
889 * @v settings Settings block
890 * @v tag Setting tag number
891 * @v value Formatted setting data
892 * @ret rc Return status code
894 static int storef_hex ( struct settings *settings, unsigned int tag,
895 const char *value ) {
896 char *ptr = ( char * ) value;
897 uint8_t bytes[ strlen ( value ) ]; /* cannot exceed strlen(value) */
898 unsigned int len = 0;
901 bytes[len++] = strtoul ( ptr, &ptr, 16 );
904 return store_setting ( settings, tag, bytes, len );
915 * Fetch and format value of hex string setting
917 * @v settings Settings block, or NULL to search all blocks
918 * @v tag Setting tag number
919 * @v buf Buffer to contain formatted value
920 * @v len Length of buffer
921 * @ret len Length of formatted value, or negative error
923 static int fetchf_hex ( struct settings *settings, unsigned int tag,
924 char *buf, size_t len ) {
930 raw_len = fetch_setting_len ( settings, tag );
935 uint8_t raw[raw_len];
937 check_len = fetch_setting ( settings, tag, raw, sizeof (raw) );
938 assert ( check_len == raw_len );
941 buf[0] = 0; /* Ensure that a terminating NUL exists */
942 for ( i = 0 ; i < raw_len ; i++ ) {
943 used += ssnprintf ( ( buf + used ), ( len - used ),
944 "%s%02x", ( used ? ":" : "" ),
951 /** A hex-string setting */
952 struct setting_type setting_type_hex __setting_type = {
954 .storef = storef_hex,
955 .fetchf = fetchf_hex,
958 /******************************************************************************
962 ******************************************************************************
965 /** Some basic setting definitions */
966 struct named_setting basic_named_settings[] __named_setting = {
969 .description = "IPv4 address",
970 .tag = DHCP_EB_YIADDR,
971 .type = &setting_type_ipv4,
975 .description = "IPv4 subnet mask",
976 .tag = DHCP_SUBNET_MASK,
977 .type = &setting_type_ipv4,
981 .description = "Default gateway",
983 .type = &setting_type_ipv4,
987 .description = "DNS server",
988 .tag = DHCP_DNS_SERVERS,
989 .type = &setting_type_ipv4,
993 .description = "Host name",
994 .tag = DHCP_HOST_NAME,
995 .type = &setting_type_string,
999 .description = "Boot filename",
1000 .tag = DHCP_BOOTFILE_NAME,
1001 .type = &setting_type_string,
1004 .name = "root-path",
1005 .description = "NFS/iSCSI root path",
1006 .tag = DHCP_ROOT_PATH,
1007 .type = &setting_type_string,
1011 .description = "User name",
1012 .tag = DHCP_EB_USERNAME,
1013 .type = &setting_type_string,
1017 .description = "Password",
1018 .tag = DHCP_EB_PASSWORD,
1019 .type = &setting_type_string,
1022 .name = "initiator-iqn",
1023 .description = "iSCSI initiator name",
1024 .tag = DHCP_ISCSI_INITIATOR_IQN,
1025 .type = &setting_type_string,
1029 .description = "Priority of these settings",
1030 .tag = DHCP_EB_PRIORITY,
1031 .type = &setting_type_int8,