Skip to content

Commit

Permalink
[settings] Add the notion of a "tag magic" to numbered settings
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Michael Brown committed Oct 30, 2008
1 parent 621101c commit 0a6c66a
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 25 deletions.
23 changes: 19 additions & 4 deletions src/arch/i386/firmware/pcbios/smbios_settings.c
Expand Up @@ -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
*
Expand All @@ -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 ) ) )

Expand All @@ -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 ) )

/**
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/core/nvo.c
Expand Up @@ -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 );
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/core/settings.c
Expand Up @@ -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 */
Expand Down
40 changes: 24 additions & 16 deletions src/drivers/net/phantom/phantom.c
Expand Up @@ -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
*
*/
Expand Down Expand Up @@ -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 */
Expand All @@ -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;
}

/**
Expand All @@ -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;
Expand All @@ -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 ) );
Expand Down Expand Up @@ -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.
Expand Down
15 changes: 13 additions & 2 deletions src/include/gpxe/settings.h
Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
}

/**
Expand All @@ -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 );
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/net/netdevice.c
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/net/udp/dhcp.c
Expand Up @@ -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;
}
Expand Down

0 comments on commit 0a6c66a

Please sign in to comment.