
From: Simon Glass <sjg@chromium.org> Use the smbios_info struct in this function, so it can deal with any version of SMBIOS table. Also update smbios_update_version_full() to work the same way. Drop find_next_header() which is now unused. Signed-off-by: Simon Glass <sjg@chromium.org> --- board/coreboot/coreboot/sysinfo.c | 12 +++--- include/smbios.h | 8 ++-- lib/efi_loader/efi_tcg2.c | 3 +- lib/smbios-parser.c | 66 +++++++++++++------------------ 4 files changed, 41 insertions(+), 48 deletions(-) diff --git a/board/coreboot/coreboot/sysinfo.c b/board/coreboot/coreboot/sysinfo.c index 5cf5cf3e286..2fb68cbfa92 100644 --- a/board/coreboot/coreboot/sysinfo.c +++ b/board/coreboot/coreboot/sysinfo.c @@ -55,15 +55,15 @@ static int cb_get_str(struct udevice *dev, int id, size_t size, char *val) static int cb_detect(struct udevice *dev) { struct cb_sysinfo_priv *priv = dev_get_priv(dev); - const struct smbios_entry *smbios; + struct smbios_info info; + int ret; - smbios = smbios_entry(lib_sysinfo.smbios_start, - lib_sysinfo.smbios_size); - if (!smbios) + ret = smbios_locate(lib_sysinfo.smbios_start, &info); + if (ret) return 0; - priv->bios = smbios_get_header(smbios, SMBIOS_BIOS_INFORMATION); - priv->system = smbios_get_header(smbios, SMBIOS_SYSTEM_INFORMATION); + priv->bios = smbios_get_header(&info, SMBIOS_BIOS_INFORMATION); + priv->system = smbios_get_header(&info, SMBIOS_SYSTEM_INFORMATION); priv->t0 = (struct smbios_type0 *)priv->bios; priv->t1 = (struct smbios_type1 *)priv->system; diff --git a/include/smbios.h b/include/smbios.h index 1e9f7ddceb9..16d3b0305d1 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -348,8 +348,8 @@ const struct smbios_entry *smbios_entry(u64 address, u32 size); * @type: SMBIOS type * @return: NULL or a valid pointer to a struct smbios_header */ -const struct smbios_header * -smbios_get_header(const struct smbios_entry *entry, int type); +const struct smbios_header *smbios_get_header(const struct smbios_info *info, + int type); /** * smbios_string() - Return string from SMBIOS @@ -397,9 +397,11 @@ int smbios_update_version_full(void *smbios_tab, const char *version); * * @entry: pointer to a struct smbios3_entry * @header: pointer to a struct smbios_header + * @table_maximum_size: number of bytes used by the tables at @header */ void smbios_prepare_measurement(const struct smbios3_entry *entry, - struct smbios_header *header); + struct smbios_header *smbios_copy, + int table_maximum_size); /** * smbios_get_string() - get SMBIOS string from table diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c index 1832eeb5dce..f1276ca7293 100644 --- a/lib/efi_loader/efi_tcg2.c +++ b/lib/efi_loader/efi_tcg2.c @@ -1127,7 +1127,8 @@ tcg2_measure_smbios(struct udevice *dev, (void *)((uintptr_t)entry->struct_table_address), entry->table_maximum_size); - smbios_prepare_measurement(entry, smbios_copy); + smbios_prepare_measurement(entry, smbios_copy, + entry->table_maximum_size); ret = measure_event(dev, 1, EV_EFI_HANDOFF_TABLES2, event_size, (u8 *)event); diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c index b05fc28d95f..d941930f754 100644 --- a/lib/smbios-parser.c +++ b/lib/smbios-parser.c @@ -62,36 +62,17 @@ const struct smbios_entry *smbios_entry(u64 address, u32 size) return entry; } -static u8 *find_next_header(u8 *pos) -{ - /* search for _double_ NULL bytes */ - while (!((*pos == 0) && (*(pos + 1) == 0))) - pos++; - - /* step behind the double NULL bytes */ - pos += 2; - - return pos; -} - -static struct smbios_header *get_next_header(const struct smbios_header *curr) -{ - u8 *pos = ((u8 *)curr) + curr->length; - - return (struct smbios_header *)find_next_header(pos); -} - -const struct smbios_header *smbios_get_header(const struct smbios_entry *entry, +const struct smbios_header *smbios_get_header(const struct smbios_info *info, int type) { - const unsigned int num_header = entry->struct_count; - const struct smbios_header *header = (struct smbios_header *)((uintptr_t)entry->struct_table_address); + struct smbios_header *header; - for (unsigned int i = 0; i < num_header; i++) { + for (header = info->table; header; + header = smbios_next_table(info, header)) { if (header->type == type) return header; - header = get_next_header(header); + header = smbios_next_table(info, header); } return NULL; @@ -126,15 +107,21 @@ char *smbios_string(const struct smbios_header *header, int index) return string_from_smbios_table(header, index); } -int smbios_update_version_full(void *smbios_tab, const char *version) +int smbios_update_version_full(void *smbios_tab, const char *new_version) { const struct smbios_header *hdr; + struct smbios_info info; struct smbios_type0 *bios; uint old_len, len; char *ptr; + int ret; + + ret = smbios_locate(map_to_sysmem(smbios_tab), &info); + if (ret) + return log_msg_ret("tab", -ENOENT); log_info("Updating SMBIOS table at %p\n", smbios_tab); - hdr = smbios_get_header(smbios_tab, SMBIOS_BIOS_INFORMATION); + hdr = smbios_get_header(&info, SMBIOS_BIOS_INFORMATION); if (!hdr) return log_msg_ret("tab", -ENOENT); bios = (struct smbios_type0 *)hdr; @@ -149,12 +136,12 @@ int smbios_update_version_full(void *smbios_tab, const char *version) * are not disturbed. See smbios_add_string() */ old_len = strnlen(ptr, SMBIOS_STR_MAX); - len = strnlen(version, SMBIOS_STR_MAX); + len = strnlen(new_version, SMBIOS_STR_MAX); if (len > old_len) return log_ret(-ENOSPC); log_debug("Replacing SMBIOS type 0 version string '%s'\n", ptr); - memcpy(ptr, version, len); + memcpy(ptr, new_version, len); #ifdef LOG_DEBUG print_buffer((ulong)ptr, ptr, 1, old_len + 1, 0); #endif @@ -260,23 +247,26 @@ static void clear_smbios_table(struct smbios_header *header, } void smbios_prepare_measurement(const struct smbios3_entry *entry, - struct smbios_header *smbios_copy) + struct smbios_header *smbios_copy, + int table_maximum_size) { - u32 i, j; - void *table_end; - struct smbios_header *header; + struct smbios_info info; + u32 i; - table_end = (void *)((u8 *)smbios_copy + entry->table_maximum_size); + info.table = smbios_copy; + info.count = 0; /* unknown */ + info.max_size = table_maximum_size; + info.version = 3 << 16; for (i = 0; i < ARRAY_SIZE(smbios_filter_tables); i++) { - header = smbios_copy; - for (j = 0; (void *)header < table_end; j++) { + struct smbios_header *header; + + for (header = info.table; header; + header = smbios_next_table(&info, header)) { if (header->type == smbios_filter_tables[i].type) break; - - header = get_next_header(header); } - if ((void *)header >= table_end) + if (!header) continue; clear_smbios_table(header, -- 2.43.0