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;
/* 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;
} *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;
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 );
/* 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;
}
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;
******************************************************************************
*/
+/**
+ * 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
*
*/
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 );
}
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 ) )
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 )
* @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 );
}
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 );
#include <ipxe/settings.h>
#include <ipxe/device.h>
#include <ipxe/netdevice.h>
+#include <ipxe/init.h>
/** @file
*
.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,
+};