/** 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
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,
.op = &simple_settings_operations,
};
+/**
+ * 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
*
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();
******************************************************************************
*/
+/**
+ * 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
*
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;
}
struct dhcp_option_block options;
};
-/** A DHCP option applicator */
-struct dhcp_option_applicator {
- /** DHCP option tag */
- unsigned int tag;
- /** Applicator
- *
- * @v tag DHCP option tag
- * @v option DHCP option
- * @ret rc Return status code
- */
- int ( * apply ) ( unsigned int tag, struct dhcp_option *option );
-};
-
-/** Declare a DHCP option applicator */
-#define __dhcp_applicator \
- __table ( struct dhcp_option_applicator, dhcp_applicators, 01 )
-
/**
* Get reference to DHCP options block
*
/** Declare a configuration setting */
#define __named_setting __table ( struct named_setting, named_settings, 01 )
+/**
+ * A settings applicator
+ *
+ */
+struct settings_applicator {
+ /** Apply updated settings
+ *
+ * @ret rc Return status code
+ */
+ int ( * apply ) ( void );
+};
+
+/** Declare a settings applicator */
+#define __settings_applicator \
+ __table ( struct settings_applicator, settings_applicators, 01 )
+
extern int simple_settings_store ( struct settings *settings, unsigned int tag,
const void *data, size_t len );
extern int simple_settings_fetch ( struct settings *settings, unsigned int tag,
extern int register_settings ( struct settings *settings,
struct settings *parent );
extern void unregister_settings ( struct settings *settings );
+extern int store_setting ( struct settings *settings, unsigned int tag,
+ const void *data, size_t len );
extern int fetch_setting ( struct settings *settings, unsigned int tag,
void *data, size_t len );
extern int fetch_setting_len ( struct settings *settings, unsigned int tag );
settings->name = 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
- */
-static inline int store_setting ( struct settings *settings, unsigned int tag,
- const void *data, size_t len ) {
- return settings->op->store ( settings, tag, data, len );
-}
-
/**
* Delete setting
*
/** List of registered DHCP option blocks */
LIST_HEAD ( dhcp_option_blocks );
-/** Registered DHCP option applicators */
-static struct dhcp_option_applicator dhcp_option_applicators[0]
- __table_start ( struct dhcp_option_applicator, dhcp_applicators );
-static struct dhcp_option_applicator dhcp_option_applicators_end[0]
- __table_end ( struct dhcp_option_applicator, dhcp_applicators );
-
/**
* Obtain printable version of a DHCP option tag
*
* @ret rc Return status code
*/
int apply_dhcp_options ( struct dhcp_option_block *options ) {
- struct dhcp_option_applicator *applicator;
- struct dhcp_option *option;
struct in_addr tftp_server;
struct uri *uri;
char uri_string[32];
- unsigned int tag;
- int rc;
/* Set current working URI based on TFTP server */
find_dhcp_ipv4_option ( options, DHCP_EB_SIADDR, &tftp_server );
churi ( uri );
uri_put ( uri );
- /* Call all registered DHCP option applicators */
- for ( applicator = dhcp_option_applicators ;
- applicator < dhcp_option_applicators_end ; applicator++ ) {
- tag = applicator->tag;
- option = find_dhcp_option ( options, tag );
- if ( ! option )
- continue;
- if ( ( rc = applicator->apply ( tag, option ) ) != 0 ) {
- DBG ( "Could not apply DHCP option %s: %s\n",
- dhcp_tag_name ( tag ), strerror ( rc ) );
- return rc;
- }
- }
-
return 0;
}
#include <gpxe/process.h>
#include <gpxe/uaccess.h>
#include <gpxe/tcpip.h>
-#include <gpxe/dhcp.h>
+#include <gpxe/settings.h>
#include <gpxe/features.h>
#include <gpxe/iscsi.h>
/****************************************************************************
*
- * DHCP option applicators
+ * Settings applicators
*
*/
-/**
- * Apply DHCP iSCSI option
- *
- * @v tag DHCP option tag
- * @v option DHCP option
- * @ret rc Return status code
- */
-static int apply_dhcp_iscsi_string ( unsigned int tag,
- struct dhcp_option *option ) {
- char *prefix = "";
- size_t prefix_len;
- size_t len;
+/** An iSCSI string setting */
+struct iscsi_string_setting {
+ /** Setting tag number */
+ unsigned int tag;
+ /** String to update */
char **string;
- char *p;
-
- /* Identify string and prefix */
- switch ( tag ) {
- case DHCP_ISCSI_INITIATOR_IQN:
- string = &iscsi_explicit_initiator_iqn;
- break;
- case DHCP_EB_USERNAME:
- string = &iscsi_username;
- break;
- case DHCP_EB_PASSWORD:
- string = &iscsi_password;
- break;
- case DHCP_HOST_NAME:
- string = &iscsi_default_initiator_iqn;
- prefix = "iqn.2000-09.org.etherboot:";
- break;
- default:
- assert ( 0 );
- return -EINVAL;
- }
-
- /* Free old string */
- free ( *string );
- *string = NULL;
-
- /* Allocate and fill new string */
- prefix_len = strlen ( prefix );
- len = ( prefix_len + option->len + 1 );
- p = *string = malloc ( len );
- if ( ! p )
- return -ENOMEM;
- strcpy ( p, prefix );
- dhcp_snprintf ( ( p + prefix_len ), ( len - prefix_len ), option );
- return 0;
-}
+ /** String prefix */
+ const char *prefix;
+};
-/** DHCP iSCSI option applicators */
-struct dhcp_option_applicator dhcp_iscsi_applicators[] __dhcp_applicator = {
+/** iSCSI string settings */
+static struct iscsi_string_setting iscsi_string_settings[] = {
{
.tag = DHCP_ISCSI_INITIATOR_IQN,
- .apply = apply_dhcp_iscsi_string,
+ .string = &iscsi_explicit_initiator_iqn,
+ .prefix = "",
},
{
.tag = DHCP_EB_USERNAME,
- .apply = apply_dhcp_iscsi_string,
+ .string = &iscsi_username,
+ .prefix = "",
},
{
.tag = DHCP_EB_PASSWORD,
- .apply = apply_dhcp_iscsi_string,
+ .string = &iscsi_password,
+ .prefix = "",
},
{
.tag = DHCP_HOST_NAME,
- .apply = apply_dhcp_iscsi_string,
+ .string = &iscsi_default_initiator_iqn,
+ .prefix = "iqn.2000-09.org.etherboot:",
},
};
+/**
+ * Apply iSCSI setting
+ *
+ * @v setting iSCSI string setting
+ * @ret rc Return status code
+ */
+static int apply_iscsi_string_setting ( struct iscsi_string_setting *setting ){
+ size_t prefix_len;
+ int setting_len;
+ size_t len;
+ int check_len;
+ char *p;
+
+ /* Free old string */
+ free ( *setting->string );
+ *setting->string = NULL;
+
+ /* Allocate new string */
+ prefix_len = strlen ( setting->prefix );
+ setting_len = fetch_setting_len ( NULL, setting->tag );
+ if ( setting_len < 0 )
+ return setting_len;
+ len = ( prefix_len + setting_len + 1 );
+ p = *setting->string = malloc ( len );
+ if ( ! p )
+ return -ENOMEM;
+
+ /* Fill new string */
+ strcpy ( p, setting->prefix );
+ check_len = fetch_string_setting ( NULL, setting->tag,
+ ( p + prefix_len ),
+ ( len - prefix_len ) );
+ assert ( check_len == setting_len );
+
+ return 0;
+}
+
+/**
+ * Apply iSCSI settings
+ *
+ * @ret rc Return status code
+ */
+static int apply_iscsi_settings ( void ) {
+ struct iscsi_string_setting *setting;
+ unsigned int i;
+ int rc;
+
+ for ( i = 0 ; i < ( sizeof ( iscsi_string_settings ) /
+ sizeof ( iscsi_string_settings[0] ) ) ; i++ ) {
+ setting = &iscsi_string_settings[i];
+ if ( ( rc = apply_iscsi_string_setting ( setting ) ) != 0 ) {
+ DBG ( "iSCSI could not apply setting %d\n",
+ setting->tag );
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+/** iSCSI settings applicator */
+struct settings_applicator iscsi_settings_applicator __settings_applicator = {
+ .apply = apply_iscsi_settings,
+};
+
/****************************************************************************
*
* Initiator name
#include <gpxe/resolv.h>
#include <gpxe/retry.h>
#include <gpxe/tcpip.h>
-#include <gpxe/dhcp.h>
+#include <gpxe/settings.h>
#include <gpxe/features.h>
#include <gpxe/dns.h>
};
/**
- * Apply DHCP nameserver option
+ * Apply nameserver setting
*
- * @v tag DHCP option tag
- * @v option DHCP option
+ * @ret rc Return status code
*/
-static int apply_dhcp_nameserver ( unsigned int tag __unused,
- struct dhcp_option *option ) {
- struct sockaddr_in *sin_nameserver;
-
- sin_nameserver = ( struct sockaddr_in * ) &nameserver;
- sin_nameserver->sin_family = AF_INET;
- dhcp_ipv4_option ( option, &sin_nameserver->sin_addr );
-
- DBG ( "DNS using nameserver %s\n",
- inet_ntoa ( sin_nameserver->sin_addr ) );
+static int apply_nameserver_setting ( void ) {
+ struct sockaddr_in *sin_nameserver =
+ ( struct sockaddr_in * ) &nameserver;
+ int len;
+
+ if ( ( len = fetch_ipv4_setting ( NULL, DHCP_DNS_SERVERS,
+ &sin_nameserver->sin_addr ) ) >= 0 ){
+ sin_nameserver->sin_family = AF_INET;
+ DBG ( "DNS using nameserver %s\n",
+ inet_ntoa ( sin_nameserver->sin_addr ) );
+ }
return 0;
}
-/** DHCP nameserver applicator */
-struct dhcp_option_applicator dhcp_nameserver_applicator __dhcp_applicator = {
- .tag = DHCP_DNS_SERVERS,
- .apply = apply_dhcp_nameserver,
+/** Nameserver setting applicator */
+struct settings_applicator nameserver_applicator __settings_applicator = {
+ .apply = apply_nameserver_setting,
};