diff --git a/src/arch/i386/firmware/pcbios/smbios_settings.c b/src/arch/i386/firmware/pcbios/smbios_settings.c index b088e51dc..3238fb195 100644 --- a/src/arch/i386/firmware/pcbios/smbios_settings.c +++ b/src/arch/i386/firmware/pcbios/smbios_settings.c @@ -24,6 +24,16 @@ #include #include +/** 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 13078022b..e5c07d986 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 f97842f4b..9ad2ced26 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 659bd2c1e..47bbcb9a4 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 ee7dacee3..37c01b058 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 6ea90b41b..81c4ae886 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 ab751cd53..213478323 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; }