[settings] Avoid overwriting the start of .text in fetch_string_setting()
[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,
385                                ( ( len > 0 ) ? ( len - 1 ) : 0 ) );
386 }
387
388 /**
389  * Fetch value of IPv4 address setting
390  *
391  * @v settings          Settings block, or NULL to search all blocks
392  * @v setting           Setting to fetch
393  * @v inp               IPv4 address to fill in
394  * @ret len             Length of setting, or negative error
395  */
396 int fetch_ipv4_setting ( struct settings *settings, struct setting *setting,
397                          struct in_addr *inp ) {
398         int len;
399
400         len = fetch_setting ( settings, setting, inp, sizeof ( *inp ) );
401         if ( len < 0 )
402                 return len;
403         if ( len < ( int ) sizeof ( *inp ) )
404                 return -ERANGE;
405         return len;
406 }
407
408 /**
409  * Fetch value of signed integer setting
410  *
411  * @v settings          Settings block, or NULL to search all blocks
412  * @v setting           Setting to fetch
413  * @v value             Integer value to fill in
414  * @ret len             Length of setting, or negative error
415  */
416 int fetch_int_setting ( struct settings *settings, struct setting *setting,
417                         long *value ) {
418         union {
419                 long value;
420                 uint8_t u8[ sizeof ( long ) ];
421                 int8_t s8[ sizeof ( long ) ];
422         } buf;
423         int len;
424         int i;
425
426         buf.value = 0;
427         len = fetch_setting ( settings, setting, &buf, sizeof ( buf ) );
428         if ( len < 0 )
429                 return len;
430         if ( len > ( int ) sizeof ( buf ) )
431                 return -ERANGE;
432
433         *value = ( ( buf.s8[0] >= 0 ) ? 0 : -1L );
434         for ( i = 0 ; i < len ; i++ ) {
435                 *value = ( ( *value << 8 ) | buf.u8[i] );
436         }
437
438         return len;
439 }
440
441 /**
442  * Fetch value of unsigned integer setting
443  *
444  * @v settings          Settings block, or NULL to search all blocks
445  * @v setting           Setting to fetch
446  * @v value             Integer value to fill in
447  * @ret len             Length of setting, or negative error
448  */
449 int fetch_uint_setting ( struct settings *settings, struct setting *setting,
450                          unsigned long *value ) {
451         long svalue;
452         int len;
453
454         len = fetch_int_setting ( settings, setting, &svalue );
455         if ( len < 0 )
456                 return len;
457
458         *value = ( svalue & ( -1UL >> ( sizeof ( long ) - len ) ) );
459
460         return len;
461 }
462
463 /**
464  * Fetch value of signed integer setting, or zero
465  *
466  * @v settings          Settings block, or NULL to search all blocks
467  * @v setting           Setting to fetch
468  * @ret value           Setting value, or zero
469  */
470 long fetch_intz_setting ( struct settings *settings, struct setting *setting ){
471         long value = 0;
472
473         fetch_int_setting ( settings, setting, &value );
474         return value;
475 }
476
477 /**
478  * Fetch value of unsigned integer setting, or zero
479  *
480  * @v settings          Settings block, or NULL to search all blocks
481  * @v setting           Setting to fetch
482  * @ret value           Setting value, or zero
483  */
484 unsigned long fetch_uintz_setting ( struct settings *settings,
485                                     struct setting *setting ) {
486         unsigned long value = 0;
487
488         fetch_uint_setting ( settings, setting, &value );
489         return value;
490 }
491
492 /**
493  * Fetch value of UUID setting
494  *
495  * @v settings          Settings block, or NULL to search all blocks
496  * @v setting           Setting to fetch
497  * @v uuid              UUID to fill in
498  * @ret len             Length of setting, or negative error
499  */
500 int fetch_uuid_setting ( struct settings *settings, struct setting *setting,
501                          union uuid *uuid ) {
502         int len;
503
504         len = fetch_setting ( settings, setting, uuid, sizeof ( *uuid ) );
505         if ( len < 0 )
506                 return len;
507         if ( len != sizeof ( *uuid ) )
508                 return -ERANGE;
509         return len;
510 }
511
512 /**
513  * Compare two settings
514  *
515  * @v a                 Setting to compare
516  * @v b                 Setting to compare
517  * @ret 0               Settings are the same
518  * @ret non-zero        Settings are not the same
519  */
520 int setting_cmp ( struct setting *a, struct setting *b ) {
521
522         /* If the settings have tags, compare them */
523         if ( a->tag && ( a->tag == b->tag ) )
524                 return 0;
525
526         /* Otherwise, compare the names */
527         return strcmp ( a->name, b->name );
528 }
529
530 /******************************************************************************
531  *
532  * Formatted setting routines
533  *
534  ******************************************************************************
535  */
536
537 /**
538  * Store value of typed setting
539  *
540  * @v settings          Settings block
541  * @v setting           Setting to store
542  * @v type              Settings type
543  * @v value             Formatted setting data, or NULL
544  * @ret rc              Return status code
545  */
546 int storef_setting ( struct settings *settings, struct setting *setting,
547                      const char *value ) {
548
549         /* NULL value implies deletion.  Avoid imposing the burden of
550          * checking for NULL values on each typed setting's storef()
551          * method.
552          */
553         if ( ! value )
554                 return delete_setting ( settings, setting );
555                 
556         return setting->type->storef ( settings, setting, value );
557 }
558
559 /**
560  * Find named setting
561  *
562  * @v name              Name
563  * @ret setting         Named setting, or NULL
564  */
565 static struct setting * find_setting ( const char *name ) {
566         struct setting *setting;
567
568         for ( setting = settings ; setting < settings_end ; setting++ ) {
569                 if ( strcmp ( name, setting->name ) == 0 )
570                         return setting;
571         }
572         return NULL;
573 }
574
575 /**
576  * Find setting type
577  *
578  * @v name              Name
579  * @ret type            Setting type, or NULL
580  */
581 static struct setting_type * find_setting_type ( const char *name ) {
582         struct setting_type *type;
583
584         for ( type = setting_types ; type < setting_types_end ; type++ ) {
585                 if ( strcmp ( name, type->name ) == 0 )
586                         return type;
587         }
588         return NULL;
589 }
590
591 /**
592  * Parse setting name
593  *
594  * @v name              Name of setting
595  * @v settings          Settings block to fill in
596  * @v setting           Setting to fill in
597  * @ret rc              Return status code
598  *
599  * Interprets a name of the form
600  * "[settings_name/]tag_name[:type_name]" and fills in the appropriate
601  * fields.
602  */
603 static int parse_setting_name ( const char *name, struct settings **settings,
604                                 struct setting *setting ) {
605         char tmp_name[ strlen ( name ) + 1 ];
606         char *settings_name;
607         char *setting_name;
608         char *type_name;
609         struct setting *named_setting;
610         char *tmp;
611
612         /* Set defaults */
613         *settings = &settings_root;
614         memset ( setting, 0, sizeof ( *setting ) );
615         setting->type = &setting_type_hex;
616
617         /* Split name into "[settings_name/]setting_name[:type_name]" */
618         memcpy ( tmp_name, name, sizeof ( tmp_name ) );
619         if ( ( setting_name = strchr ( tmp_name, '/' ) ) != NULL ) {
620                 *(setting_name++) = 0;
621                 settings_name = tmp_name;
622         } else {
623                 setting_name = tmp_name;
624                 settings_name = NULL;
625         }
626         if ( ( type_name = strchr ( setting_name, ':' ) ) != NULL )
627                 *(type_name++) = 0;
628
629         /* Identify settings block, if specified */
630         if ( settings_name ) {
631                 *settings = find_settings ( settings_name );
632                 if ( *settings == NULL ) {
633                         DBG ( "Unrecognised settings block \"%s\" in \"%s\"\n",
634                               settings_name, name );
635                         return -ENODEV;
636                 }
637         }
638
639         /* Identify tag number */
640         if ( ( named_setting = find_setting ( setting_name ) ) != NULL ) {
641                 memcpy ( setting, named_setting, sizeof ( *setting ) );
642         } else {
643                 /* Unrecognised name: try to interpret as a tag number */
644                 tmp = setting_name;
645                 while ( 1 ) {
646                         setting->tag = ( ( setting->tag << 8 ) |
647                                          strtoul ( tmp, &tmp, 0 ) );
648                         if ( *tmp == 0 )
649                                 break;
650                         if ( *tmp != '.' ) {
651                                 DBG ( "Invalid setting \"%s\" in \"%s\"\n",
652                                       setting_name, name );
653                                 return -ENOENT;
654                         }
655                         tmp++;
656                 }
657         }
658
659         /* Identify setting type, if specified */
660         if ( type_name ) {
661                 setting->type = find_setting_type ( type_name );
662                 if ( setting->type == NULL ) {
663                         DBG ( "Invalid setting type \"%s\" in \"%s\"\n",
664                               type_name, name );
665                         return -ENOTSUP;
666                 }
667         }
668
669         return 0;
670 }
671
672 /**
673  * Parse and store value of named setting
674  *
675  * @v name              Name of setting
676  * @v value             Formatted setting data, or NULL
677  * @ret rc              Return status code
678  */
679 int storef_named_setting ( const char *name, const char *value ) {
680         struct settings *settings;
681         struct setting setting;
682         int rc;
683
684         if ( ( rc = parse_setting_name ( name, &settings, &setting ) ) != 0 )
685                 return rc;
686         return storef_setting ( settings, &setting, value );
687 }
688
689 /**
690  * Fetch and format value of named setting
691  *
692  * @v name              Name of setting
693  * @v buf               Buffer to contain formatted value
694  * @v len               Length of buffer
695  * @ret len             Length of formatted value, or negative error
696  */
697 int fetchf_named_setting ( const char *name, char *buf, size_t len ) {
698         struct settings *settings;
699         struct setting setting;
700         int rc;
701
702         if ( ( rc = parse_setting_name ( name, &settings, &setting ) ) != 0 )
703                 return rc;
704         return fetchf_setting ( settings, &setting, buf, len );
705 }
706
707 /******************************************************************************
708  *
709  * Setting types
710  *
711  ******************************************************************************
712  */
713
714 /**
715  * Parse and store value of string setting
716  *
717  * @v settings          Settings block
718  * @v setting           Setting to store
719  * @v value             Formatted setting data
720  * @ret rc              Return status code
721  */
722 static int storef_string ( struct settings *settings, struct setting *setting,
723                            const char *value ) {
724         return store_setting ( settings, setting, value, strlen ( value ) );
725 }
726
727 /**
728  * Fetch and format value of string setting
729  *
730  * @v settings          Settings block, or NULL to search all blocks
731  * @v setting           Setting to fetch
732  * @v buf               Buffer to contain formatted value
733  * @v len               Length of buffer
734  * @ret len             Length of formatted value, or negative error
735  */
736 static int fetchf_string ( struct settings *settings, struct setting *setting,
737                            char *buf, size_t len ) {
738         return fetch_string_setting ( settings, setting, buf, len );
739 }
740
741 /** A string setting type */
742 struct setting_type setting_type_string __setting_type = {
743         .name = "string",
744         .storef = storef_string,
745         .fetchf = fetchf_string,
746 };
747
748 /**
749  * Parse and store value of IPv4 address setting
750  *
751  * @v settings          Settings block
752  * @v setting           Setting to store
753  * @v value             Formatted setting data
754  * @ret rc              Return status code
755  */
756 static int storef_ipv4 ( struct settings *settings, struct setting *setting,
757                          const char *value ) {
758         struct in_addr ipv4;
759
760         if ( inet_aton ( value, &ipv4 ) == 0 )
761                 return -EINVAL;
762         return store_setting ( settings, setting, &ipv4, sizeof ( ipv4 ) );
763 }
764
765 /**
766  * Fetch and format value of IPv4 address setting
767  *
768  * @v settings          Settings block, or NULL to search all blocks
769  * @v setting           Setting to fetch
770  * @v buf               Buffer to contain formatted value
771  * @v len               Length of buffer
772  * @ret len             Length of formatted value, or negative error
773  */
774 static int fetchf_ipv4 ( struct settings *settings, struct setting *setting,
775                          char *buf, size_t len ) {
776         struct in_addr ipv4;
777         int raw_len;
778
779         if ( ( raw_len = fetch_ipv4_setting ( settings, setting, &ipv4 ) ) < 0)
780                 return raw_len;
781         return snprintf ( buf, len, "%s", inet_ntoa ( ipv4 ) );
782 }
783
784 /** An IPv4 address setting type */
785 struct setting_type setting_type_ipv4 __setting_type = {
786         .name = "ipv4",
787         .storef = storef_ipv4,
788         .fetchf = fetchf_ipv4,
789 };
790
791 /**
792  * Parse and store value of integer setting
793  *
794  * @v settings          Settings block
795  * @v setting           Setting to store
796  * @v value             Formatted setting data
797  * @v size              Integer size, in bytes
798  * @ret rc              Return status code
799  */
800 static int storef_int ( struct settings *settings, struct setting *setting,
801                         const char *value, unsigned int size ) {
802         union {
803                 uint32_t num;
804                 uint8_t bytes[4];
805         } u;
806         char *endp;
807
808         u.num = htonl ( strtoul ( value, &endp, 0 ) );
809         if ( *endp )
810                 return -EINVAL;
811         return store_setting ( settings, setting, 
812                                &u.bytes[ sizeof ( u ) - size ], size );
813 }
814
815 /**
816  * Parse and store value of 8-bit integer setting
817  *
818  * @v settings          Settings block
819  * @v setting           Setting to store
820  * @v value             Formatted setting data
821  * @v size              Integer size, in bytes
822  * @ret rc              Return status code
823  */
824 static int storef_int8 ( struct settings *settings, struct setting *setting,
825                          const char *value ) {
826         return storef_int ( settings, setting, value, 1 );
827 }
828
829 /**
830  * Parse and store value of 16-bit integer setting
831  *
832  * @v settings          Settings block
833  * @v setting           Setting to store
834  * @v value             Formatted setting data
835  * @v size              Integer size, in bytes
836  * @ret rc              Return status code
837  */
838 static int storef_int16 ( struct settings *settings, struct setting *setting,
839                           const char *value ) {
840         return storef_int ( settings, setting, value, 2 );
841 }
842
843 /**
844  * Parse and store value of 32-bit integer setting
845  *
846  * @v settings          Settings block
847  * @v setting           Setting to store
848  * @v value             Formatted setting data
849  * @v size              Integer size, in bytes
850  * @ret rc              Return status code
851  */
852 static int storef_int32 ( struct settings *settings, struct setting *setting,
853                           const char *value ) {
854         return storef_int ( settings, setting, value, 4 );
855 }
856
857 /**
858  * Fetch and format value of signed integer setting
859  *
860  * @v settings          Settings block, or NULL to search all blocks
861  * @v setting           Setting to fetch
862  * @v buf               Buffer to contain formatted value
863  * @v len               Length of buffer
864  * @ret len             Length of formatted value, or negative error
865  */
866 static int fetchf_int ( struct settings *settings, struct setting *setting,
867                         char *buf, size_t len ) {
868         long value;
869         int rc;
870
871         if ( ( rc = fetch_int_setting ( settings, setting, &value ) ) < 0 )
872                 return rc;
873         return snprintf ( buf, len, "%ld", value );
874 }
875
876 /**
877  * Fetch and format value of unsigned integer setting
878  *
879  * @v settings          Settings block, or NULL to search all blocks
880  * @v setting           Setting to fetch
881  * @v buf               Buffer to contain formatted value
882  * @v len               Length of buffer
883  * @ret len             Length of formatted value, or negative error
884  */
885 static int fetchf_uint ( struct settings *settings, struct setting *setting,
886                          char *buf, size_t len ) {
887         unsigned long value;
888         int rc;
889
890         if ( ( rc = fetch_uint_setting ( settings, setting, &value ) ) < 0 )
891                 return rc;
892         return snprintf ( buf, len, "%#lx", value );
893 }
894
895 /** A signed 8-bit integer setting type */
896 struct setting_type setting_type_int8 __setting_type = {
897         .name = "int8",
898         .storef = storef_int8,
899         .fetchf = fetchf_int,
900 };
901
902 /** A signed 16-bit integer setting type */
903 struct setting_type setting_type_int16 __setting_type = {
904         .name = "int16",
905         .storef = storef_int16,
906         .fetchf = fetchf_int,
907 };
908
909 /** A signed 32-bit integer setting type */
910 struct setting_type setting_type_int32 __setting_type = {
911         .name = "int32",
912         .storef = storef_int32,
913         .fetchf = fetchf_int,
914 };
915
916 /** An unsigned 8-bit integer setting type */
917 struct setting_type setting_type_uint8 __setting_type = {
918         .name = "uint8",
919         .storef = storef_int8,
920         .fetchf = fetchf_uint,
921 };
922
923 /** An unsigned 16-bit integer setting type */
924 struct setting_type setting_type_uint16 __setting_type = {
925         .name = "uint16",
926         .storef = storef_int16,
927         .fetchf = fetchf_uint,
928 };
929
930 /** An unsigned 32-bit integer setting type */
931 struct setting_type setting_type_uint32 __setting_type = {
932         .name = "uint32",
933         .storef = storef_int32,
934         .fetchf = fetchf_uint,
935 };
936
937 /**
938  * Parse and store value of hex string setting
939  *
940  * @v settings          Settings block
941  * @v setting           Setting to store
942  * @v value             Formatted setting data
943  * @ret rc              Return status code
944  */
945 static int storef_hex ( struct settings *settings, struct setting *setting,
946                         const char *value ) {
947         char *ptr = ( char * ) value;
948         uint8_t bytes[ strlen ( value ) ]; /* cannot exceed strlen(value) */
949         unsigned int len = 0;
950
951         while ( 1 ) {
952                 bytes[len++] = strtoul ( ptr, &ptr, 16 );
953                 switch ( *ptr ) {
954                 case '\0' :
955                         return store_setting ( settings, setting, bytes, len );
956                 case ':' :
957                         ptr++;
958                         break;
959                 default :
960                         return -EINVAL;
961                 }
962         }
963 }
964
965 /**
966  * Fetch and format value of hex string setting
967  *
968  * @v settings          Settings block, or NULL to search all blocks
969  * @v setting           Setting to fetch
970  * @v buf               Buffer to contain formatted value
971  * @v len               Length of buffer
972  * @ret len             Length of formatted value, or negative error
973  */
974 static int fetchf_hex ( struct settings *settings, struct setting *setting,
975                         char *buf, size_t len ) {
976         int raw_len;
977         int check_len;
978         int used = 0;
979         int i;
980
981         raw_len = fetch_setting_len ( settings, setting );
982         if ( raw_len < 0 )
983                 return raw_len;
984
985         {
986                 uint8_t raw[raw_len];
987
988                 check_len = fetch_setting ( settings, setting, raw,
989                                             sizeof ( raw ) );
990                 assert ( check_len == raw_len );
991                 
992                 if ( len )
993                         buf[0] = 0; /* Ensure that a terminating NUL exists */
994                 for ( i = 0 ; i < raw_len ; i++ ) {
995                         used += ssnprintf ( ( buf + used ), ( len - used ),
996                                             "%s%02x", ( used ? ":" : "" ),
997                                             raw[i] );
998                 }
999                 return used;
1000         }
1001 }
1002
1003 /** A hex-string setting */
1004 struct setting_type setting_type_hex __setting_type = {
1005         .name = "hex",
1006         .storef = storef_hex,
1007         .fetchf = fetchf_hex,
1008 };
1009
1010 /**
1011  * Parse and store value of UUID setting
1012  *
1013  * @v settings          Settings block
1014  * @v setting           Setting to store
1015  * @v value             Formatted setting data
1016  * @ret rc              Return status code
1017  */
1018 static int storef_uuid ( struct settings *settings __unused,
1019                          struct setting *setting __unused,
1020                          const char *value __unused ) {
1021         return -ENOTSUP;
1022 }
1023
1024 /**
1025  * Fetch and format value of UUID setting
1026  *
1027  * @v settings          Settings block, or NULL to search all blocks
1028  * @v setting           Setting to fetch
1029  * @v buf               Buffer to contain formatted value
1030  * @v len               Length of buffer
1031  * @ret len             Length of formatted value, or negative error
1032  */
1033 static int fetchf_uuid ( struct settings *settings, struct setting *setting,
1034                          char *buf, size_t len ) {
1035         union uuid uuid;
1036         int raw_len;
1037
1038         if ( ( raw_len = fetch_uuid_setting ( settings, setting, &uuid ) ) < 0)
1039                 return raw_len;
1040         return snprintf ( buf, len, "%s", uuid_ntoa ( &uuid ) );
1041 }
1042
1043 /** UUID setting type */
1044 struct setting_type setting_type_uuid __setting_type = {
1045         .name = "uuid",
1046         .storef = storef_uuid,
1047         .fetchf = fetchf_uuid,
1048 };
1049
1050 /******************************************************************************
1051  *
1052  * Settings
1053  *
1054  ******************************************************************************
1055  */
1056
1057 /** Hostname setting */
1058 struct setting hostname_setting __setting = {
1059         .name = "hostname",
1060         .description = "Host name",
1061         .tag = DHCP_HOST_NAME,
1062         .type = &setting_type_string,
1063 };
1064
1065 /** Filename setting */
1066 struct setting filename_setting __setting = {
1067         .name = "filename",
1068         .description = "Boot filename",
1069         .tag = DHCP_BOOTFILE_NAME,
1070         .type = &setting_type_string,
1071 };
1072
1073 /** Root path setting */
1074 struct setting root_path_setting __setting = {
1075         .name = "root-path",
1076         .description = "NFS/iSCSI root path",
1077         .tag = DHCP_ROOT_PATH,
1078         .type = &setting_type_string,
1079 };
1080
1081 /** Username setting */
1082 struct setting username_setting __setting = {
1083         .name = "username",
1084         .description = "User name",
1085         .tag = DHCP_EB_USERNAME,
1086         .type = &setting_type_string,
1087 };
1088
1089 /** Password setting */
1090 struct setting password_setting __setting = {
1091         .name = "password",
1092         .description = "Password",
1093         .tag = DHCP_EB_PASSWORD,
1094         .type = &setting_type_string,
1095 };
1096
1097 /** Priority setting */
1098 struct setting priority_setting __setting = {
1099         .name = "priority",
1100         .description = "Priority of these settings",
1101         .tag = DHCP_EB_PRIORITY,
1102         .type = &setting_type_int8,
1103 };