
From: Simon Glass <sjg@chromium.org> The code in the smbios command is a nice implementation of finding the tables. It supports both SMBIOS2 and SMBIOS3, which smbios-parser.c does not. Move this code over to the library, creating a struct to hold the result. Signed-off-by: Simon Glass <sjg@chromium.org> --- Changes in v2: - Fix the return values on error cmd/smbios.c | 52 ++++++++++++--------------------------------- include/smbios.h | 27 +++++++++++++++++++++++ lib/smbios-parser.c | 45 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 39 deletions(-) diff --git a/cmd/smbios.c b/cmd/smbios.c index 8dd31190a01..830cd513ad7 100644 --- a/cmd/smbios.c +++ b/cmd/smbios.c @@ -377,56 +377,30 @@ static void smbios_print_type127(struct smbios_type127 *table) static int do_smbios(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - ulong addr; - void *entry; - u32 size; - char version[12]; - struct smbios_header *table; - static const char smbios_sig[] = "_SM_"; - static const char smbios3_sig[] = "_SM3_"; - size_t count = 0; - u32 table_maximum_size; - - addr = gd_smbios_start(); - if (!addr) { + struct smbios_info info; + int ret; + + ret = smbios_locate(gd_smbios_start(), &info); + if (ret == -ENOENT) { log_warning("SMBIOS not available\n"); return CMD_RET_FAILURE; } - entry = map_sysmem(addr, 0); - if (!memcmp(entry, smbios3_sig, sizeof(smbios3_sig) - 1)) { - struct smbios3_entry *entry3 = entry; - - table = (void *)(uintptr_t)entry3->struct_table_address; - snprintf(version, sizeof(version), "%d.%d.%d", - entry3->major_ver, entry3->minor_ver, entry3->doc_rev); - table = (void *)(uintptr_t)entry3->struct_table_address; - size = entry3->length; - table_maximum_size = entry3->table_maximum_size; - } else if (!memcmp(entry, smbios_sig, sizeof(smbios_sig) - 1)) { - struct smbios_entry *entry2 = entry; - - snprintf(version, sizeof(version), "%d.%d", - entry2->major_ver, entry2->minor_ver); - table = (void *)(uintptr_t)entry2->struct_table_address; - size = entry2->length; - table_maximum_size = entry2->struct_table_length; - } else { + if (ret == -EINVAL) { log_err("Unknown SMBIOS anchor format\n"); return CMD_RET_FAILURE; } - if (table_compute_checksum(entry, size)) { + if (ret == -EIO) { log_err("Invalid anchor checksum\n"); return CMD_RET_FAILURE; } - printf("SMBIOS %s present.\n", version); + printf("SMBIOS %d.%d.%d present.\n", info.version >> 16, + (info.version >> 8) & 0xff, info.version & 0xff); - for (struct smbios_header *pos = table; pos; - pos = smbios_next_table(pos)) - ++count; - printf("%zd structures occupying %d bytes\n", count, table_maximum_size); - printf("Table at 0x%llx\n", (unsigned long long)map_to_sysmem(table)); + printf("%d structures occupying %d bytes\n", info.count, info.max_size); + printf("Table at 0x%llx\n", + (unsigned long long)map_to_sysmem(info.table)); - for (struct smbios_header *pos = table; pos; + for (struct smbios_header *pos = info.table; pos; pos = smbios_next_table(pos)) { printf("\nHandle 0x%04x, DMI type %d, %d bytes at 0x%llx\n", pos->handle, pos->type, pos->length, diff --git a/include/smbios.h b/include/smbios.h index 1415de1c5d0..44f16309a8d 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -15,6 +15,23 @@ #define SMBIOS_MAJOR_VER 3 #define SMBIOS_MINOR_VER 7 +/** + * struct smbios_info - Information about SMBIOS tables + * + * @table: Pointer to the first table + * @count: Number of tables + * @max_size: Maximum size of the tables pointed to by struct_table_address + * @version: table version in the form 0xMMmmrr, where MM is the major version + * number (2 or 3), mm is the minor version number and rr is * the revision + * (always 0 for major-version 2) + */ +struct smbios_info { + struct smbios_header *table; + int count; + int max_size; + int version; +}; + enum { SMBIOS_STR_MAX = 64, /* Maximum length allowed for a string */ }; @@ -401,4 +418,14 @@ const char *smbios_get_string(void *table, int index); */ struct smbios_header *smbios_next_table(struct smbios_header *table); +/** + * smbios_locate() - Locate the SMBIOS tables + * + * @addr: Address of SMBIOS table, typically gd_smbios_start() + * @info: Returns the SMBIOS info, on success + * Return: 0 if OK, -EINVAL if the address is 0, -NOENT if the header signature + * is not recognised, -EIO if the checksum is wrong + */ +int smbios_locate(ulong addr, struct smbios_info *info); + #endif /* _SMBIOS_H_ */ diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c index 42c095f3d08..918dd3bef48 100644 --- a/lib/smbios-parser.c +++ b/lib/smbios-parser.c @@ -6,11 +6,15 @@ #define LOG_CATEGORY LOGC_BOOT #include <errno.h> +#include <mapmem.h> #include <smbios.h> #include <string.h> #include <tables_csum.h> +#include <asm/global_data.h> #include <linux/kernel.h> +DECLARE_GLOBAL_DATA_PTR; + const char *smbios_get_string(void *table, int index) { const char *str = (char *)table + @@ -277,3 +281,44 @@ void smbios_prepare_measurement(const struct smbios3_entry *entry, smbios_filter_tables[i].count); } } + +int smbios_locate(ulong addr, struct smbios_info *info) +{ + static const char smbios3_sig[] = "_SM3_"; + static const char smbios_sig[] = "_SM_"; + void *entry; + uint size; + + if (!addr) + return -EINVAL; + + entry = map_sysmem(addr, 0); + if (!memcmp(entry, smbios3_sig, sizeof(smbios3_sig) - 1)) { + struct smbios3_entry *entry3 = entry; + + info->table = (void *)(uintptr_t)entry3->struct_table_address; + info->version = entry3->major_ver << 16 | + entry3->minor_ver << 8 | entry3->doc_rev; + size = entry3->length; + info->max_size = entry3->table_maximum_size; + } else if (!memcmp(entry, smbios_sig, sizeof(smbios_sig) - 1)) { + struct smbios_entry *entry2 = entry; + + info->version = entry2->major_ver << 16 | + entry2->minor_ver << 8; + info->table = (void *)(uintptr_t)entry2->struct_table_address; + size = entry2->length; + info->max_size = entry2->struct_table_length; + } else { + return -ENOENT; + } + if (table_compute_checksum(entry, size)) + return -EIO; + + info->count = 0; + for (struct smbios_header *pos = info->table; pos; + pos = smbios_next_table(pos)) + info->count++; + + return 0; +} -- 2.43.0