summaryrefslogtreecommitdiffstats
path: root/src/core/settings.c
diff options
context:
space:
mode:
authorMichael Brown2008-03-21 00:15:48 +0100
committerMichael Brown2008-03-21 00:15:48 +0100
commitcf033046206aede5064c798bfa887fbb888b9217 (patch)
tree9836e9742cda7fd923a75eeb100b467817bd31b6 /src/core/settings.c
parent[Settings] Add per-netdevice settings block (diff)
downloadipxe-cf033046206aede5064c798bfa887fbb888b9217.tar.gz
ipxe-cf033046206aede5064c798bfa887fbb888b9217.tar.xz
ipxe-cf033046206aede5064c798bfa887fbb888b9217.zip
[Settings] Introduce settings applicators.
Convert DHCP option applicators in dns.c and iscsi.c to settings applicators. Kill off DHCP option applicators.
Diffstat (limited to 'src/core/settings.c')
-rw-r--r--src/core/settings.c111
1 files changed, 102 insertions, 9 deletions
diff --git a/src/core/settings.c b/src/core/settings.c
index 49a7410d..458ba111 100644
--- a/src/core/settings.c
+++ b/src/core/settings.c
@@ -37,15 +37,21 @@
/** Registered setting types */
static struct setting_type setting_types[0]
-__table_start ( struct setting_type, setting_types );
+ __table_start ( struct setting_type, setting_types );
static struct setting_type setting_types_end[0]
-__table_end ( struct setting_type, setting_types );
+ __table_end ( struct setting_type, setting_types );
/** Registered named settings */
static struct named_setting named_settings[0]
-__table_start ( struct named_setting, named_settings );
+ __table_start ( struct named_setting, named_settings );
static struct named_setting named_settings_end[0]
-__table_end ( struct named_setting, named_settings );
+ __table_end ( struct named_setting, named_settings );
+
+/** Registered settings applicators */
+static struct settings_applicator settings_applicators[0]
+ __table_start ( struct settings_applicator, settings_applicators );
+static struct settings_applicator settings_applicators_end[0]
+ __table_end ( struct settings_applicator, settings_applicators );
/**
* Obtain printable version of a settings tag number
@@ -94,10 +100,6 @@ int simple_settings_fetch ( struct settings *settings, unsigned int tag,
return ( len ? len : 8 );
}
-// Dummy routine just for testing
-static void apply_settings ( void ) {
-}
-
/** Simple settings operations */
struct settings_operations simple_settings_operations = {
.store = simple_settings_store,
@@ -114,6 +116,66 @@ struct settings settings_root = {
};
/**
+ * Apply all settings
+ *
+ * @ret rc Return status code
+ */
+static int apply_settings ( void ) {
+ struct settings_applicator *applicator;
+ int rc;
+
+ /* Call all settings applicators */
+ for ( applicator = settings_applicators ;
+ applicator < settings_applicators_end ; applicator++ ) {
+ if ( ( rc = applicator->apply() ) != 0 ) {
+ DBG ( "Could not apply settings using applicator "
+ "%p: %s\n", applicator, strerror ( rc ) );
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Reprioritise settings
+ *
+ * @v settings Settings block
+ *
+ * Reorders the settings block amongst its siblings according to its
+ * priority.
+ */
+static void reprioritise_settings ( struct settings *settings ) {
+ struct settings *parent = settings->parent;
+ long priority;
+ struct settings *tmp;
+ long tmp_priority;
+
+ /* Stop when we reach the top of the tree */
+ if ( ! parent )
+ return;
+
+ /* Read priority, if present */
+ priority = 0;
+ fetch_int_setting ( settings, DHCP_EB_PRIORITY, &priority );
+
+ /* Remove from siblings list */
+ list_del ( &settings->siblings );
+
+ /* Reinsert after any existing blocks which have a higher priority */
+ list_for_each_entry ( tmp, &parent->children, siblings ) {
+ tmp_priority = 0;
+ fetch_int_setting ( tmp, DHCP_EB_PRIORITY, &tmp_priority );
+ if ( priority > tmp_priority )
+ break;
+ }
+ list_add_tail ( &settings->siblings, &tmp->siblings );
+
+ /* Recurse up the tree */
+ reprioritise_settings ( parent );
+}
+
+/**
* Register settings block
*
* @v settings Settings block
@@ -134,6 +196,9 @@ int register_settings ( struct settings *settings, struct settings *parent ) {
list_add_tail ( &settings->siblings, &parent->children );
DBGC ( settings, "Settings %p registered\n", settings );
+ /* Fix up settings priority */
+ reprioritise_settings ( settings );
+
/* Apply potentially-updated settings */
apply_settings();
@@ -207,6 +272,34 @@ struct settings * find_settings ( const char *name ) {
*/
/**
+ * Store value of setting
+ *
+ * @v settings Settings block
+ * @v tag Setting tag number
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+int store_setting ( struct settings *settings, unsigned int tag,
+ const void *data, size_t len ) {
+ int rc;
+
+ /* Store setting */
+ if ( ( rc = settings->op->store ( settings, tag, data, len ) ) != 0 )
+ return rc;
+
+ /* Reprioritise settings if necessary */
+ if ( tag == DHCP_EB_PRIORITY )
+ reprioritise_settings ( settings );
+
+ /* Apply potentially-updated setting */
+ if ( ( rc = apply_settings() ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
* Fetch value of setting
*
* @v settings Settings block, or NULL to search all blocks
@@ -288,7 +381,7 @@ int fetch_ipv4_setting ( struct settings *settings, unsigned int tag,
len = fetch_setting ( settings, tag, inp, sizeof ( *inp ) );
if ( len < 0 )
return len;
- if ( len != sizeof ( *inp ) )
+ if ( len < ( int ) sizeof ( *inp ) )
return -ERANGE;
return len;
}