diff options
author | Michael Brown | 2011-03-22 17:56:35 +0100 |
---|---|---|
committer | Michael Brown | 2011-03-22 20:54:58 +0100 |
commit | f5fd4dec3bab362a2ff7844859914e1f191fb905 (patch) | |
tree | 607eacef2f79c016a0c3c3031de2bb7d8aa7e331 /src/core/settings.c | |
parent | [forcedeth] Clear the MII link status register on link status changes (diff) | |
download | ipxe-f5fd4dec3bab362a2ff7844859914e1f191fb905.tar.gz ipxe-f5fd4dec3bab362a2ff7844859914e1f191fb905.tar.xz ipxe-f5fd4dec3bab362a2ff7844859914e1f191fb905.zip |
[settings] Formalise notion of setting applicability
Expose a function setting_applies() to allow a caller to determine
whether or not a particular setting is applicable to a particular
settings block.
Restrict DHCP-backed settings blocks to accepting only DHCP-based
settings.
Restrict network device settings blocks to accepting only DHCP-based
settings and network device-specific settings such as "mac".
Inspired-by: Glenn Brown <glenn@myri.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/core/settings.c')
-rw-r--r-- | src/core/settings.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/src/core/settings.c b/src/core/settings.c index 139addd5..a080904c 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -493,6 +493,19 @@ void unregister_settings ( struct settings *settings ) { */ /** + * Check applicability of setting + * + * @v settings Settings block + * @v setting Setting + * @ret applies Setting applies within this settings block + */ +int setting_applies ( struct settings *settings, struct setting *setting ) { + + return ( settings->op->applies ? + settings->op->applies ( settings, setting ) : 1 ); +} + +/** * Store value of setting * * @v settings Settings block, or NULL @@ -509,6 +522,10 @@ int store_setting ( struct settings *settings, struct setting *setting, if ( ! settings ) settings = &settings_root; + /* Fail if tag does not apply to this settings block */ + if ( ! setting_applies ( settings, setting ) ) + return -ENOTTY; + /* Sanity check */ if ( ! settings->op->store ) return -ENOTSUP; @@ -564,10 +581,12 @@ int fetch_setting ( struct settings *settings, struct setting *setting, if ( ! settings->op->fetch ) return -ENOTSUP; - /* Try this block first */ - if ( ( ret = settings->op->fetch ( settings, setting, - data, len ) ) >= 0 ) + /* Try this block first, if applicable */ + if ( setting_applies ( settings, setting ) && + ( ( ret = settings->op->fetch ( settings, setting, + data, len ) ) >= 0 ) ) { return ret; + } /* Recurse into each child block in turn */ list_for_each_entry ( child, &settings->children, siblings ) { @@ -886,17 +905,19 @@ struct setting * find_setting ( const char *name ) { /** * Parse setting name as tag number * + * @v settings Settings block * @v name Name * @ret tag Tag number, or 0 if not a valid number */ -static unsigned int parse_setting_tag ( const char *name ) { +static unsigned int parse_setting_tag ( struct settings *settings, + const char *name ) { char *tmp = ( ( char * ) name ); unsigned int tag = 0; while ( 1 ) { tag = ( ( tag << 8 ) | strtoul ( tmp, &tmp, 0 ) ); if ( *tmp == 0 ) - return tag; + return ( tag | settings->tag_magic ); if ( *tmp != '.' ) return 0; tmp++; @@ -946,6 +967,7 @@ parse_setting_name ( const char *name, char *setting_name; char *type_name; struct setting *named_setting; + unsigned int tag; /* Set defaults */ *settings = &settings_root; @@ -979,9 +1001,10 @@ parse_setting_name ( const char *name, if ( ( named_setting = find_setting ( setting_name ) ) != NULL ) { /* Matches a defined named setting; use that setting */ memcpy ( setting, named_setting, sizeof ( *setting ) ); - } else if ( ( setting->tag = parse_setting_tag ( setting_name ) ) !=0){ + } else if ( ( tag = parse_setting_tag ( *settings, + setting_name ) ) != 0 ) { /* Is a valid numeric tag; use the tag */ - setting->tag |= (*settings)->tag_magic; + setting->tag = tag; } else { /* Use the arbitrary name */ setting->name = setting_name; |