summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2008-10-29 19:17:02 +0100
committerMichael Brown2008-10-30 22:47:14 +0100
commit0a6c66a83018c64d961ee4e8601ae8950cbee00b (patch)
treec4adb1baea7c87b4e0bbd9f7d1f9127e738065d5
parent[romprefix] Further sanity checks for the PCI 3 runtime segment address (diff)
downloadipxe-0a6c66a83018c64d961ee4e8601ae8950cbee00b.tar.gz
ipxe-0a6c66a83018c64d961ee4e8601ae8950cbee00b.tar.xz
ipxe-0a6c66a83018c64d961ee4e8601ae8950cbee00b.zip
[settings] Add the notion of a "tag magic" to numbered settings
Settings can be constructed using a dotted-decimal notation, to allow for access to unnamed settings. The default interpretation is as a DHCP option number (with encapsulated options represented as "<encapsulating option>.<encapsulated option>". In several contexts (e.g. SMBIOS, Phantom CLP), it is useful to interpret the dotted-decimal notation as referring to non-DHCP options. In this case, it becomes necessary for these contexts to ignore standard DHCP options, otherwise we end up trying to, for example, retrieve the boot filename from SMBIOS. Allow settings blocks to specify a "tag magic". When dotted-decimal notation is used to construct a setting, the tag magic value of the originating settings block will be ORed in to the tag number. Store/fetch methods can then check for the magic number before interpreting arbitrarily-numbered settings.
-rw-r--r--src/arch/i386/firmware/pcbios/smbios_settings.c23
-rw-r--r--src/core/nvo.c2
-rw-r--r--src/core/settings.c1
-rw-r--r--src/drivers/net/phantom/phantom.c40
-rw-r--r--src/include/gpxe/settings.h15
-rw-r--r--src/net/netdevice.c2
-rw-r--r--src/net/udp/dhcp.c2
7 files changed, 60 insertions, 25 deletions
diff --git a/src/arch/i386/firmware/pcbios/smbios_settings.c b/src/arch/i386/firmware/pcbios/smbios_settings.c
index b088e51d..3238fb19 100644
--- a/src/arch/i386/firmware/pcbios/smbios_settings.c
+++ b/src/arch/i386/firmware/pcbios/smbios_settings.c
@@ -24,6 +24,16 @@
#include <gpxe/uuid.h>
#include <smbios.h>
+/** SMBIOS settings tag magic number */
+#define SMBIOS_TAG_MAGIC 0x5B /* "SmBios" */
+
+/**
+ * Construct SMBIOS empty tag
+ *
+ * @ret tag SMBIOS setting tag
+ */
+#define SMBIOS_EMPTY_TAG ( SMBIOS_TAG_MAGIC << 24 )
+
/**
* Construct SMBIOS raw-data tag
*
@@ -33,7 +43,8 @@
* @ret tag SMBIOS setting tag
*/
#define SMBIOS_RAW_TAG( _type, _structure, _field ) \
- ( ( (_type) << 16 ) | \
+ ( ( SMBIOS_TAG_MAGIC << 24 ) | \
+ ( (_type) << 16 ) | \
( offsetof ( _structure, _field ) << 8 ) | \
( sizeof ( ( ( _structure * ) 0 )->_field ) ) )
@@ -46,7 +57,8 @@
* @ret tag SMBIOS setting tag
*/
#define SMBIOS_STRING_TAG( _type, _structure, _field ) \
- ( ( (_type) << 16 ) | \
+ ( ( SMBIOS_TAG_MAGIC << 24 ) | \
+ ( (_type) << 16 ) | \
( offsetof ( _structure, _field ) << 8 ) )
/**
@@ -78,16 +90,18 @@ static int smbios_fetch ( struct settings *settings __unused,
struct setting *setting,
void *data, size_t len ) {
struct smbios_structure structure;
+ unsigned int tag_magic;
unsigned int tag_type;
unsigned int tag_offset;
unsigned int tag_len;
int rc;
/* Split tag into type, offset and length */
- tag_type = ( setting->tag >> 16 );
+ tag_magic = ( setting->tag >> 24 );
+ tag_type = ( ( setting->tag >> 16 ) & 0xff );
tag_offset = ( ( setting->tag >> 8 ) & 0xff );
tag_len = ( setting->tag & 0xff );
- if ( ! tag_type )
+ if ( tag_magic != SMBIOS_TAG_MAGIC )
return -ENOENT;
/* Find SMBIOS structure */
@@ -127,6 +141,7 @@ static struct settings_operations smbios_settings_operations = {
static struct settings smbios_settings = {
.refcnt = NULL,
.name = "smbios",
+ .tag_magic = SMBIOS_EMPTY_TAG,
.siblings = LIST_HEAD_INIT ( smbios_settings.siblings ),
.children = LIST_HEAD_INIT ( smbios_settings.children ),
.op = &smbios_settings_operations,
diff --git a/src/core/nvo.c b/src/core/nvo.c
index 13078022..e5c07d98 100644
--- a/src/core/nvo.c
+++ b/src/core/nvo.c
@@ -203,7 +203,7 @@ void nvo_init ( struct nvo_block *nvo, struct nvs_device *nvs,
nvo->nvs = nvs;
nvo->fragments = fragments;
settings_init ( &nvo->settings, &nvo_settings_operations, refcnt,
- "nvo" );
+ "nvo", 0 );
}
/**
diff --git a/src/core/settings.c b/src/core/settings.c
index f97842f4..9ad2ced2 100644
--- a/src/core/settings.c
+++ b/src/core/settings.c
@@ -665,6 +665,7 @@ static int parse_setting_name ( const char *name, struct settings **settings,
}
tmp++;
}
+ setting->tag |= (*settings)->tag_magic;
}
/* Identify setting type, if specified */
diff --git a/src/drivers/net/phantom/phantom.c b/src/drivers/net/phantom/phantom.c
index 659bd2c1..47bbcb9a 100644
--- a/src/drivers/net/phantom/phantom.c
+++ b/src/drivers/net/phantom/phantom.c
@@ -1589,6 +1589,12 @@ static struct net_device_operations phantom_operations = {
*
*/
+/** Phantom CLP settings tag magic */
+#define PHN_CLP_TAG_MAGIC 0xc19c1900UL
+
+/** Phantom CLP settings tag magic mask */
+#define PHN_CLP_TAG_MAGIC_MASK 0xffffff00UL
+
/** Phantom CLP data
*
*/
@@ -1790,7 +1796,7 @@ struct phantom_clp_setting {
/** gPXE setting */
struct setting *setting;
/** Setting number */
- unsigned int number;
+ unsigned int clp_setting;
};
/** Phantom CLP settings */
@@ -1802,25 +1808,29 @@ static struct phantom_clp_setting clp_settings[] = {
* Find Phantom CLP setting
*
* @v setting gPXE setting
- * @v clp_setting Equivalent Phantom CLP setting, or NULL
+ * @v clp_setting Setting number, or 0 if not found
*/
-static struct phantom_clp_setting *
-phantom_find_clp_setting ( struct phantom_nic *phantom,
- struct setting *setting ) {
+static unsigned int
+phantom_clp_setting ( struct phantom_nic *phantom, struct setting *setting ) {
struct phantom_clp_setting *clp_setting;
unsigned int i;
+ /* Search the list of explicitly-defined settings */
for ( i = 0 ; i < ( sizeof ( clp_settings ) /
sizeof ( clp_settings[0] ) ) ; i++ ) {
clp_setting = &clp_settings[i];
if ( setting_cmp ( setting, clp_setting->setting ) == 0 )
- return clp_setting;
+ return clp_setting->clp_setting;
}
+ /* Allow for use of numbered settings */
+ if ( ( setting->tag & PHN_CLP_TAG_MAGIC_MASK ) == PHN_CLP_TAG_MAGIC )
+ return ( setting->tag & ~PHN_CLP_TAG_MAGIC_MASK );
+
DBGC2 ( phantom, "Phantom %p has no \"%s\" setting\n",
phantom, setting->name );
- return NULL;
+ return 0;
}
/**
@@ -1838,18 +1848,17 @@ static int phantom_store_setting ( struct settings *settings,
struct phantom_nic_port *phantom_port =
container_of ( settings, struct phantom_nic_port, settings );
struct phantom_nic *phantom = phantom_port->phantom;
- struct phantom_clp_setting *clp_setting;
+ unsigned int clp_setting;
int rc;
/* Find Phantom setting equivalent to gPXE setting */
- clp_setting = phantom_find_clp_setting ( phantom, setting );
+ clp_setting = phantom_clp_setting ( phantom, setting );
if ( ! clp_setting )
return -ENOTSUP;
/* Store setting */
if ( ( rc = phantom_clp_store ( phantom, phantom_port->port,
- clp_setting->number,
- data, len ) ) != 0 ) {
+ clp_setting, data, len ) ) != 0 ) {
DBGC ( phantom, "Phantom %p could not store setting \"%s\": "
"%s\n", phantom, setting->name, strerror ( rc ) );
return rc;
@@ -1873,19 +1882,18 @@ static int phantom_fetch_setting ( struct settings *settings,
struct phantom_nic_port *phantom_port =
container_of ( settings, struct phantom_nic_port, settings );
struct phantom_nic *phantom = phantom_port->phantom;
- struct phantom_clp_setting *clp_setting;
+ unsigned int clp_setting;
int read_len;
int rc;
/* Find Phantom setting equivalent to gPXE setting */
- clp_setting = phantom_find_clp_setting ( phantom, setting );
+ clp_setting = phantom_clp_setting ( phantom, setting );
if ( ! clp_setting )
return -ENOTSUP;
/* Fetch setting */
if ( ( read_len = phantom_clp_fetch ( phantom, phantom_port->port,
- clp_setting->number,
- data, len ) ) < 0 ) {
+ clp_setting, data, len ) ) < 0 ){
rc = read_len;
DBGC ( phantom, "Phantom %p could not fetch setting \"%s\": "
"%s\n", phantom, setting->name, strerror ( rc ) );
@@ -2269,7 +2277,7 @@ static int phantom_probe ( struct pci_device *pci,
phantom_port->port = i;
settings_init ( &phantom_port->settings,
&phantom_settings_operations,
- &netdev->refcnt, "clp" );
+ &netdev->refcnt, "clp", PHN_CLP_TAG_MAGIC );
}
/* BUG5945 - need to hack PCI config space on P3 B1 silicon.
diff --git a/src/include/gpxe/settings.h b/src/include/gpxe/settings.h
index ee7dacee..37c01b05 100644
--- a/src/include/gpxe/settings.h
+++ b/src/include/gpxe/settings.h
@@ -72,6 +72,14 @@ struct settings {
struct refcnt *refcnt;
/** Name */
const char *name;
+ /** Tag magic
+ *
+ * This value will be ORed in to any numerical tags
+ * constructed by parse_setting_name(), and can be used to
+ * avoid e.g. attempting to retrieve the subnet mask from
+ * SMBIOS, or the system UUID from DHCP.
+ */
+ unsigned int tag_magic;
/** Parent settings block */
struct settings *parent;
/** Sibling settings blocks */
@@ -225,16 +233,19 @@ extern struct setting mac_setting __setting;
* @v op Settings block operations
* @v refcnt Containing object reference counter, or NULL
* @v name Settings block name
+ * @v tag_magic Tag magic
*/
static inline void settings_init ( struct settings *settings,
struct settings_operations *op,
struct refcnt *refcnt,
- const char *name ) {
+ const char *name,
+ unsigned int tag_magic ) {
INIT_LIST_HEAD ( &settings->siblings );
INIT_LIST_HEAD ( &settings->children );
settings->op = op;
settings->refcnt = refcnt;
settings->name = name;
+ settings->tag_magic = tag_magic;
}
/**
@@ -248,7 +259,7 @@ static inline void simple_settings_init ( struct simple_settings *simple,
struct refcnt *refcnt,
const char *name ) {
settings_init ( &simple->settings, &simple_settings_operations,
- refcnt, name );
+ refcnt, name, 0 );
}
/**
diff --git a/src/net/netdevice.c b/src/net/netdevice.c
index 6ea90b41..81c4ae88 100644
--- a/src/net/netdevice.c
+++ b/src/net/netdevice.c
@@ -268,7 +268,7 @@ struct net_device * alloc_netdev ( size_t priv_size ) {
INIT_LIST_HEAD ( &netdev->rx_queue );
settings_init ( netdev_settings ( netdev ),
&netdev_settings_operations, &netdev->refcnt,
- netdev->name );
+ netdev->name, 0 );
netdev->priv = ( ( ( void * ) netdev ) + sizeof ( *netdev ) );
}
return netdev;
diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c
index ab751cd5..21347832 100644
--- a/src/net/udp/dhcp.c
+++ b/src/net/udp/dhcp.c
@@ -256,7 +256,7 @@ static struct dhcp_settings * dhcpset_create ( const struct dhcphdr *dhcphdr,
dhcppkt_init ( &dhcpset->dhcppkt, data, len );
settings_init ( &dhcpset->settings,
&dhcpset_settings_operations, &dhcpset->refcnt,
- DHCP_SETTINGS_NAME );
+ DHCP_SETTINGS_NAME, 0 );
}
return dhcpset;
}