7a02985b1712f7479e0c832347409e92ee06dfc1
[people/mcb30/gpxe.git] / src / core / settings.c
1 /*
2  * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3  *
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.
8  *
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.
13  *
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.
17  */
18
19 FILE_LICENCE ( GPL2_OR_LATER );
20
21 #include <stdint.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <strings.h>
26 #include <byteswap.h>
27 #include <errno.h>
28 #include <assert.h>
29 #include <gpxe/in.h>
30 #include <gpxe/vsprintf.h>
31 #include <gpxe/dhcp.h>
32 #include <gpxe/uuid.h>
33 #include <gpxe/uri.h>
34 #include <gpxe/settings.h>
35
36 /** @file
37  *
38  * Configuration settings
39  *
40  */
41
42 /******************************************************************************
43  *
44  * Generic settings blocks
45  *
46  ******************************************************************************
47  */
48
49 /**
50  * A generic setting
51  *
52  */
53 struct generic_setting {
54         /** List of generic settings */
55         struct list_head list;
56         /** Setting */
57         struct setting setting;
58         /** Size of setting name */
59         size_t name_len;
60         /** Size of setting data */
61         size_t data_len;
62 };
63
64 /**
65  * Get generic setting name
66  *
67  * @v generic           Generic setting
68  * @ret name            Generic setting name
69  */
70 static inline void * generic_setting_name ( struct generic_setting *generic ) {
71         return ( ( ( void * ) generic ) + sizeof ( *generic ) );
72 }
73
74 /**
75  * Get generic setting data
76  *
77  * @v generic           Generic setting
78  * @ret data            Generic setting data
79  */
80 static inline void * generic_setting_data ( struct generic_setting *generic ) {
81         return ( ( ( void * ) generic ) + sizeof ( *generic ) +
82                  generic->name_len );
83 }
84
85 /**
86  * Find generic setting
87  *
88  * @v generics          Generic settings block
89  * @v setting           Setting to find
90  * @ret generic         Generic setting, or NULL
91  */
92 static struct generic_setting *
93 find_generic_setting ( struct generic_settings *generics,
94                        struct setting *setting ) {
95         struct generic_setting *generic;
96
97         list_for_each_entry ( generic, &generics->list, list ) {
98                 if ( setting_cmp ( &generic->setting, setting ) == 0 )
99                         return generic;
100         }
101         return NULL;
102 }
103
104 /**
105  * Store value of generic setting
106  *
107  * @v settings          Settings block
108  * @v setting           Setting to store
109  * @v data              Setting data, or NULL to clear setting
110  * @v len               Length of setting data
111  * @ret rc              Return status code
112  */
113 int generic_settings_store ( struct settings *settings,
114                              struct setting *setting,
115                              const void *data, size_t len ) {
116         struct generic_settings *generics =
117                 container_of ( settings, struct generic_settings, settings );
118         struct generic_setting *old;
119         struct generic_setting *new = NULL;
120         size_t name_len;
121
122         /* Identify existing generic setting, if any */
123         old = find_generic_setting ( generics, setting );
124
125         /* Create new generic setting, if required */
126         if ( len ) {
127                 /* Allocate new generic setting */
128                 name_len = ( strlen ( setting->name ) + 1 );
129                 new = zalloc ( sizeof ( *new ) + name_len + len );
130                 if ( ! new )
131                         return -ENOMEM;
132
133                 /* Populate new generic setting */
134                 new->name_len = name_len;
135                 new->data_len = len;
136                 memcpy ( &new->setting, setting, sizeof ( new->setting ) );
137                 new->setting.name = generic_setting_name ( new );
138                 memcpy ( generic_setting_name ( new ),
139                          setting->name, name_len );
140                 memcpy ( generic_setting_data ( new ), data, len );
141         }
142
143         /* Delete existing generic setting, if any */
144         if ( old ) {
145                 list_del ( &old->list );
146                 free ( old );
147         }
148
149         /* Add new setting to list, if any */
150         if ( new )
151                 list_add ( &new->list, &generics->list );
152
153         return 0;
154 }
155
156 /**
157  * Fetch value of generic setting
158  *
159  * @v settings          Settings block
160  * @v setting           Setting to fetch
161  * @v data              Buffer to fill with setting data
162  * @v len               Length of buffer
163  * @ret len             Length of setting data, or negative error
164  */
165 int generic_settings_fetch ( struct settings *settings,
166                              struct setting *setting,
167                              void *data, size_t len ) {
168         struct generic_settings *generics =
169                 container_of ( settings, struct generic_settings, settings );
170         struct generic_setting *generic;
171
172         /* Find generic setting */
173         generic = find_generic_setting ( generics, setting );
174         if ( ! generic )
175                 return -ENOENT;
176
177         /* Copy out generic setting data */
178         if ( len > generic->data_len )
179                 len = generic->data_len;
180         memcpy ( data, generic_setting_data ( generic ), len );
181         return generic->data_len;
182 }
183
184 /**
185  * Clear generic settings block
186  *
187  * @v settings          Settings block
188  */
189 void generic_settings_clear ( struct settings *settings ) {
190         struct generic_settings *generics =
191                 container_of ( settings, struct generic_settings, settings );
192         struct generic_setting *generic;
193         struct generic_setting *tmp;
194
195         list_for_each_entry_safe ( generic, tmp, &generics->list, list ) {
196                 list_del ( &generic->list );
197                 free ( generic );
198         }
199         assert ( list_empty ( &generics->list ) );
200 }
201
202 /** Generic settings operations */
203 struct settings_operations generic_settings_operations = {
204         .store = generic_settings_store,
205         .fetch = generic_settings_fetch,
206         .clear = generic_settings_clear,
207 };
208
209 /******************************************************************************
210  *
211  * Registered settings blocks
212  *
213  ******************************************************************************
214  */
215
216 /** Root generic settings block */
217 struct generic_settings generic_settings_root = {
218         .settings = {
219                 .refcnt = NULL,
220                 .name = "",
221                 .siblings =
222                     LIST_HEAD_INIT ( generic_settings_root.settings.siblings ),
223                 .children =
224                     LIST_HEAD_INIT ( generic_settings_root.settings.children ),
225                 .op = &generic_settings_operations,
226         },
227         .list = LIST_HEAD_INIT ( generic_settings_root.list ),
228 };
229
230 /** Root settings block */
231 #define settings_root generic_settings_root.settings
232
233 /**
234  * Find child named settings block
235  *
236  * @v parent            Parent settings block
237  * @v name              Name within this parent
238  * @ret settings        Settings block, or NULL
239  */
240 static struct settings * find_child_settings ( struct settings *parent,
241                                                const char *name ) {
242         struct settings *settings;
243
244         /* Treat empty name as meaning "this block" */
245         if ( ! *name )
246                 return parent;
247
248         /* Look for child with matching name */
249         list_for_each_entry ( settings, &parent->children, siblings ) {
250                 if ( strcmp ( settings->name, name ) == 0 )
251                         return settings;
252         }
253
254         return NULL;
255 }
256
257 /**
258  * Find or create child named settings block
259  *
260  * @v parent            Parent settings block
261  * @v name              Name within this parent
262  * @ret settings        Settings block, or NULL
263  */
264 static struct settings * autovivify_child_settings ( struct settings *parent,
265                                                      const char *name ) {
266         struct {
267                 struct generic_settings generic;
268                 char name[ strlen ( name ) + 1 /* NUL */ ];
269         } *new_child;
270         struct settings *settings;
271
272         /* Return existing settings, if existent */
273         if ( ( settings = find_child_settings ( parent, name ) ) != NULL )
274                 return settings;
275
276         /* Create new generic settings block */
277         new_child = zalloc ( sizeof ( *new_child ) );
278         if ( ! new_child ) {
279                 DBGC ( parent, "Settings %p could not create child %s\n",
280                        parent, name );
281                 return NULL;
282         }
283         memcpy ( new_child->name, name, sizeof ( new_child->name ) );
284         generic_settings_init ( &new_child->generic, NULL, new_child->name );
285         settings = &new_child->generic.settings;
286         register_settings ( settings, parent );
287         return settings;
288 }
289
290 /**
291  * Return settings block name (for debug only)
292  *
293  * @v settings          Settings block
294  * @ret name            Settings block name
295  */
296 static const char * settings_name ( struct settings *settings ) {
297         static char buf[64];
298         char tmp[ sizeof ( buf ) ];
299         int count;
300
301         for ( count = 0 ; settings ; settings = settings->parent ) {
302                 memcpy ( tmp, buf, sizeof ( tmp ) );
303                 snprintf ( buf, sizeof ( buf ), "%s%c%s", settings->name,
304                            ( count++ ? '.' : '\0' ), tmp );
305         }
306         return ( buf + 1 );
307 }
308
309 /**
310  * Parse settings block name
311  *
312  * @v name              Name
313  * @v get_child         Function to find or create child settings block
314  * @ret settings        Settings block, or NULL
315  */
316 static struct settings *
317 parse_settings_name ( const char *name,
318                       struct settings * ( * get_child ) ( struct settings *,
319                                                           const char * ) ) {
320         struct settings *settings = &settings_root;
321         char name_copy[ strlen ( name ) + 1 ];
322         char *subname;
323         char *remainder;
324
325         /* Create modifiable copy of name */
326         memcpy ( name_copy, name, sizeof ( name_copy ) );
327         remainder = name_copy;
328
329         /* Parse each name component in turn */
330         while ( remainder ) {
331                 subname = remainder;
332                 remainder = strchr ( subname, '.' );
333                 if ( remainder )
334                         *(remainder++) = '\0';
335                 settings = get_child ( settings, subname );
336                 if ( ! settings )
337                         break;
338         }
339
340         return settings;
341 }
342
343 /**
344  * Find named settings block
345  *
346  * @v name              Name
347  * @ret settings        Settings block, or NULL
348  */
349 struct settings * find_settings ( const char *name ) {
350
351         return parse_settings_name ( name, find_child_settings );
352 }
353
354 /**
355  * Apply all settings
356  *
357  * @ret rc              Return status code
358  */
359 static int apply_settings ( void ) {
360         struct settings_applicator *applicator;
361         int rc;
362
363         /* Call all settings applicators */
364         for_each_table_entry ( applicator, SETTINGS_APPLICATORS ) {
365                 if ( ( rc = applicator->apply() ) != 0 ) {
366                         DBG ( "Could not apply settings using applicator "
367                               "%p: %s\n", applicator, strerror ( rc ) );
368                         return rc;
369                 }
370         }
371
372         return 0;
373 }
374
375 /**
376  * Reprioritise settings
377  *
378  * @v settings          Settings block
379  *
380  * Reorders the settings block amongst its siblings according to its
381  * priority.
382  */
383 static void reprioritise_settings ( struct settings *settings ) {
384         struct settings *parent = settings->parent;
385         long priority;
386         struct settings *tmp;
387         long tmp_priority;
388
389         /* Stop when we reach the top of the tree */
390         if ( ! parent )
391                 return;
392
393         /* Read priority, if present */
394         priority = fetch_intz_setting ( settings, &priority_setting );
395
396         /* Remove from siblings list */
397         list_del ( &settings->siblings );
398
399         /* Reinsert after any existing blocks which have a higher priority */
400         list_for_each_entry ( tmp, &parent->children, siblings ) {
401                 tmp_priority = fetch_intz_setting ( tmp, &priority_setting );
402                 if ( priority > tmp_priority )
403                         break;
404         }
405         list_add_tail ( &settings->siblings, &tmp->siblings );
406
407         /* Recurse up the tree */
408         reprioritise_settings ( parent );
409 }
410
411 /**
412  * Register settings block
413  *
414  * @v settings          Settings block
415  * @v parent            Parent settings block, or NULL
416  * @ret rc              Return status code
417  */
418 int register_settings ( struct settings *settings, struct settings *parent ) {
419         struct settings *old_settings;
420
421         /* NULL parent => add to settings root */
422         assert ( settings != NULL );
423         if ( parent == NULL )
424                 parent = &settings_root;
425
426         /* Remove any existing settings with the same name */
427         if ( ( old_settings = find_child_settings ( parent, settings->name ) ))
428                 unregister_settings ( old_settings );
429
430         /* Add to list of settings */
431         ref_get ( settings->refcnt );
432         ref_get ( parent->refcnt );
433         settings->parent = parent;
434         list_add_tail ( &settings->siblings, &parent->children );
435         DBGC ( settings, "Settings %p (\"%s\") registered\n",
436                settings, settings_name ( settings ) );
437
438         /* Fix up settings priority */
439         reprioritise_settings ( settings );
440
441         /* Apply potentially-updated settings */
442         apply_settings();
443
444         return 0;
445 }
446
447 /**
448  * Unregister settings block
449  *
450  * @v settings          Settings block
451  */
452 void unregister_settings ( struct settings *settings ) {
453
454         DBGC ( settings, "Settings %p (\"%s\") unregistered\n",
455                settings, settings_name ( settings ) );
456
457         /* Remove from list of settings */
458         ref_put ( settings->refcnt );
459         ref_put ( settings->parent->refcnt );
460         settings->parent = NULL;
461         list_del ( &settings->siblings );
462
463         /* Apply potentially-updated settings */
464         apply_settings();
465 }
466
467 /******************************************************************************
468  *
469  * Core settings routines
470  *
471  ******************************************************************************
472  */
473
474 /**
475  * Store value of setting
476  *
477  * @v settings          Settings block, or NULL
478  * @v setting           Setting to store
479  * @v data              Setting data, or NULL to clear setting
480  * @v len               Length of setting data
481  * @ret rc              Return status code
482  */
483 int store_setting ( struct settings *settings, struct setting *setting,
484                     const void *data, size_t len ) {
485         int rc;
486
487         /* NULL settings implies storing into the global settings root */
488         if ( ! settings )
489                 settings = &settings_root;
490
491         /* Sanity check */
492         if ( ! settings->op->store )
493                 return -ENOTSUP;
494
495         /* Store setting */
496         if ( ( rc = settings->op->store ( settings, setting,
497                                           data, len ) ) != 0 )
498                 return rc;
499
500         /* Reprioritise settings if necessary */
501         if ( setting_cmp ( setting, &priority_setting ) == 0 )
502                 reprioritise_settings ( settings );
503
504         /* If these settings are registered, apply potentially-updated
505          * settings
506          */
507         for ( ; settings ; settings = settings->parent ) {
508                 if ( settings == &settings_root ) {
509                         if ( ( rc = apply_settings() ) != 0 )
510                                 return rc;
511                         break;
512                 }
513         }
514
515         return 0;
516 }
517
518 /**
519  * Fetch value of setting
520  *
521  * @v settings          Settings block, or NULL to search all blocks
522  * @v setting           Setting to fetch
523  * @v data              Buffer to fill with setting data
524  * @v len               Length of buffer
525  * @ret len             Length of setting data, or negative error
526  *
527  * The actual length of the setting will be returned even if
528  * the buffer was too small.
529  */
530 int fetch_setting ( struct settings *settings, struct setting *setting,
531                     void *data, size_t len ) {
532         struct settings *child;
533         int ret;
534
535         /* Avoid returning uninitialised data on error */
536         memset ( data, 0, len );
537
538         /* NULL settings implies starting at the global settings root */
539         if ( ! settings )
540                 settings = &settings_root;
541
542         /* Sanity check */
543         if ( ! settings->op->fetch )
544                 return -ENOTSUP;
545
546         /* Try this block first */
547         if ( ( ret = settings->op->fetch ( settings, setting,
548                                            data, len ) ) >= 0 )
549                 return ret;
550
551         /* Recurse into each child block in turn */
552         list_for_each_entry ( child, &settings->children, siblings ) {
553                 if ( ( ret = fetch_setting ( child, setting,
554                                              data, len ) ) >= 0 )
555                         return ret;
556         }
557
558         return -ENOENT;
559 }
560
561 /**
562  * Fetch length of setting
563  *
564  * @v settings          Settings block, or NULL to search all blocks
565  * @v setting           Setting to fetch
566  * @ret len             Length of setting data, or negative error
567  *
568  * This function can also be used as an existence check for the
569  * setting.
570  */
571 int fetch_setting_len ( struct settings *settings, struct setting *setting ) {
572         return fetch_setting ( settings, setting, NULL, 0 );
573 }
574
575 /**
576  * Fetch value of string setting
577  *
578  * @v settings          Settings block, or NULL to search all blocks
579  * @v setting           Setting to fetch
580  * @v data              Buffer to fill with setting string data
581  * @v len               Length of buffer
582  * @ret len             Length of string setting, or negative error
583  *
584  * The resulting string is guaranteed to be correctly NUL-terminated.
585  * The returned length will be the length of the underlying setting
586  * data.
587  */
588 int fetch_string_setting ( struct settings *settings, struct setting *setting,
589                            char *data, size_t len ) {
590         memset ( data, 0, len );
591         return fetch_setting ( settings, setting, data,
592                                ( ( len > 0 ) ? ( len - 1 ) : 0 ) );
593 }
594
595 /**
596  * Fetch value of string setting
597  *
598  * @v settings          Settings block, or NULL to search all blocks
599  * @v setting           Setting to fetch
600  * @v data              Buffer to allocate and fill with setting string data
601  * @ret len             Length of string setting, or negative error
602  *
603  * The resulting string is guaranteed to be correctly NUL-terminated.
604  * The returned length will be the length of the underlying setting
605  * data.  The caller is responsible for eventually freeing the
606  * allocated buffer.
607  */
608 int fetch_string_setting_copy ( struct settings *settings,
609                                 struct setting *setting,
610                                 char **data ) {
611         int len;
612         int check_len = 0;
613
614         len = fetch_setting_len ( settings, setting );
615         if ( len < 0 )
616                 return len;
617
618         *data = malloc ( len + 1 );
619         if ( ! *data )
620                 return -ENOMEM;
621
622         check_len = fetch_string_setting ( settings, setting, *data,
623                                            ( len + 1 ) );
624         assert ( check_len == len );
625         return len;
626 }
627
628 /**
629  * Fetch value of IPv4 address setting
630  *
631  * @v settings          Settings block, or NULL to search all blocks
632  * @v setting           Setting to fetch
633  * @v inp               IPv4 address to fill in
634  * @ret len             Length of setting, or negative error
635  */
636 int fetch_ipv4_setting ( struct settings *settings, struct setting *setting,
637                          struct in_addr *inp ) {
638         int len;
639
640         len = fetch_setting ( settings, setting, inp, sizeof ( *inp ) );
641         if ( len < 0 )
642                 return len;
643         if ( len < ( int ) sizeof ( *inp ) )
644                 return -ERANGE;
645         return len;
646 }
647
648 /**
649  * Fetch value of signed integer setting
650  *
651  * @v settings          Settings block, or NULL to search all blocks
652  * @v setting           Setting to fetch
653  * @v value             Integer value to fill in
654  * @ret len             Length of setting, or negative error
655  */
656 int fetch_int_setting ( struct settings *settings, struct setting *setting,
657                         long *value ) {
658         union {
659                 uint8_t u8[ sizeof ( long ) ];
660                 int8_t s8[ sizeof ( long ) ];
661         } buf;
662         int len;
663         int i;
664
665         /* Avoid returning uninitialised data on error */
666         *value = 0;
667
668         /* Fetch raw (network-ordered, variable-length) setting */
669         len = fetch_setting ( settings, setting, &buf, sizeof ( buf ) );
670         if ( len < 0 )
671                 return len;
672         if ( len > ( int ) sizeof ( buf ) )
673                 return -ERANGE;
674
675         /* Convert to host-ordered signed long */
676         *value = ( ( buf.s8[0] >= 0 ) ? 0 : -1L );
677         for ( i = 0 ; i < len ; i++ ) {
678                 *value = ( ( *value << 8 ) | buf.u8[i] );
679         }
680
681         return len;
682 }
683
684 /**
685  * Fetch value of unsigned integer setting
686  *
687  * @v settings          Settings block, or NULL to search all blocks
688  * @v setting           Setting to fetch
689  * @v value             Integer value to fill in
690  * @ret len             Length of setting, or negative error
691  */
692 int fetch_uint_setting ( struct settings *settings, struct setting *setting,
693                          unsigned long *value ) {
694         long svalue;
695         int len;
696
697         /* Avoid returning uninitialised data on error */
698         *value = 0;
699
700         /* Fetch as a signed long */
701         len = fetch_int_setting ( settings, setting, &svalue );
702         if ( len < 0 )
703                 return len;
704
705         /* Mask off sign-extended bits */
706         assert ( len <= ( int ) sizeof ( long ) );
707         *value = ( svalue & ( -1UL >> ( 8 * ( sizeof ( long ) - len ) ) ) );
708
709         return len;
710 }
711
712 /**
713  * Fetch value of signed integer setting, or zero
714  *
715  * @v settings          Settings block, or NULL to search all blocks
716  * @v setting           Setting to fetch
717  * @ret value           Setting value, or zero
718  */
719 long fetch_intz_setting ( struct settings *settings, struct setting *setting ){
720         long value;
721
722         fetch_int_setting ( settings, setting, &value );
723         return value;
724 }
725
726 /**
727  * Fetch value of unsigned integer setting, or zero
728  *
729  * @v settings          Settings block, or NULL to search all blocks
730  * @v setting           Setting to fetch
731  * @ret value           Setting value, or zero
732  */
733 unsigned long fetch_uintz_setting ( struct settings *settings,
734                                     struct setting *setting ) {
735         unsigned long value;
736
737         fetch_uint_setting ( settings, setting, &value );
738         return value;
739 }
740
741 /**
742  * Fetch value of UUID setting
743  *
744  * @v settings          Settings block, or NULL to search all blocks
745  * @v setting           Setting to fetch
746  * @v uuid              UUID to fill in
747  * @ret len             Length of setting, or negative error
748  */
749 int fetch_uuid_setting ( struct settings *settings, struct setting *setting,
750                          union uuid *uuid ) {
751         int len;
752
753         len = fetch_setting ( settings, setting, uuid, sizeof ( *uuid ) );
754         if ( len < 0 )
755                 return len;
756         if ( len != sizeof ( *uuid ) )
757                 return -ERANGE;
758         return len;
759 }
760
761 /**
762  * Clear settings block
763  *
764  * @v settings          Settings block
765  */
766 void clear_settings ( struct settings *settings ) {
767         if ( settings->op->clear )
768                 settings->op->clear ( settings );
769 }
770
771 /**
772  * Compare two settings
773  *
774  * @v a                 Setting to compare
775  * @v b                 Setting to compare
776  * @ret 0               Settings are the same
777  * @ret non-zero        Settings are not the same
778  */
779 int setting_cmp ( struct setting *a, struct setting *b ) {
780
781         /* If the settings have tags, compare them */
782         if ( a->tag && ( a->tag == b->tag ) )
783                 return 0;
784
785         /* Otherwise, compare the names */
786         return strcmp ( a->name, b->name );
787 }
788
789 /******************************************************************************
790  *
791  * Formatted setting routines
792  *
793  ******************************************************************************
794  */
795
796 /**
797  * Store value of typed setting
798  *
799  * @v settings          Settings block
800  * @v setting           Setting to store
801  * @v type              Settings type
802  * @v value             Formatted setting data, or NULL
803  * @ret rc              Return status code
804  */
805 int storef_setting ( struct settings *settings, struct setting *setting,
806                      const char *value ) {
807
808         /* NULL value implies deletion.  Avoid imposing the burden of
809          * checking for NULL values on each typed setting's storef()
810          * method.
811          */
812         if ( ! value )
813                 return delete_setting ( settings, setting );
814                 
815         return setting->type->storef ( settings, setting, value );
816 }
817
818 /**
819  * Find named setting
820  *
821  * @v name              Name
822  * @ret setting         Named setting, or NULL
823  */
824 static struct setting * find_setting ( const char *name ) {
825         struct setting *setting;
826
827         for_each_table_entry ( setting, SETTINGS ) {
828                 if ( strcmp ( name, setting->name ) == 0 )
829                         return setting;
830         }
831         return NULL;
832 }
833
834 /**
835  * Parse setting name as tag number
836  *
837  * @v name              Name
838  * @ret tag             Tag number, or 0 if not a valid number
839  */
840 static unsigned int parse_setting_tag ( const char *name ) {
841         char *tmp = ( ( char * ) name );
842         unsigned int tag = 0;
843
844         while ( 1 ) {
845                 tag = ( ( tag << 8 ) | strtoul ( tmp, &tmp, 0 ) );
846                 if ( *tmp == 0 )
847                         return tag;
848                 if ( *tmp != '.' )
849                         return 0;
850                 tmp++;
851         }
852 }
853
854 /**
855  * Find setting type
856  *
857  * @v name              Name
858  * @ret type            Setting type, or NULL
859  */
860 static struct setting_type * find_setting_type ( const char *name ) {
861         struct setting_type *type;
862
863         for_each_table_entry ( type, SETTING_TYPES ) {
864                 if ( strcmp ( name, type->name ) == 0 )
865                         return type;
866         }
867         return NULL;
868 }
869
870 /**
871  * Parse setting name
872  *
873  * @v name              Name of setting
874  * @v get_child         Function to find or create child settings block
875  * @v settings          Settings block to fill in
876  * @v setting           Setting to fill in
877  * @v tmp_name          Buffer for copy of setting name
878  * @ret rc              Return status code
879  *
880  * Interprets a name of the form
881  * "[settings_name/]tag_name[:type_name]" and fills in the appropriate
882  * fields.
883  *
884  * The @c tmp_name buffer must be large enough to hold a copy of the
885  * setting name.
886  */
887 static int
888 parse_setting_name ( const char *name,
889                      struct settings * ( * get_child ) ( struct settings *,
890                                                          const char * ),
891                      struct settings **settings, struct setting *setting,
892                      char *tmp_name ) {
893         char *settings_name;
894         char *setting_name;
895         char *type_name;
896         struct setting *named_setting;
897
898         /* Set defaults */
899         *settings = &settings_root;
900         memset ( setting, 0, sizeof ( *setting ) );
901         setting->name = "";
902         setting->type = &setting_type_string;
903
904         /* Split name into "[settings_name/]setting_name[:type_name]" */
905         strcpy ( tmp_name, name );
906         if ( ( setting_name = strchr ( tmp_name, '/' ) ) != NULL ) {
907                 *(setting_name++) = 0;
908                 settings_name = tmp_name;
909         } else {
910                 setting_name = tmp_name;
911                 settings_name = NULL;
912         }
913         if ( ( type_name = strchr ( setting_name, ':' ) ) != NULL )
914                 *(type_name++) = 0;
915
916         /* Identify settings block, if specified */
917         if ( settings_name ) {
918                 *settings = parse_settings_name ( settings_name, get_child );
919                 if ( *settings == NULL ) {
920                         DBG ( "Unrecognised settings block \"%s\" in \"%s\"\n",
921                               settings_name, name );
922                         return -ENODEV;
923                 }
924         }
925
926         /* Identify setting */
927         if ( ( named_setting = find_setting ( setting_name ) ) != NULL ) {
928                 /* Matches a defined named setting; use that setting */
929                 memcpy ( setting, named_setting, sizeof ( *setting ) );
930         } else if ( ( setting->tag = parse_setting_tag ( setting_name ) ) !=0){
931                 /* Is a valid numeric tag; use the tag */
932                 setting->tag |= (*settings)->tag_magic;
933         } else {
934                 /* Use the arbitrary name */
935                 setting->name = setting_name;
936         }
937
938         /* Identify setting type, if specified */
939         if ( type_name ) {
940                 setting->type = find_setting_type ( type_name );
941                 if ( setting->type == NULL ) {
942                         DBG ( "Invalid setting type \"%s\" in \"%s\"\n",
943                               type_name, name );
944                         return -ENOTSUP;
945                 }
946         }
947
948         return 0;
949 }
950
951 /**
952  * Parse and store value of named setting
953  *
954  * @v name              Name of setting
955  * @v value             Formatted setting data, or NULL
956  * @ret rc              Return status code
957  */
958 int storef_named_setting ( const char *name, const char *value ) {
959         struct settings *settings;
960         struct setting setting;
961         char tmp_name[ strlen ( name ) + 1 ];
962         int rc;
963
964         if ( ( rc = parse_setting_name ( name, autovivify_child_settings,
965                                          &settings, &setting, tmp_name )) != 0)
966                 return rc;
967         return storef_setting ( settings, &setting, value );
968 }
969
970 /**
971  * Fetch and format value of named setting
972  *
973  * @v name              Name of setting
974  * @v buf               Buffer to contain formatted value
975  * @v len               Length of buffer
976  * @ret len             Length of formatted value, or negative error
977  */
978 int fetchf_named_setting ( const char *name, char *buf, size_t len ) {
979         struct settings *settings;
980         struct setting setting;
981         char tmp_name[ strlen ( name ) + 1 ];
982         int rc;
983
984         if ( ( rc = parse_setting_name ( name, find_child_settings,
985                                          &settings, &setting, tmp_name )) != 0)
986                 return rc;
987         return fetchf_setting ( settings, &setting, buf, len );
988 }
989
990 /******************************************************************************
991  *
992  * Setting types
993  *
994  ******************************************************************************
995  */
996
997 /**
998  * Parse and store value of string setting
999  *
1000  * @v settings          Settings block
1001  * @v setting           Setting to store
1002  * @v value             Formatted setting data
1003  * @ret rc              Return status code
1004  */
1005 static int storef_string ( struct settings *settings, struct setting *setting,
1006                            const char *value ) {
1007         return store_setting ( settings, setting, value, strlen ( value ) );
1008 }
1009
1010 /**
1011  * Fetch and format value of string setting
1012  *
1013  * @v settings          Settings block, or NULL to search all blocks
1014  * @v setting           Setting to fetch
1015  * @v buf               Buffer to contain formatted value
1016  * @v len               Length of buffer
1017  * @ret len             Length of formatted value, or negative error
1018  */
1019 static int fetchf_string ( struct settings *settings, struct setting *setting,
1020                            char *buf, size_t len ) {
1021         return fetch_string_setting ( settings, setting, buf, len );
1022 }
1023
1024 /** A string setting type */
1025 struct setting_type setting_type_string __setting_type = {
1026         .name = "string",
1027         .storef = storef_string,
1028         .fetchf = fetchf_string,
1029 };
1030
1031 /**
1032  * Parse and store value of URI-encoded string setting
1033  *
1034  * @v settings          Settings block
1035  * @v setting           Setting to store
1036  * @v value             Formatted setting data
1037  * @ret rc              Return status code
1038  */
1039 static int storef_uristring ( struct settings *settings,
1040                               struct setting *setting,
1041                               const char *value ) {
1042         char buf[ strlen ( value ) + 1 ]; /* Decoding never expands string */
1043         size_t len;
1044
1045         len = uri_decode ( value, buf, sizeof ( buf ) );
1046         return store_setting ( settings, setting, buf, len );
1047 }
1048
1049 /**
1050  * Fetch and format value of URI-encoded string setting
1051  *
1052  * @v settings          Settings block, or NULL to search all blocks
1053  * @v setting           Setting to fetch
1054  * @v buf               Buffer to contain formatted value
1055  * @v len               Length of buffer
1056  * @ret len             Length of formatted value, or negative error
1057  */
1058 static int fetchf_uristring ( struct settings *settings,
1059                               struct setting *setting,
1060                               char *buf, size_t len ) {
1061         ssize_t raw_len;
1062
1063         /* We need to always retrieve the full raw string to know the
1064          * length of the encoded string.
1065          */
1066         raw_len = fetch_setting ( settings, setting, NULL, 0 );
1067         if ( raw_len < 0 )
1068                 return raw_len;
1069
1070         {
1071                 char raw_buf[ raw_len + 1 ];
1072        
1073                 fetch_string_setting ( settings, setting, raw_buf,
1074                                        sizeof ( raw_buf ) );
1075                 return uri_encode ( raw_buf, buf, len );
1076         }
1077 }
1078
1079 /** A URI-encoded string setting type */
1080 struct setting_type setting_type_uristring __setting_type = {
1081         .name = "uristring",
1082         .storef = storef_uristring,
1083         .fetchf = fetchf_uristring,
1084 };
1085
1086 /**
1087  * Parse and store value of IPv4 address setting
1088  *
1089  * @v settings          Settings block
1090  * @v setting           Setting to store
1091  * @v value             Formatted setting data
1092  * @ret rc              Return status code
1093  */
1094 static int storef_ipv4 ( struct settings *settings, struct setting *setting,
1095                          const char *value ) {
1096         struct in_addr ipv4;
1097
1098         if ( inet_aton ( value, &ipv4 ) == 0 )
1099                 return -EINVAL;
1100         return store_setting ( settings, setting, &ipv4, sizeof ( ipv4 ) );
1101 }
1102
1103 /**
1104  * Fetch and format value of IPv4 address setting
1105  *
1106  * @v settings          Settings block, or NULL to search all blocks
1107  * @v setting           Setting to fetch
1108  * @v buf               Buffer to contain formatted value
1109  * @v len               Length of buffer
1110  * @ret len             Length of formatted value, or negative error
1111  */
1112 static int fetchf_ipv4 ( struct settings *settings, struct setting *setting,
1113                          char *buf, size_t len ) {
1114         struct in_addr ipv4;
1115         int raw_len;
1116
1117         if ( ( raw_len = fetch_ipv4_setting ( settings, setting, &ipv4 ) ) < 0)
1118                 return raw_len;
1119         return snprintf ( buf, len, "%s", inet_ntoa ( ipv4 ) );
1120 }
1121
1122 /** An IPv4 address setting type */
1123 struct setting_type setting_type_ipv4 __setting_type = {
1124         .name = "ipv4",
1125         .storef = storef_ipv4,
1126         .fetchf = fetchf_ipv4,
1127 };
1128
1129 /**
1130  * Parse and store value of integer setting
1131  *
1132  * @v settings          Settings block
1133  * @v setting           Setting to store
1134  * @v value             Formatted setting data
1135  * @v size              Integer size, in bytes
1136  * @ret rc              Return status code
1137  */
1138 static int storef_int ( struct settings *settings, struct setting *setting,
1139                         const char *value, unsigned int size ) {
1140         union {
1141                 uint32_t num;
1142                 uint8_t bytes[4];
1143         } u;
1144         char *endp;
1145
1146         u.num = htonl ( strtoul ( value, &endp, 0 ) );
1147         if ( *endp )
1148                 return -EINVAL;
1149         return store_setting ( settings, setting, 
1150                                &u.bytes[ sizeof ( u ) - size ], size );
1151 }
1152
1153 /**
1154  * Parse and store value of 8-bit integer setting
1155  *
1156  * @v settings          Settings block
1157  * @v setting           Setting to store
1158  * @v value             Formatted setting data
1159  * @v size              Integer size, in bytes
1160  * @ret rc              Return status code
1161  */
1162 static int storef_int8 ( struct settings *settings, struct setting *setting,
1163                          const char *value ) {
1164         return storef_int ( settings, setting, value, 1 );
1165 }
1166
1167 /**
1168  * Parse and store value of 16-bit integer setting
1169  *
1170  * @v settings          Settings block
1171  * @v setting           Setting to store
1172  * @v value             Formatted setting data
1173  * @v size              Integer size, in bytes
1174  * @ret rc              Return status code
1175  */
1176 static int storef_int16 ( struct settings *settings, struct setting *setting,
1177                           const char *value ) {
1178         return storef_int ( settings, setting, value, 2 );
1179 }
1180
1181 /**
1182  * Parse and store value of 32-bit integer setting
1183  *
1184  * @v settings          Settings block
1185  * @v setting           Setting to store
1186  * @v value             Formatted setting data
1187  * @v size              Integer size, in bytes
1188  * @ret rc              Return status code
1189  */
1190 static int storef_int32 ( struct settings *settings, struct setting *setting,
1191                           const char *value ) {
1192         return storef_int ( settings, setting, value, 4 );
1193 }
1194
1195 /**
1196  * Fetch and format value of signed integer setting
1197  *
1198  * @v settings          Settings block, or NULL to search all blocks
1199  * @v setting           Setting to fetch
1200  * @v buf               Buffer to contain formatted value
1201  * @v len               Length of buffer
1202  * @ret len             Length of formatted value, or negative error
1203  */
1204 static int fetchf_int ( struct settings *settings, struct setting *setting,
1205                         char *buf, size_t len ) {
1206         long value;
1207         int rc;
1208
1209         if ( ( rc = fetch_int_setting ( settings, setting, &value ) ) < 0 )
1210                 return rc;
1211         return snprintf ( buf, len, "%ld", value );
1212 }
1213
1214 /**
1215  * Fetch and format value of unsigned integer setting
1216  *
1217  * @v settings          Settings block, or NULL to search all blocks
1218  * @v setting           Setting to fetch
1219  * @v buf               Buffer to contain formatted value
1220  * @v len               Length of buffer
1221  * @ret len             Length of formatted value, or negative error
1222  */
1223 static int fetchf_uint ( struct settings *settings, struct setting *setting,
1224                          char *buf, size_t len ) {
1225         unsigned long value;
1226         int rc;
1227
1228         if ( ( rc = fetch_uint_setting ( settings, setting, &value ) ) < 0 )
1229                 return rc;
1230         return snprintf ( buf, len, "%#lx", value );
1231 }
1232
1233 /** A signed 8-bit integer setting type */
1234 struct setting_type setting_type_int8 __setting_type = {
1235         .name = "int8",
1236         .storef = storef_int8,
1237         .fetchf = fetchf_int,
1238 };
1239
1240 /** A signed 16-bit integer setting type */
1241 struct setting_type setting_type_int16 __setting_type = {
1242         .name = "int16",
1243         .storef = storef_int16,
1244         .fetchf = fetchf_int,
1245 };
1246
1247 /** A signed 32-bit integer setting type */
1248 struct setting_type setting_type_int32 __setting_type = {
1249         .name = "int32",
1250         .storef = storef_int32,
1251         .fetchf = fetchf_int,
1252 };
1253
1254 /** An unsigned 8-bit integer setting type */
1255 struct setting_type setting_type_uint8 __setting_type = {
1256         .name = "uint8",
1257         .storef = storef_int8,
1258         .fetchf = fetchf_uint,
1259 };
1260
1261 /** An unsigned 16-bit integer setting type */
1262 struct setting_type setting_type_uint16 __setting_type = {
1263         .name = "uint16",
1264         .storef = storef_int16,
1265         .fetchf = fetchf_uint,
1266 };
1267
1268 /** An unsigned 32-bit integer setting type */
1269 struct setting_type setting_type_uint32 __setting_type = {
1270         .name = "uint32",
1271         .storef = storef_int32,
1272         .fetchf = fetchf_uint,
1273 };
1274
1275 /**
1276  * Parse and store value of hex string setting
1277  *
1278  * @v settings          Settings block
1279  * @v setting           Setting to store
1280  * @v value             Formatted setting data
1281  * @ret rc              Return status code
1282  */
1283 static int storef_hex ( struct settings *settings, struct setting *setting,
1284                         const char *value ) {
1285         char *ptr = ( char * ) value;
1286         uint8_t bytes[ strlen ( value ) ]; /* cannot exceed strlen(value) */
1287         unsigned int len = 0;
1288
1289         while ( 1 ) {
1290                 bytes[len++] = strtoul ( ptr, &ptr, 16 );
1291                 switch ( *ptr ) {
1292                 case '\0' :
1293                         return store_setting ( settings, setting, bytes, len );
1294                 case ':' :
1295                         ptr++;
1296                         break;
1297                 default :
1298                         return -EINVAL;
1299                 }
1300         }
1301 }
1302
1303 /**
1304  * Fetch and format value of hex string setting
1305  *
1306  * @v settings          Settings block, or NULL to search all blocks
1307  * @v setting           Setting to fetch
1308  * @v buf               Buffer to contain formatted value
1309  * @v len               Length of buffer
1310  * @ret len             Length of formatted value, or negative error
1311  */
1312 static int fetchf_hex ( struct settings *settings, struct setting *setting,
1313                         char *buf, size_t len ) {
1314         int raw_len;
1315         int check_len;
1316         int used = 0;
1317         int i;
1318
1319         raw_len = fetch_setting_len ( settings, setting );
1320         if ( raw_len < 0 )
1321                 return raw_len;
1322
1323         {
1324                 uint8_t raw[raw_len];
1325
1326                 check_len = fetch_setting ( settings, setting, raw,
1327                                             sizeof ( raw ) );
1328                 if ( check_len < 0 )
1329                         return check_len;
1330                 assert ( check_len == raw_len );
1331                 
1332                 if ( len )
1333                         buf[0] = 0; /* Ensure that a terminating NUL exists */
1334                 for ( i = 0 ; i < raw_len ; i++ ) {
1335                         used += ssnprintf ( ( buf + used ), ( len - used ),
1336                                             "%s%02x", ( used ? ":" : "" ),
1337                                             raw[i] );
1338                 }
1339                 return used;
1340         }
1341 }
1342
1343 /** A hex-string setting */
1344 struct setting_type setting_type_hex __setting_type = {
1345         .name = "hex",
1346         .storef = storef_hex,
1347         .fetchf = fetchf_hex,
1348 };
1349
1350 /**
1351  * Parse and store value of UUID setting
1352  *
1353  * @v settings          Settings block
1354  * @v setting           Setting to store
1355  * @v value             Formatted setting data
1356  * @ret rc              Return status code
1357  */
1358 static int storef_uuid ( struct settings *settings __unused,
1359                          struct setting *setting __unused,
1360                          const char *value __unused ) {
1361         return -ENOTSUP;
1362 }
1363
1364 /**
1365  * Fetch and format value of UUID setting
1366  *
1367  * @v settings          Settings block, or NULL to search all blocks
1368  * @v setting           Setting to fetch
1369  * @v buf               Buffer to contain formatted value
1370  * @v len               Length of buffer
1371  * @ret len             Length of formatted value, or negative error
1372  */
1373 static int fetchf_uuid ( struct settings *settings, struct setting *setting,
1374                          char *buf, size_t len ) {
1375         union uuid uuid;
1376         int raw_len;
1377
1378         if ( ( raw_len = fetch_uuid_setting ( settings, setting, &uuid ) ) < 0)
1379                 return raw_len;
1380         return snprintf ( buf, len, "%s", uuid_ntoa ( &uuid ) );
1381 }
1382
1383 /** UUID setting type */
1384 struct setting_type setting_type_uuid __setting_type = {
1385         .name = "uuid",
1386         .storef = storef_uuid,
1387         .fetchf = fetchf_uuid,
1388 };
1389
1390 /******************************************************************************
1391  *
1392  * Settings
1393  *
1394  ******************************************************************************
1395  */
1396
1397 /** Hostname setting */
1398 struct setting hostname_setting __setting = {
1399         .name = "hostname",
1400         .description = "Host name",
1401         .tag = DHCP_HOST_NAME,
1402         .type = &setting_type_string,
1403 };
1404
1405 /** Filename setting */
1406 struct setting filename_setting __setting = {
1407         .name = "filename",
1408         .description = "Boot filename",
1409         .tag = DHCP_BOOTFILE_NAME,
1410         .type = &setting_type_string,
1411 };
1412
1413 /** Root path setting */
1414 struct setting root_path_setting __setting = {
1415         .name = "root-path",
1416         .description = "NFS/iSCSI root path",
1417         .tag = DHCP_ROOT_PATH,
1418         .type = &setting_type_string,
1419 };
1420
1421 /** Username setting */
1422 struct setting username_setting __setting = {
1423         .name = "username",
1424         .description = "User name",
1425         .tag = DHCP_EB_USERNAME,
1426         .type = &setting_type_string,
1427 };
1428
1429 /** Password setting */
1430 struct setting password_setting __setting = {
1431         .name = "password",
1432         .description = "Password",
1433         .tag = DHCP_EB_PASSWORD,
1434         .type = &setting_type_string,
1435 };
1436
1437 /** Priority setting */
1438 struct setting priority_setting __setting = {
1439         .name = "priority",
1440         .description = "Priority of these settings",
1441         .tag = DHCP_EB_PRIORITY,
1442         .type = &setting_type_int8,
1443 };