From 8bc20c1aa09ec521476f4b35b0a09c21e2e1e5f3 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 1 May 2013 20:42:57 +0100 Subject: [PATCH] [smbios] Allow access to multiple instances of SMBIOS structures Extend the syntax for numerical SMBIOS settings from smbios/.. to smbios/[.].. Where SMBIOS provides multiple structures with the same , this extended syntax allows for access to structures other than the first. If is omitted then it will default to zero, giving access to the first instance (and so matching existing behaviour). The 16-bit SMBIOS handle (which is an alternative way to disambiguate multiple instances of the same type of structure) can be accessed, if required, using smbios/..2.2:uint16 Signed-off-by: Michael Brown --- src/include/ipxe/smbios.h | 2 +- src/interface/smbios/smbios.c | 6 ++++-- src/interface/smbios/smbios_settings.c | 7 +++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/include/ipxe/smbios.h b/src/include/ipxe/smbios.h index 0765c4e4..aaba6cb1 100644 --- a/src/include/ipxe/smbios.h +++ b/src/include/ipxe/smbios.h @@ -162,7 +162,7 @@ struct smbios { #define SMBIOS_VERSION( major, minor ) ( ( (major) << 8 ) | (minor) ) extern int find_smbios ( struct smbios *smbios ); -extern int find_smbios_structure ( unsigned int type, +extern int find_smbios_structure ( unsigned int type, unsigned int instance, struct smbios_structure *structure ); extern int read_smbios_structure ( struct smbios_structure *structure, void *data, size_t len ); diff --git a/src/interface/smbios/smbios.c b/src/interface/smbios/smbios.c index 2adaa53d..90907e18 100644 --- a/src/interface/smbios/smbios.c +++ b/src/interface/smbios/smbios.c @@ -59,10 +59,11 @@ static size_t find_strings_terminator ( size_t offset ) { * Find specific structure type within SMBIOS * * @v type Structure type to search for + * @v instance Instance of this type of structure * @v structure SMBIOS structure descriptor to fill in * @ret rc Return status code */ -int find_smbios_structure ( unsigned int type, +int find_smbios_structure ( unsigned int type, unsigned int instance, struct smbios_structure *structure ) { unsigned int count = 0; size_t offset = 0; @@ -105,7 +106,8 @@ int find_smbios_structure ( unsigned int type, structure->header.len, structure->strings_len ); /* If this is the structure we want, return */ - if ( structure->header.type == type ) { + if ( ( structure->header.type == type ) && + ( instance-- == 0 ) ) { structure->offset = offset; return 0; } diff --git a/src/interface/smbios/smbios_settings.c b/src/interface/smbios/smbios_settings.c index 17f9a48e..d2975df4 100644 --- a/src/interface/smbios/smbios_settings.c +++ b/src/interface/smbios/smbios_settings.c @@ -81,18 +81,21 @@ static int smbios_fetch ( struct settings *settings __unused, struct setting *setting, void *data, size_t len ) { struct smbios_structure structure; + unsigned int tag_instance; unsigned int tag_type; unsigned int tag_offset; unsigned int tag_len; int rc; - /* Split tag into type, offset and length */ + /* Split tag into instance, type, offset and length */ + tag_instance = ( ( setting->tag >> 24 ) & 0xff ); tag_type = ( ( setting->tag >> 16 ) & 0xff ); tag_offset = ( ( setting->tag >> 8 ) & 0xff ); tag_len = ( setting->tag & 0xff ); /* Find SMBIOS structure */ - if ( ( rc = find_smbios_structure ( tag_type, &structure ) ) != 0 ) + if ( ( rc = find_smbios_structure ( tag_type, tag_instance, + &structure ) ) != 0 ) return rc; {