aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/settings.c73
-rw-r--r--src/hci/tui/settings_ui.c2
-rw-r--r--src/include/ipxe/settings.h7
-rw-r--r--src/net/netdev_settings.c49
4 files changed, 107 insertions, 24 deletions
diff --git a/src/core/settings.c b/src/core/settings.c
index 927ad84..80cd6a9 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 403d124..eb82ae5 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 8ee9516..6e75251 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 3ea7ace..7215276 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,
+};