diff options
-rw-r--r-- | src/core/settings.c | 73 | ||||
-rw-r--r-- | src/hci/tui/settings_ui.c | 2 | ||||
-rw-r--r-- | src/include/ipxe/settings.h | 7 | ||||
-rw-r--r-- | src/net/netdev_settings.c | 49 |
4 files changed, 107 insertions, 24 deletions
diff --git a/src/core/settings.c b/src/core/settings.c index 927ad845..80cd6a9f 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -271,6 +271,9 @@ struct settings * find_child_settings ( struct settings *parent, const char *name ) { struct settings *settings; + /* Find target parent settings block */ + parent = settings_target ( parent ); + /* Treat empty name as meaning "this block" */ if ( ! *name ) return parent; @@ -278,7 +281,7 @@ struct settings * find_child_settings ( struct settings *parent, /* Look for child with matching name */ list_for_each_entry ( settings, &parent->children, siblings ) { if ( strcmp ( settings->name, name ) == 0 ) - return settings; + return settings_target ( settings ); } return NULL; @@ -299,6 +302,9 @@ static struct settings * autovivify_child_settings ( struct settings *parent, } *new_child; struct settings *settings; + /* Find target parent settings block */ + parent = settings_target ( parent ); + /* Return existing settings, if existent */ if ( ( settings = find_child_settings ( parent, name ) ) != NULL ) return settings; @@ -330,6 +336,10 @@ const char * settings_name ( struct settings *settings ) { static char buf[16]; char tmp[ sizeof ( buf ) ]; + /* Find target settings block */ + settings = settings_target ( settings ); + + /* Construct name */ for ( buf[2] = buf[0] = 0 ; settings ; settings = settings->parent ) { memcpy ( tmp, buf, sizeof ( tmp ) ); snprintf ( buf, sizeof ( buf ), ".%s%s", settings->name, tmp ); @@ -359,20 +369,11 @@ parse_settings_name ( const char *name, /* Parse each name component in turn */ while ( remainder ) { - struct net_device *netdev; - subname = remainder; remainder = strchr ( subname, '.' ); if ( remainder ) *(remainder++) = '\0'; - - /* Special case "netX" root settings block */ - if ( ( subname == name_copy ) && ! strcmp ( subname, "netX" ) && - ( ( netdev = last_opened_netdev() ) != NULL ) ) - settings = get_child ( settings, netdev->name ); - else - settings = get_child ( settings, subname ); - + settings = get_child ( settings, subname ); if ( ! settings ) break; } @@ -460,10 +461,11 @@ int register_settings ( struct settings *settings, struct settings *parent, const char *name ) { struct settings *old_settings; - /* NULL parent => add to settings root */ + /* Sanity check */ assert ( settings != NULL ); - if ( parent == NULL ) - parent = &settings_root; + + /* Find target parent settings block */ + parent = settings_target ( parent ); /* Apply settings block name */ settings->name = name; @@ -524,6 +526,26 @@ void unregister_settings ( struct settings *settings ) { */ /** + * Redirect to target settings block + * + * @v settings Settings block, or NULL + * @ret settings Underlying settings block + */ +struct settings * settings_target ( struct settings *settings ) { + + /* NULL settings implies the global settings root */ + if ( ! settings ) + settings = &settings_root; + + /* Redirect to underlying settings block, if applicable */ + if ( settings->op->redirect ) + return settings->op->redirect ( settings ); + + /* Otherwise, return this settings block */ + return settings; +} + +/** * Check applicability of setting * * @v settings Settings block @@ -532,6 +554,10 @@ void unregister_settings ( struct settings *settings ) { */ int setting_applies ( struct settings *settings, struct setting *setting ) { + /* Find target settings block */ + settings = settings_target ( settings ); + + /* Check applicability of setting */ return ( settings->op->applies ? settings->op->applies ( settings, setting ) : 1 ); } @@ -549,9 +575,8 @@ int store_setting ( struct settings *settings, struct setting *setting, const void *data, size_t len ) { int rc; - /* NULL settings implies storing into the global settings root */ - if ( ! settings ) - settings = &settings_root; + /* Find target settings block */ + settings = settings_target ( settings ); /* Fail if tag does not apply to this settings block */ if ( ! setting_applies ( settings, setting ) ) @@ -609,9 +634,8 @@ static int fetch_setting_and_origin ( struct settings *settings, if ( origin ) *origin = NULL; - /* NULL settings implies starting at the global settings root */ - if ( ! settings ) - settings = &settings_root; + /* Find target settings block */ + settings = settings_target ( settings ); /* Sanity check */ if ( ! settings->op->fetch ) @@ -971,6 +995,11 @@ int fetch_uuid_setting ( struct settings *settings, struct setting *setting, * @v settings Settings block */ void clear_settings ( struct settings *settings ) { + + /* Find target settings block */ + settings = settings_target ( settings ); + + /* Clear settings, if applicable */ if ( settings->op->clear ) settings->op->clear ( settings ); } @@ -1230,9 +1259,7 @@ int setting_name ( struct settings *settings, struct setting *setting, char *buf, size_t len ) { const char *name; - if ( ! settings ) - settings = &settings_root; - + settings = settings_target ( settings ); name = settings_name ( settings ); return snprintf ( buf, len, "%s%s%s:%s", name, ( name[0] ? "/" : "" ), setting->name, setting->type->name ); diff --git a/src/hci/tui/settings_ui.c b/src/hci/tui/settings_ui.c index 403d1245..eb82ae54 100644 --- a/src/hci/tui/settings_ui.c +++ b/src/hci/tui/settings_ui.c @@ -441,7 +441,7 @@ static void reveal_setting_row ( struct setting_widget *widget, static void init_widget ( struct setting_widget *widget, struct settings *settings ) { - widget->settings = settings; + widget->settings = settings_target ( settings ); widget->num_rows = select_setting_row ( widget, 0 ); widget->first_visible = SETTINGS_LIST_ROWS; draw_title_row ( widget ); diff --git a/src/include/ipxe/settings.h b/src/include/ipxe/settings.h index 8ee9516e..6e75251c 100644 --- a/src/include/ipxe/settings.h +++ b/src/include/ipxe/settings.h @@ -77,6 +77,12 @@ struct setting { /** Settings block operations */ struct settings_operations { + /** Redirect to underlying settings block (if applicable) + * + * @v settings Settings block + * @ret settings Underlying settings block + */ + struct settings * ( * redirect ) ( struct settings *settings ); /** Check applicability of setting * * @v settings Settings block @@ -248,6 +254,7 @@ extern int register_settings ( struct settings *settings, struct settings *parent, const char *name ); extern void unregister_settings ( struct settings *settings ); +extern struct settings * settings_target ( struct settings *settings ); extern int setting_applies ( struct settings *settings, struct setting *setting ); extern int store_setting ( struct settings *settings, struct setting *setting, diff --git a/src/net/netdev_settings.c b/src/net/netdev_settings.c index 3ea7ace5..72152762 100644 --- a/src/net/netdev_settings.c +++ b/src/net/netdev_settings.c @@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <ipxe/settings.h> #include <ipxe/device.h> #include <ipxe/netdevice.h> +#include <ipxe/init.h> /** @file * @@ -295,3 +296,51 @@ struct settings_operations netdev_settings_operations = { .fetch = netdev_fetch, .clear = netdev_clear, }; + +/** + * Redirect "netX" settings block + * + * @v settings Settings block + * @ret settings Underlying settings block + */ +static struct settings * netdev_redirect ( struct settings *settings ) { + struct net_device *netdev; + + /* Redirect to most recently opened network device */ + netdev = last_opened_netdev(); + if ( netdev ) { + return netdev_settings ( netdev ); + } else { + return settings; + } +} + +/** "netX" settings operations */ +static struct settings_operations netdev_redirect_settings_operations = { + .redirect = netdev_redirect, +}; + +/** "netX" settings */ +static struct settings netdev_redirect_settings = { + .refcnt = NULL, + .siblings = LIST_HEAD_INIT ( netdev_redirect_settings.siblings ), + .children = LIST_HEAD_INIT ( netdev_redirect_settings.children ), + .op = &netdev_redirect_settings_operations, +}; + +/** Initialise "netX" settings */ +static void netdev_redirect_settings_init ( void ) { + int rc; + + if ( ( rc = register_settings ( &netdev_redirect_settings, NULL, + "netX" ) ) != 0 ) { + DBG ( "Could not register netX settings: %s\n", + strerror ( rc ) ); + return; + } +} + +/** "netX" settings initialiser */ +struct init_fn netdev_redirect_settings_init_fn __init_fn ( INIT_LATE ) = { + .initialise = netdev_redirect_settings_init, +}; |