752531864d8f811276407a358e439d24eaf96b86
[people/balajirrao/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 #include <stdint.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <strings.h>
24 #include <byteswap.h>
25 #include <errno.h>
26 #include <assert.h>
27 #include <gpxe/in.h>
28 #include <gpxe/vsprintf.h>
29 #include <gpxe/dhcp.h>
30 #include <gpxe/uuid.h>
31 #include <gpxe/settings.h>
32
33 /** @file
34  *
35  * Configuration settings
36  *
37  */
38
39 /** Registered settings */
40 static struct setting settings[0]
41         __table_start ( struct setting, settings );
42 static struct setting settings_end[0]
43         __table_end ( struct setting, settings );
44
45 /** Registered setting types */
46 static struct setting_type setting_types[0]
47         __table_start ( struct setting_type, setting_types );
48 static struct setting_type setting_types_end[0]
49         __table_end ( struct setting_type, setting_types );
50
51 /** Registered settings applicators */
52 static struct settings_applicator settings_applicators[0]
53         __table_start ( struct settings_applicator, settings_applicators );
54 static struct settings_applicator settings_applicators_end[0]
55         __table_end ( struct settings_applicator, settings_applicators );
56
57 /******************************************************************************
58  *
59  * Registered settings blocks
60  *
61  ******************************************************************************
62  */
63
64 /**
65  * Store value of simple setting
66  *
67  * @v options           DHCP option block
68  * @v setting           Setting to store
69  * @v data              Setting data, or NULL to clear setting
70  * @v len               Length of setting data
71  * @ret rc              Return status code
72  */
73 int simple_settings_store ( struct settings *settings, struct setting *setting,
74                             const void *data, size_t len ) {
75         struct simple_settings *simple =
76                 container_of ( settings, struct simple_settings, settings );
77         return dhcpopt_extensible_store ( &simple->dhcpopts, setting->tag,
78                                           data, len );
79 }
80
81 /**
82  * Fetch value of simple setting
83  *
84  * @v options           DHCP option block
85  * @v setting           Setting to fetch
86  * @v data              Buffer to fill with setting data
87  * @v len               Length of buffer
88  * @ret len             Length of setting data, or negative error
89  */
90 int simple_settings_fetch ( struct settings *settings, struct setting *setting,
91                             void *data, size_t len ) {
92         struct simple_settings *simple =
93                 container_of ( settings, struct simple_settings, settings );
94         return dhcpopt_fetch ( &simple->dhcpopts, setting->tag, data, len );
95 }
96
97 /** Simple settings operations */
98 struct settings_operations simple_settings_operations = {
99         .store = simple_settings_store,
100         .fetch = simple_settings_fetch,
101 };
102
103 /** Root simple settings block */
104 struct simple_settings simple_settings_root = {
105         .settings = {
106                 .refcnt = NULL,
107                 .name = "",
108                 .siblings =
109                      LIST_HEAD_INIT ( simple_settings_root.settings.siblings ),
110                 .children =
111                      LIST_HEAD_INIT ( simple_settings_root.settings.children ),
112                 .op = &simple_settings_operations,
113         },
114 };
115
116 /** Root settings block */
117 #define settings_root simple_settings_root.settings
118
119 /**
120  * Apply all settings
121  *
122  * @ret rc              Return status code
123  */
124 static int apply_settings ( void ) {
125         struct settings_applicator *applicator;
126         int rc;
127
128         /* Call all settings applicators */
129         for ( applicator = settings_applicators ;
130               applicator < settings_applicators_end ; applicator++ ) {
131                 if ( ( rc = applicator->apply() ) != 0 ) {
132                         DBG ( "Could not apply settings using applicator "
133                               "%p: %s\n", applicator, strerror ( rc ) );
134                         return rc;
135                 }
136         }
137
138         return 0;
139 }
140
141 /**
142  * Reprioritise settings
143  *
144  * @v settings          Settings block
145  *
146  * Reorders the settings block amongst its siblings according to its
147  * priority.
148  */
149 static void reprioritise_settings ( struct settings *settings ) {
150         struct settings *parent = settings->parent;
151         long priority;
152         struct settings *tmp;
153         long tmp_priority;
154
155         /* Stop when we reach the top of the tree */
156         if ( ! parent )
157                 return;
158
159         /* Read priority, if present */
160         priority = fetch_intz_setting ( settings, &priority_setting );
161
162         /* Remove from siblings list */
163         list_del ( &settings->siblings );
164
165         /* Reinsert after any existing blocks which have a higher priority */
166         list_for_each_entry ( tmp, &parent->children, siblings ) {
167                 tmp_priority = fetch_intz_setting ( tmp, &priority_setting );
168                 if ( priority > tmp_priority )
169                         break;
170         }
171         list_add_tail ( &settings->siblings, &tmp->siblings );
172
173         /* Recurse up the tree */
174         reprioritise_settings ( parent );
175 }
176
177 /**
178  * Register settings block
179  *
180  * @v settings          Settings block
181  * @v parent            Parent settings block, or NULL
182  * @ret rc              Return status code
183  */
184 int register_settings ( struct settings *settings, struct settings *parent ) {
185
186         /* NULL parent => add to settings root */
187         assert ( settings != NULL );
188         if ( parent == NULL )
189                 parent = &settings_root;
190
191         /* Add to list of settings */
192         ref_get ( settings->refcnt );
193         ref_get ( parent->refcnt );
194         settings->parent = parent;
195         list_add_tail ( &settings->siblings, &parent->children );
196         DBGC ( settings, "Settings %p registered\n", settings );
197
198         /* Fix up settings priority */
199         reprioritise_settings ( settings );
200
201         /* Apply potentially-updated settings */
202         apply_settings();
203
204         return 0;
205 }
206
207 /**
208  * Unregister settings block
209  *
210  * @v settings          Settings block
211  */
212 void unregister_settings ( struct settings *settings ) {
213
214         /* Remove from list of settings */
215         ref_put ( settings->refcnt );
216         ref_put ( settings->parent->refcnt );
217         settings->parent = NULL;
218         list_del ( &settings->siblings );
219         DBGC ( settings, "Settings %p unregistered\n", settings );
220
221         /* Apply potentially-updated settings */
222         apply_settings();
223 }
224
225 /**
226  * Find child named settings block
227  *
228  * @v parent            Parent settings block
229  * @v name              Name within this parent
230  * @ret settings        Settings block, or NULL
231  */
232 struct settings * find_child_settings ( struct settings *parent,
233                                         const char *name ) {
234         struct settings *settings;
235         size_t len;
236
237         /* NULL parent => add to settings root */
238         if ( parent == NULL )
239                 parent = &settings_root;
240
241         /* Look for a child whose name matches the initial component */
242         list_for_each_entry ( settings, &parent->children, siblings ) {
243                 len = strlen ( settings->name );
244                 if ( strncmp ( name, settings->name, len ) != 0 )
245                         continue;
246                 if ( name[len] == 0 )
247                         return settings;
248                 if ( name[len] == '.' )
249                         return find_child_settings ( settings,
250                                                      ( name + len + 1 ) );
251         }
252
253         return NULL;
254 }
255
256 /**
257  * Find named settings block
258  *
259  * @v name              Name
260  * @ret settings        Settings block, or NULL
261  */
262 struct settings * find_settings ( const char *name ) {
263
264         /* If name is empty, use the root */
265         if ( ! *name )
266                 return &settings_root;
267
268         return find_child_settings ( &settings_root, name );
269 }
270
271 /******************************************************************************
272  *
273  * Core settings routines
274  *
275  ******************************************************************************
276  */
277
278 /**
279  * Store value of setting
280  *
281  * @v settings          Settings block
282  * @v setting           Setting to store
283  * @v data              Setting data, or NULL to clear setting
284  * @v len               Length of setting data
285  * @ret rc              Return status code
286  */
287 int store_setting ( struct settings *settings, struct setting *setting,
288                     const void *data, size_t len ) {
289         int rc;
290
291         /* Sanity check */
292         if ( ! settings )
293                 return -ENODEV;
294
295         /* Store setting */
296         if ( ( rc = settings->op->store ( settings, setting,
297                                           data, len ) ) != 0 )
298                 return rc;
299
300         /* Reprioritise settings if necessary */
301         if ( setting_cmp ( setting, &priority_setting ) == 0 )
302                 reprioritise_settings ( settings );
303
304         /* If these settings are registered, apply potentially-updated
305          * settings
306          */
307         for ( ; settings ; settings = settings->parent ) {
308                 if ( settings == &settings_root ) {
309                         if ( ( rc = apply_settings() ) != 0 )
310                                 return rc;
311                         break;
312                 }
313         }
314
315         return 0;
316 }
317
318 /**
319  * Fetch value of setting
320  *
321  * @v settings          Settings block, or NULL to search all blocks
322  * @v setting           Setting to fetch
323  * @v data              Buffer to fill with setting data
324  * @v len               Length of buffer
325  * @ret len             Length of setting data, or negative error
326  *
327  * The actual length of the setting will be returned even if
328  * the buffer was too small.
329  */
330 int fetch_setting ( struct settings *settings, struct setting *setting,
331                     void *data, size_t len ) {
332         struct settings *child;
333         int ret;
334
335         /* NULL settings implies starting at the global settings root */
336         if ( ! settings )
337                 settings = &settings_root;
338
339         /* Try this block first */
340         if ( ( ret = settings->op->fetch ( settings, setting,
341                                            data, len ) ) >= 0 )
342                 return ret;
343
344         /* Recurse into each child block in turn */
345         list_for_each_entry ( child, &settings->children, siblings ) {
346                 if ( ( ret = fetch_setting ( child, setting,
347                                              data, len ) ) >= 0 )
348                         return ret;
349         }
350
351         return -ENOENT;
352 }
353
354 /**
355  * Fetch length of setting
356  *
357  * @v settings          Settings block, or NULL to search all blocks
358  * @v setting           Setting to fetch
359  * @ret len             Length of setting data, or negative error
360  *
361  * This function can also be used as an existence check for the
362  * setting.
363  */
364 int fetch_setting_len ( struct settings *settings, struct setting *setting ) {
365         return fetch_setting ( settings, setting, NULL, 0 );
366 }
367
368 /**
369  * Fetch value of string setting
370  *
371  * @v settings          Settings block, or NULL to search all blocks
372  * @v setting           Setting to fetch
373  * @v data              Buffer to fill with setting string data
374  * @v len               Length of buffer
375  * @ret len             Length of string setting, or negative error
376  *
377  * The resulting string is guaranteed to be correctly NUL-terminated.
378  * The returned length will be the length of the underlying setting
379  * data.
380  */
381 int fetch_string_setting ( struct settings *settings, struct setting *setting,
382                            char *data, size_t len ) {
383         memset ( data, 0, len );
384         return fetch_setting ( settings, setting, data, ( len - 1 ) );
385 }
386
387 /**
388  * Fetch value of IPv4 address setting
389  *
390  * @v settings          Settings block, or NULL to search all blocks
391  * @v setting           Setting to fetch
392  * @v inp               IPv4 address to fill in
393  * @ret len             Length of setting, or negative error
394  */
395 int fetch_ipv4_setting ( struct settings *settings, struct setting *setting,
396                          struct in_addr *inp ) {
397         int len;
398
399         len = fetch_setting ( settings, setting, inp, sizeof ( *inp ) );
400         if ( len < 0 )
401                 return len;
402         if ( len < ( int ) sizeof ( *inp ) )
403                 return -ERANGE;
404         return len;
405 }
406
407 /**
408  * Fetch value of signed integer setting
409  *
410  * @v settings          Settings block, or NULL to search all blocks
411  * @v setting           Setting to fetch
412  * @v value             Integer value to fill in
413  * @ret len             Length of setting, or negative error
414  */
415 int fetch_int_setting ( struct settings *settings, struct setting *setting,
416                         long *value ) {
417         union {
418                 long value;
419                 uint8_t u8[ sizeof ( long ) ];
420                 int8_t s8[ sizeof ( long ) ];
421         } buf;
422         int len;
423         int i;
424
425         buf.value = 0;
426         len = fetch_setting ( settings, setting, &buf, sizeof ( buf ) );
427         if ( len < 0 )
428                 return len;
429         if ( len > ( int ) sizeof ( buf ) )
430                 return -ERANGE;
431
432         *value = ( ( buf.s8[0] >= 0 ) ? 0 : -1L );
433         for ( i = 0 ; i < len ; i++ ) {
434                 *value = ( ( *value << 8 ) | buf.u8[i] );
435         }
436
437         return len;
438 }
439
440 /**
441  * Fetch value of unsigned integer setting
442  *
443  * @v settings          Settings block, or NULL to search all blocks
444  * @v setting           Setting to fetch
445  * @v value             Integer value to fill in
446  * @ret len             Length of setting, or negative error
447  */
448 int fetch_uint_setting ( struct settings *settings, struct setting *setting,
449                          unsigned long *value ) {
450         long svalue;
451         int len;
452
453         len = fetch_int_setting ( settings, setting, &svalue );
454         if ( len < 0 )
455                 return len;
456
457         *value = ( svalue & ( -1UL >> ( sizeof ( long ) - len ) ) );
458
459         return len;
460 }
461
462 /**
463  * Fetch value of signed integer setting, or zero
464  *
465  * @v settings          Settings block, or NULL to search all blocks
466  * @v setting           Setting to fetch
467  * @ret value           Setting value, or zero
468  */
469 long fetch_intz_setting ( struct settings *settings, struct setting *setting ){
470         long value = 0;
471
472         fetch_int_setting ( settings, setting, &value );
473         return value;
474 }
475
476 /**
477  * Fetch value of unsigned integer setting, or zero
478  *
479  * @v settings          Settings block, or NULL to search all blocks
480  * @v setting           Setting to fetch
481  * @ret value           Setting value, or zero
482  */
483 unsigned long fetch_uintz_setting ( struct settings *settings,
484                                     struct setting *setting ) {
485         unsigned long value = 0;
486
487         fetch_uint_setting ( settings, setting, &value );
488         return value;
489 }
490
491 /**
492  * Fetch value of UUID setting
493  *
494  * @v settings          Settings block, or NULL to search all blocks
495  * @v setting           Setting to fetch
496  * @v uuid              UUID to fill in
497  * @ret len             Length of setting, or negative error
498  */
499 int fetch_uuid_setting ( struct settings *settings, struct setting *setting,
500                          union uuid *uuid ) {
501         int len;
502
503         len = fetch_setting ( settings, setting, uuid, sizeof ( *uuid ) );
504         if ( len < 0 )
505                 return len;
506         if ( len != sizeof ( *uuid ) )
507                 return -ERANGE;
508         return len;
509 }
510
511 /**
512  * Compare two settings
513  *
514  * @v a                 Setting to compare
515  * @v b                 Setting to compare
516  * @ret 0               Settings are the same
517  * @ret non-zero        Settings are not the same
518  */
519 int setting_cmp ( struct setting *a, struct setting *b ) {
520
521         /* If the settings have tags, compare them */
522         if ( a->tag && ( a->tag == b->tag ) )
523                 return 0;
524
525         /* Otherwise, compare the names */
526         return strcmp ( a->name, b->name );
527 }
528
529 /******************************************************************************
530  *
531  * Formatted setting routines
532  *
533  ******************************************************************************
534  */
535
536 /**
537  * Store value of typed setting
538  *
539  * @v settings          Settings block
540  * @v setting           Setting to store
541  * @v type              Settings type
542  * @v value             Formatted setting data, or NULL
543  * @ret rc              Return status code
544  */
545 int storef_setting ( struct settings *settings, struct setting *setting,
546                      const char *value ) {
547
548         /* NULL value implies deletion.  Avoid imposing the burden of
549          * checking for NULL values on each typed setting's storef()
550          * method.
551          */
552         if ( ! value )
553                 return delete_setting ( settings, setting );
554                 
555         return setting->type->storef ( settings, setting, value );
556 }
557
558 /**
559  * Find named setting
560  *
561  * @v name              Name
562  * @ret setting         Named setting, or NULL
563  */
564 static struct setting * find_setting ( const char *name ) {
565         struct setting *setting;
566
567         for ( setting = settings ; setting < settings_end ; setting++ ) {
568                 if ( strcmp ( name, setting->name ) == 0 )
569                         return setting;
570         }
571         return NULL;
572 }
573
574 /**
575  * Find setting type
576  *
577  * @v name              Name
578  * @ret type            Setting type, or NULL
579  */
580 static struct setting_type * find_setting_type ( const char *name ) {
581         struct setting_type *type;
582
583         for ( type = setting_types ; type < setting_types_end ; type++ ) {
584                 if ( strcmp ( name, type->name ) == 0 )
585                         return type;
586         }
587         return NULL;
588 }
589
590 /**
591  * Parse setting name
592  *
593  * @v name              Name of setting
594  * @v settings          Settings block to fill in
595  * @v setting           Setting to fill in
596  * @ret rc              Return status code
597  *
598  * Interprets a name of the form
599  * "[settings_name/]tag_name[:type_name]" and fills in the appropriate
600  * fields.
601  */
602 static int parse_setting_name ( const char *name, struct settings **settings,
603                                 struct setting *setting ) {
604         char tmp_name[ strlen ( name ) + 1 ];
605         char *settings_name;
606         char *setting_name;
607         char *type_name;
608         struct setting *named_setting;
609         char *tmp;
610
611         /* Set defaults */
612         *settings = &settings_root;
613         memset ( setting, 0, sizeof ( *setting ) );
614         setting->type = &setting_type_hex;
615
616         /* Split name into "[settings_name/]setting_name[:type_name]" */
617         memcpy ( tmp_name, name, sizeof ( tmp_name ) );
618         if ( ( setting_name = strchr ( tmp_name, '/' ) ) != NULL ) {
619                 *(setting_name++) = 0;
620                 settings_name = tmp_name;
621         } else {
622                 setting_name = tmp_name;
623                 settings_name = NULL;
624         }
625         if ( ( type_name = strchr ( setting_name, ':' ) ) != NULL )
626                 *(type_name++) = 0;
627
628         /* Identify settings block, if specified */
629         if ( settings_name ) {
630                 *settings = find_settings ( settings_name );
631                 if ( *settings == NULL ) {
632                         DBG ( "Unrecognised settings block \"%s\" in \"%s\"\n",
633                               settings_name, name );
634                         return -ENODEV;
635                 }
636         }
637
638         /* Identify tag number */
639         if ( ( named_setting = find_setting ( setting_name ) ) != NULL ) {
640                 memcpy ( setting, named_setting, sizeof ( *setting ) );
641         } else {
642                 /* Unrecognised name: try to interpret as a tag number */
643                 tmp = setting_name;
644                 while ( 1 ) {
645                         setting->tag = ( ( setting->tag << 8 ) |
646                                          strtoul ( tmp, &tmp, 0 ) );
647                         if ( *tmp == 0 )
648                                 break;
649                         if ( *tmp != '.' ) {
650                                 DBG ( "Invalid setting \"%s\" in \"%s\"\n",
651                                       setting_name, name );
652                                 return -ENOENT;
653                         }
654                         tmp++;
655                 }
656         }
657
658         /* Identify setting type, if specified */
659         if ( type_name ) {
660                 setting->type = find_setting_type ( type_name );
661                 if ( setting->type == NULL ) {
662                         DBG ( "Invalid setting type \"%s\" in \"%s\"\n",
663                               type_name, name );
664                         return -ENOTSUP;
665                 }
666         }
667
668         return 0;
669 }
670
671 /**
672  * Parse and store value of named setting
673  *
674  * @v name              Name of setting
675  * @v value             Formatted setting data, or NULL
676  * @ret rc              Return status code
677  */
678 int storef_named_setting ( const char *name, const char *value ) {
679         struct settings *settings;
680         struct setting setting;
681         int rc;
682
683         if ( ( rc = parse_setting_name ( name, &settings, &setting ) ) != 0 )
684                 return rc;
685         return storef_setting ( settings, &setting, value );
686 }
687
688 /**
689  * Fetch and format value of named setting
690  *
691  * @v name              Name of setting
692  * @v buf               Buffer to contain formatted value
693  * @v len               Length of buffer
694  * @ret len             Length of formatted value, or negative error
695  */
696 int fetchf_named_setting ( const char *name, char *buf, size_t len ) {
697         struct settings *settings;
698         struct setting setting;
699         int rc;
700
701         if ( ( rc = parse_setting_name ( name, &settings, &setting ) ) != 0 )
702                 return rc;
703         return fetchf_setting ( settings, &setting, buf, len );
704 }
705
706 /******************************************************************************
707  *
708  * Setting types
709  *
710  ******************************************************************************
711  */
712
713 /**
714  * Parse and store value of string setting
715  *
716  * @v settings          Settings block
717  * @v setting           Setting to store
718  * @v value             Formatted setting data
719  * @ret rc              Return status code
720  */
721 static int storef_string ( struct settings *settings, struct setting *setting,
722                            const char *value ) {
723         return store_setting ( settings, setting, value, strlen ( value ) );
724 }
725
726 /**
727  * Fetch and format value of string setting
728  *
729  * @v settings          Settings block, or NULL to search all blocks
730  * @v setting           Setting to fetch
731  * @v buf               Buffer to contain formatted value
732  * @v len               Length of buffer
733  * @ret len             Length of formatted value, or negative error
734  */
735 static int fetchf_string ( struct settings *settings, struct setting *setting,
736                            char *buf, size_t len ) {
737         return fetch_string_setting ( settings, setting, buf, len );
738 }
739
740 /** A string setting type */
741 struct setting_type setting_type_string __setting_type = {
742         .name = "string",
743         .storef = storef_string,
744         .fetchf = fetchf_string,
745 };
746
747 /**
748  * Parse and store value of IPv4 address setting
749  *
750  * @v settings          Settings block
751  * @v setting           Setting to store
752  * @v value             Formatted setting data
753  * @ret rc              Return status code
754  */
755 static int storef_ipv4 ( struct settings *settings, struct setting *setting,
756                          const char *value ) {
757         struct in_addr ipv4;
758
759         if ( inet_aton ( value, &ipv4 ) == 0 )
760                 return -EINVAL;
761         return store_setting ( settings, setting, &ipv4, sizeof ( ipv4 ) );
762 }
763
764 /**
765  * Fetch and format value of IPv4 address setting
766  *
767  * @v settings          Settings block, or NULL to search all blocks
768  * @v setting           Setting to fetch
769  * @v buf               Buffer to contain formatted value
770  * @v len               Length of buffer
771  * @ret len             Length of formatted value, or negative error
772  */
773 static int fetchf_ipv4 ( struct settings *settings, struct setting *setting,
774                          char *buf, size_t len ) {
775         struct in_addr ipv4;
776         int raw_len;
777
778         if ( ( raw_len = fetch_ipv4_setting ( settings, setting, &ipv4 ) ) < 0)
779                 return raw_len;
780         return snprintf ( buf, len, "%s", inet_ntoa ( ipv4 ) );
781 }
782
783 /** An IPv4 address setting type */
784 struct setting_type setting_type_ipv4 __setting_type = {
785         .name = "ipv4",
786         .storef = storef_ipv4,
787         .fetchf = fetchf_ipv4,
788 };
789
790 /**
791  * Parse and store value of integer setting
792  *
793  * @v settings          Settings block
794  * @v setting           Setting to store
795  * @v value             Formatted setting data
796  * @v size              Integer size, in bytes
797  * @ret rc              Return status code
798  */
799 static int storef_int ( struct settings *settings, struct setting *setting,
800                         const char *value, unsigned int size ) {
801         union {
802                 uint32_t num;
803                 uint8_t bytes[4];
804         } u;
805         char *endp;
806
807         u.num = htonl ( strtoul ( value, &endp, 0 ) );
808         if ( *endp )
809                 return -EINVAL;
810         return store_setting ( settings, setting, 
811                                &u.bytes[ sizeof ( u ) - size ], size );
812 }
813
814 /**
815  * Parse and store value of 8-bit integer setting
816  *
817  * @v settings          Settings block
818  * @v setting           Setting to store
819  * @v value             Formatted setting data
820  * @v size              Integer size, in bytes
821  * @ret rc              Return status code
822  */
823 static int storef_int8 ( struct settings *settings, struct setting *setting,
824                          const char *value ) {
825         return storef_int ( settings, setting, value, 1 );
826 }
827
828 /**
829  * Parse and store value of 16-bit integer setting
830  *
831  * @v settings          Settings block
832  * @v setting           Setting to store
833  * @v value             Formatted setting data
834  * @v size              Integer size, in bytes
835  * @ret rc              Return status code
836  */
837 static int storef_int16 ( struct settings *settings, struct setting *setting,
838                           const char *value ) {
839         return storef_int ( settings, setting, value, 2 );
840 }
841
842 /**
843  * Parse and store value of 32-bit integer setting
844  *
845  * @v settings          Settings block
846  * @v setting           Setting to store
847  * @v value             Formatted setting data
848  * @v size              Integer size, in bytes
849  * @ret rc              Return status code
850  */
851 static int storef_int32 ( struct settings *settings, struct setting *setting,
852                           const char *value ) {
853         return storef_int ( settings, setting, value, 4 );
854 }
855
856 /**
857  * Fetch and format value of signed integer setting
858  *
859  * @v settings          Settings block, or NULL to search all blocks
860  * @v setting           Setting to fetch
861  * @v buf               Buffer to contain formatted value
862  * @v len               Length of buffer
863  * @ret len             Length of formatted value, or negative error
864  */
865 static int fetchf_int ( struct settings *settings, struct setting *setting,
866                         char *buf, size_t len ) {
867         long value;
868         int rc;
869
870         if ( ( rc = fetch_int_setting ( settings, setting, &value ) ) < 0 )
871                 return rc;
872         return snprintf ( buf, len, "%ld", value );
873 }
874
875 /**
876  * Fetch and format value of unsigned integer setting
877  *
878  * @v settings          Settings block, or NULL to search all blocks
879  * @v setting           Setting to fetch
880  * @v buf               Buffer to contain formatted value
881  * @v len               Length of buffer
882  * @ret len             Length of formatted value, or negative error
883  */
884 static int fetchf_uint ( struct settings *settings, struct setting *setting,
885                          char *buf, size_t len ) {
886         unsigned long value;
887         int rc;
888
889         if ( ( rc = fetch_uint_setting ( settings, setting, &value ) ) < 0 )
890                 return rc;
891         return snprintf ( buf, len, "%#lx", value );
892 }
893
894 /** A signed 8-bit integer setting type */
895 struct setting_type setting_type_int8 __setting_type = {
896         .name = "int8",
897         .storef = storef_int8,
898         .fetchf = fetchf_int,
899 };
900
901 /** A signed 16-bit integer setting type */
902 struct setting_type setting_type_int16 __setting_type = {
903         .name = "int16",
904         .storef = storef_int16,
905         .fetchf = fetchf_int,
906 };
907
908 /** A signed 32-bit integer setting type */
909 struct setting_type setting_type_int32 __setting_type = {
910         .name = "int32",
911         .storef = storef_int32,
912         .fetchf = fetchf_int,
913 };
914
915 /** An unsigned 8-bit integer setting type */
916 struct setting_type setting_type_uint8 __setting_type = {
917         .name = "uint8",
918         .storef = storef_int8,
919         .fetchf = fetchf_uint,
920 };
921
922 /** An unsigned 16-bit integer setting type */
923 struct setting_type setting_type_uint16 __setting_type = {
924         .name = "uint16",
925         .storef = storef_int16,
926         .fetchf = fetchf_uint,
927 };
928
929 /** An unsigned 32-bit integer setting type */
930 struct setting_type setting_type_uint32 __setting_type = {
931         .name = "uint32",
932         .storef = storef_int32,
933         .fetchf = fetchf_uint,
934 };
935
936 /**
937  * Parse and store value of hex string setting
938  *
939  * @v settings          Settings block
940  * @v setting           Setting to store
941  * @v value             Formatted setting data
942  * @ret rc              Return status code
943  */
944 static int storef_hex ( struct settings *settings, struct setting *setting,
945                         const char *value ) {
946         char *ptr = ( char * ) value;
947         uint8_t bytes[ strlen ( value ) ]; /* cannot exceed strlen(value) */
948         unsigned int len = 0;
949
950         while ( 1 ) {
951                 bytes[len++] = strtoul ( ptr, &ptr, 16 );
952                 switch ( *ptr ) {
953                 case '\0' :
954                         return store_setting ( settings, setting, bytes, len );
955                 case ':' :
956                         ptr++;
957                         break;
958                 default :
959                         return -EINVAL;
960                 }
961         }
962 }
963
964 /**
965  * Fetch and format value of hex string setting
966  *
967  * @v settings          Settings block, or NULL to search all blocks
968  * @v setting           Setting to fetch
969  * @v buf               Buffer to contain formatted value
970  * @v len               Length of buffer
971  * @ret len             Length of formatted value, or negative error
972  */
973 static int fetchf_hex ( struct settings *settings, struct setting *setting,
974                         char *buf, size_t len ) {
975         int raw_len;
976         int check_len;
977         int used = 0;
978         int i;
979
980         raw_len = fetch_setting_len ( settings, setting );
981         if ( raw_len < 0 )
982                 return raw_len;
983
984         {
985                 uint8_t raw[raw_len];
986
987                 check_len = fetch_setting ( settings, setting, raw,
988                                             sizeof ( raw ) );
989                 assert ( check_len == raw_len );
990                 
991                 if ( len )
992                         buf[0] = 0; /* Ensure that a terminating NUL exists */
993                 for ( i = 0 ; i < raw_len ; i++ ) {
994                         used += ssnprintf ( ( buf + used ), ( len - used ),
995                                             "%s%02x", ( used ? ":" : "" ),
996                                             raw[i] );
997                 }
998                 return used;
999         }
1000 }
1001
1002 /** A hex-string setting */
1003 struct setting_type setting_type_hex __setting_type = {
1004         .name = "hex",
1005         .storef = storef_hex,
1006         .fetchf = fetchf_hex,
1007 };
1008
1009 /**
1010  * Parse and store value of UUID setting
1011  *
1012  * @v settings          Settings block
1013  * @v setting           Setting to store
1014  * @v value             Formatted setting data
1015  * @ret rc              Return status code
1016  */
1017 static int storef_uuid ( struct settings *settings __unused,
1018                          struct setting *setting __unused,
1019                          const char *value __unused ) {
1020         return -ENOTSUP;
1021 }
1022
1023 /**
1024  * Fetch and format value of UUID setting
1025  *
1026  * @v settings          Settings block, or NULL to search all blocks
1027  * @v setting           Setting to fetch
1028  * @v buf               Buffer to contain formatted value
1029  * @v len               Length of buffer
1030  * @ret len             Length of formatted value, or negative error
1031  */
1032 static int fetchf_uuid ( struct settings *settings, struct setting *setting,
1033                          char *buf, size_t len ) {
1034         union uuid uuid;
1035         int raw_len;
1036
1037         if ( ( raw_len = fetch_uuid_setting ( settings, setting, &uuid ) ) < 0)
1038                 return raw_len;
1039         return snprintf ( buf, len, "%s", uuid_ntoa ( &uuid ) );
1040 }
1041
1042 /** UUID setting type */
1043 struct setting_type setting_type_uuid __setting_type = {
1044         .name = "uuid",
1045         .storef = storef_uuid,
1046         .fetchf = fetchf_uuid,
1047 };
1048
1049 /******************************************************************************
1050  *
1051  * Settings
1052  *
1053  ******************************************************************************
1054  */
1055
1056 /** Hostname setting */
1057 struct setting hostname_setting __setting = {
1058         .name = "hostname",
1059         .description = "Host name",
1060         .tag = DHCP_HOST_NAME,
1061         .type = &setting_type_string,
1062 };
1063
1064 /** Filename setting */
1065 struct setting filename_setting __setting = {
1066         .name = "filename",
1067         .description = "Boot filename",
1068         .tag = DHCP_BOOTFILE_NAME,
1069         .type = &setting_type_string,
1070 };
1071
1072 /** Root path setting */
1073 struct setting root_path_setting __setting = {
1074         .name = "root-path",
1075         .description = "NFS/iSCSI root path",
1076         .tag = DHCP_ROOT_PATH,
1077         .type = &setting_type_string,
1078 };
1079
1080 /** Username setting */
1081 struct setting username_setting __setting = {
1082         .name = "username",
1083         .description = "User name",
1084         .tag = DHCP_EB_USERNAME,
1085         .type = &setting_type_string,
1086 };
1087
1088 /** Password setting */
1089 struct setting password_setting __setting = {
1090         .name = "password",
1091         .description = "Password",
1092         .tag = DHCP_EB_PASSWORD,
1093         .type = &setting_type_string,
1094 };
1095
1096 /** Priority setting */
1097 struct setting priority_setting __setting = {
1098         .name = "priority",
1099         .description = "Priority of these settings",
1100         .tag = DHCP_EB_PRIORITY,
1101         .type = &setting_type_int8,
1102 };