[PATCH v2 0/8] SMBIOS improvements

Motivations for changes: Current SMBIOS library and command-line tool is not fully matching with the requirements: 1. Missing support for other mandatory types (#7, #9, #16, #17, #19). 2. Only a few platforms support SMBIOS node from the device tree. 3. Values of some fields are hardcoded in the library other than fetching from the device hardware. 4. Embedded data with dynamic length is not supported (E.g. Contained Object Handles in Type #2 and Contained Elements in Type #3)
Changes: 1. Refactor the SMBIOS library and command-line tool to better align with the SMBIOS spec. 2. Create an arch-specific driver for all aarch64-based platforms to fetch SMBIOS private data from the device hardware (processor and cache). 3. Create a sysinfo driver to poppulate platform SMBIOS private data. 4. Add generic SMBIOS DTS file for arm64 platforms for those common strings and values which cannot be retrieved from the system registers. Vendors can create their own SMBIOS node using this as an example. For those boards without SMBIOS nodes, this DTS file can be included to have a generic SMBIOS information of the system. 5. Add support for Type #7 (Cache Information) and link its handles to Type #4.
Once this patch is acceptted, subsequent patch sets will add other missing types (#9, #16, #17, #19).
Tests: To test this with QEMU arm64, please follow the guide on dt_qemu.rst to get a merged DT to run with. ``` qemu-system-arm -machine virt -machine dumpdtb=qemu.dtb cat <(dtc -I dtb qemu.dtb) <(dtc -I dtb ./dts/dt.dtb | grep -v /dts-v1/) \ | dtc - -o merged.dtb qemu-system-arm -machine virt -nographic -bios u-boot.bin -dtb merged.dtb ```
Known issues: It hits the image size limitation on R-CAR board(rcar3_salvator-x). ``` u-boot.img exceeds file size limit: limit: 0x100000 bytes actual: 0x10049d bytes excess: 0x49d bytes ``` This board needs a clean-up to reserve spaces for the changes as SMBIOS is a fundamental feature.
Below is the breakdown of the size-growth of the related functions: function old new delta static.smbios_write_type4 252 1052 +800 static.smbios_write_type7 - 764 +764 static.smbios_write_type3 188 488 +300 smbios_get_val_si - 128 +128 static.smbios_write_type2 316 376 +60 sysinfo_get_data - 56 +56 static.smbios_write_type1 380 396 +16 smbios_write_funcs 112 128 +16 ofnode_read_u32 - 12 +12 sysinfo_rcar_ops 40 48 +8 install_smbios_table 468 472 +4
Raymond Mao (8): smbios: Refactor the smbios headfile sysinfo: Add sysinfo API for accessing data area sysinfo: Add sysinfo driver and data structure for smbios smbios: Refactor smbios library armv8: Add arch-specific sysinfo platform driver armv8: Add generic smbios information into the device tree cmd: update smbios cmd configs: Enable sysinfo for QEMU Arm64
arch/arm/cpu/armv8/Makefile | 2 + arch/arm/cpu/armv8/sysinfo.c | 292 +++++++++++++++++++ arch/arm/dts/qemu-arm64.dts | 4 + arch/arm/dts/smbios_generic.dtsi | 82 ++++++ cmd/smbios.c | 346 ++++++++++++++++++++--- configs/qemu_arm64_defconfig | 2 + drivers/misc/Kconfig | 2 +- drivers/sysinfo/smbios.c | 228 +++++++++++++++ drivers/sysinfo/sysinfo-uclass.c | 20 ++ include/smbios.h | 158 ++++++----- include/smbios_def.h | 191 +++++++++++++ include/smbios_plat.h | 79 ++++++ include/sysinfo.h | 125 ++++++++- lib/smbios.c | 462 ++++++++++++++++++++++++++----- test/py/tests/test_smbios.py | 2 +- 15 files changed, 1822 insertions(+), 173 deletions(-) create mode 100644 arch/arm/cpu/armv8/sysinfo.c create mode 100644 arch/arm/dts/smbios_generic.dtsi create mode 100644 include/smbios_def.h create mode 100644 include/smbios_plat.h

Move the smbios field definitions to a separated simple headfile, which is a prerequisite to be included by dts files. Add new definitions for cache information. This patch also includes a few of code optimizations in smbios.
Signed-off-by: Raymond Mao raymond.mao@linaro.org --- Changes in v2 - Initial patch.
cmd/smbios.c | 4 +- include/smbios.h | 81 +++--------------- include/smbios_def.h | 191 +++++++++++++++++++++++++++++++++++++++++++ lib/smbios.c | 44 +++++----- 4 files changed, 228 insertions(+), 92 deletions(-) create mode 100644 include/smbios_def.h
diff --git a/cmd/smbios.c b/cmd/smbios.c index d3bd8b12a67..2122ac04e55 100644 --- a/cmd/smbios.c +++ b/cmd/smbios.c @@ -99,12 +99,12 @@ static void smbios_print_type1(struct smbios_type1 *table) smbios_print_str("Product Name", table, table->product_name); smbios_print_str("Version", table, table->version); smbios_print_str("Serial Number", table, table->serial_number); - if (table->length >= 0x19) { + if (table->hdr.length >= SMBIOS_TYPE1_LENGTH_V21) { printf("\tUUID: %pUl\n", table->uuid); printf("\tWake-up Type: %s\n", smbios_wakeup_type_str(table->wakeup_type)); } - if (table->length >= 0x1b) { + if (table->hdr.length >= SMBIOS_TYPE1_LENGTH_V24) { smbios_print_str("SKU Number", table, table->sku_number); smbios_print_str("Family", table, table->family); } diff --git a/include/smbios.h b/include/smbios.h index 00119d7a60c..78fd14d881b 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -9,6 +9,7 @@ #define _SMBIOS_H_
#include <linux/types.h> +#include <smbios_def.h>
/* SMBIOS spec version implemented */ #define SMBIOS_MAJOR_VER 3 @@ -80,19 +81,14 @@ struct __packed smbios3_entry { u64 struct_table_address; };
-/* BIOS characteristics */ -#define BIOS_CHARACTERISTICS_PCI_SUPPORTED (1 << 7) -#define BIOS_CHARACTERISTICS_UPGRADEABLE (1 << 11) -#define BIOS_CHARACTERISTICS_SELECTABLE_BOOT (1 << 16) - -#define BIOS_CHARACTERISTICS_EXT1_ACPI (1 << 0) -#define BIOS_CHARACTERISTICS_EXT2_UEFI (1 << 3) -#define BIOS_CHARACTERISTICS_EXT2_TARGET (1 << 2) - -struct __packed smbios_type0 { +struct __packed smbios_header { u8 type; u8 length; u16 handle; +}; + +struct __packed smbios_type0 { + struct smbios_header hdr; u8 vendor; u8 bios_ver; u16 bios_start_segment; @@ -109,37 +105,12 @@ struct __packed smbios_type0 { char eos[SMBIOS_STRUCT_EOS_BYTES]; };
-/** - * enum smbios_wakeup_type - wake-up type - * - * These constants are used for the Wake-Up Type field in the SMBIOS - * System Information (Type 1) structure. - */ -enum smbios_wakeup_type { - /** @SMBIOS_WAKEUP_TYPE_RESERVED: Reserved */ - SMBIOS_WAKEUP_TYPE_RESERVED, - /** @SMBIOS_WAKEUP_TYPE_OTHER: Other */ - SMBIOS_WAKEUP_TYPE_OTHER, - /** @SMBIOS_WAKEUP_TYPE_UNKNOWN: Unknown */ - SMBIOS_WAKEUP_TYPE_UNKNOWN, - /** @SMBIOS_WAKEUP_TYPE_APM_TIMER: APM Timer */ - SMBIOS_WAKEUP_TYPE_APM_TIMER, - /** @SMBIOS_WAKEUP_TYPE_MODEM_RING: Modem Ring */ - SMBIOS_WAKEUP_TYPE_MODEM_RING, - /** @SMBIOS_WAKEUP_TYPE_LAN_REMOTE: LAN Remote */ - SMBIOS_WAKEUP_TYPE_LAN_REMOTE, - /** @SMBIOS_WAKEUP_TYPE_POWER_SWITCH: Power Switch */ - SMBIOS_WAKEUP_TYPE_POWER_SWITCH, - /** @SMBIOS_WAKEUP_TYPE_PCI_PME: PCI PME# */ - SMBIOS_WAKEUP_TYPE_PCI_PME, - /** @SMBIOS_WAKEUP_TYPE_AC_POWER_RESTORED: AC Power Restored */ - SMBIOS_WAKEUP_TYPE_AC_POWER_RESTORED, -}; +#define SMBIOS_TYPE1_LENGTH_V20 0x08 +#define SMBIOS_TYPE1_LENGTH_V21 0x19 +#define SMBIOS_TYPE1_LENGTH_V24 0x1b
struct __packed smbios_type1 { - u8 type; - u8 length; - u16 handle; + struct smbios_header hdr; u8 manufacturer; u8 product_name; u8 version; @@ -151,13 +122,8 @@ struct __packed smbios_type1 { char eos[SMBIOS_STRUCT_EOS_BYTES]; };
-#define SMBIOS_BOARD_FEATURE_HOSTING (1 << 0) -#define SMBIOS_BOARD_MOTHERBOARD 10 - struct __packed smbios_type2 { - u8 type; - u8 length; - u16 handle; + struct smbios_header hdr; u8 manufacturer; u8 product_name; u8 version; @@ -171,14 +137,8 @@ struct __packed smbios_type2 { char eos[SMBIOS_STRUCT_EOS_BYTES]; };
-#define SMBIOS_ENCLOSURE_DESKTOP 3 -#define SMBIOS_STATE_SAFE 3 -#define SMBIOS_SECURITY_NONE 3 - struct __packed smbios_type3 { - u8 type; - u8 length; - u16 handle; + struct smbios_header hdr; u8 manufacturer; u8 chassis_type; u8 version; @@ -196,17 +156,8 @@ struct __packed smbios_type3 { char eos[SMBIOS_STRUCT_EOS_BYTES]; };
-#define SMBIOS_PROCESSOR_TYPE_CENTRAL 3 -#define SMBIOS_PROCESSOR_STATUS_ENABLED 1 -#define SMBIOS_PROCESSOR_UPGRADE_NONE 6 - -#define SMBIOS_PROCESSOR_FAMILY_OTHER 1 -#define SMBIOS_PROCESSOR_FAMILY_UNKNOWN 2 - struct __packed smbios_type4 { - u8 type; - u8 length; - u16 handle; + struct smbios_header hdr; u8 socket_designation; u8 processor_type; u8 processor_family; @@ -252,12 +203,6 @@ struct __packed smbios_type127 { char eos[SMBIOS_STRUCT_EOS_BYTES]; };
-struct __packed smbios_header { - u8 type; - u8 length; - u16 handle; -}; - /** * fill_smbios_header() - Fill the header of an SMBIOS table * diff --git a/include/smbios_def.h b/include/smbios_def.h new file mode 100644 index 00000000000..f49a18cd7b0 --- /dev/null +++ b/include/smbios_def.h @@ -0,0 +1,191 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2024 Linaro Limited + * Author: Raymond Mao raymond.mao@linaro.org + */ + +#ifndef _SMBIOS_DEF_H_ +#define _SMBIOS_DEF_H_ + +/* + * BIOS characteristics + */ + +#define BIOS_CHARACTERISTICS_PCI_SUPPORTED 0x80 /* BIT(7) */ +#define BIOS_CHARACTERISTICS_UPGRADEABLE 0x800 /* BIT(11) */ +#define BIOS_CHARACTERISTICS_SELECTABLE_BOOT 0x10000 /* BIT(16) */ + +#define BIOS_CHARACTERISTICS_EXT1_ACPI 1 /* BIT(0) */ +#define BIOS_CHARACTERISTICS_EXT2_UEFI 8 /* BIT(3) */ +#define BIOS_CHARACTERISTICS_EXT2_TARGET 4 /* BIT(2) */ + +/* + * System Information + */ + +#define SMBIOS_WAKEUP_TYPE_RESERVED 0 +#define SMBIOS_WAKEUP_TYPE_OTHER 1 +#define SMBIOS_WAKEUP_TYPE_UNKNOWN 2 +#define SMBIOS_WAKEUP_TYPE_APM_TIMER 3 +#define SMBIOS_WAKEUP_TYPE_MODEM_RING 4 +#define SMBIOS_WAKEUP_TYPE_LAN_REMOTE 5 +#define SMBIOS_WAKEUP_TYPE_POWER_SWITCH 6 +#define SMBIOS_WAKEUP_TYPE_PCI_PME 7 +#define SMBIOS_WAKEUP_TYPE_AC_POWER_RESTORED 8 + +/* + * Baseboard Information + */ + +#define SMBIOS_BOARD_FEAT_HOST_BOARD 1 /* BIT(0) */ +#define SMBIOS_BOARD_FEAT_REQ_AUX 2 /* BIT(1) */ +#define SMBIOS_BOARD_FEAT_REMOVABLE 4 /* BIT(2) */ +#define SMBIOS_BOARD_FEAT_REPLACEABLE 8 /* BIT(3) */ +#define SMBIOS_BOARD_FEAT_HOT_SWAPPABLE 16 /* BIT(4) */ + +#define SMBIOS_BOARD_TYPE_UNKNOWN 1 +#define SMBIOS_BOARD_TYPE_OTHER 2 +#define SMBIOS_BOARD_TYPE_SERVER_BLADE 3 +#define SMBIOS_BOARD_TYPE_CON_SWITCH 4 +#define SMBIOS_BOARD_TYPE_SM_MODULE 5 +#define SMBIOS_BOARD_TYPE_PROCESSOR_MODULE 6 +#define SMBIOS_BOARD_TYPE_IO_MODULE 7 +#define SMBIOS_BOARD_TYPE_MEM_MODULE 8 +#define SMBIOS_BOARD_TYPE_DAUGHTER_BOARD 9 +#define SMBIOS_BOARD_TYPE_MOTHERBOARD 10 +#define SMBIOS_BOARD_TYPE_PROC_MEM_MODULE 11 +#define SMBIOS_BOARD_TYPE_PROC_IO_MODULE 12 +#define SMBIOS_BOARD_TYPE_INTERCON 13 + +/* + * System Enclosure or Chassis + */ + +#define SMBIOS_ENCLOSURE_DESKTOP 3 + +#define SMBIOS_STATE_OTHER 1 +#define SMBIOS_STATE_UNKNOWN 2 +#define SMBIOS_STATE_SAFE 3 +#define SMBIOS_STATE_WARNING 4 +#define SMBIOS_STATE_CRITICAL 5 +#define SMBIOS_STATE_NONRECOVERABLE 6 + +#define SMBIOS_SECURITY_OTHER 1 +#define SMBIOS_SECURITY_UNKNOWN 2 +#define SMBIOS_SECURITY_NONE 3 +#define SMBIOS_SECURITY_EXTINT_LOCK 4 +#define SMBIOS_SECURITY_EXTINT_EN 5 + +#define SMBIOS_ENCLOSURE_OEM_UND 0 +#define SMBIOS_ENCLOSURE_HEIGHT_UND 0 +#define SMBIOS_POWCORD_NUM_UND 0 +#define SMBIOS_ELEMENT_TYPE_SELECT 0x80 /* BIT(7) */ + +/* + * Processor Information + */ + +#define SMBIOS_PROCESSOR_TYPE_OTHER 1 +#define SMBIOS_PROCESSOR_TYPE_UNKNOWN 2 +#define SMBIOS_PROCESSOR_TYPE_CENTRAL 3 +#define SMBIOS_PROCESSOR_TYPE_MATH 4 +#define SMBIOS_PROCESSOR_TYPE_DSP 5 +#define SMBIOS_PROCESSOR_TYPE_VIDEO 6 + +#define SMBIOS_PROCESSOR_STATUS_UNKNOWN 0 +#define SMBIOS_PROCESSOR_STATUS_ENABLED 1 +#define SMBIOS_PROCESSOR_STATUS_DISABLED_USER 2 +#define SMBIOS_PROCESSOR_STATUS_DISABLED_BIOS 3 +#define SMBIOS_PROCESSOR_STATUS_IDLE 4 +#define SMBIOS_PROCESSOR_STATUS_OTHER 7 + +#define SMBIOS_PROCESSOR_UPGRADE_OTHER 1 +#define SMBIOS_PROCESSOR_UPGRADE_UNKNOWN 2 +#define SMBIOS_PROCESSOR_UPGRADE_NONE 6 + +#define SMBIOS_PROCESSOR_FAMILY_OTHER 1 +#define SMBIOS_PROCESSOR_FAMILY_UNKNOWN 2 +#define SMBIOS_PROCESSOR_FAMILY_RSVD 255 +#define SMBIOS_PROCESSOR_FAMILY_ARMV7 256 +#define SMBIOS_PROCESSOR_FAMILY_ARMV8 257 +#define SMBIOS_PROCESSOR_FAMILY_RV32 512 +#define SMBIOS_PROCESSOR_FAMILY_RV64 513 + +#define SMBIOS_PROCESSOR_FAMILY_EXT 0xfe + +/* Processor Characteristics */ +#define SMBIOS_PROCESSOR_RSVD 1 /* BIT(0) */ +#define SMBIOS_PROCESSOR_UND 2 /* BIT(1) */ +#define SMBIOS_PROCESSOR_64BIT 4 /* BIT(2) */ +#define SMBIOS_PROCESSOR_MULTICORE 8 /* BIT(3) */ +#define SMBIOS_PROCESSOR_HWTHREAD 16 /* BIT(4) */ +#define SMBIOS_PROCESSOR_EXEC_PROT 32 /* BIT(5) */ +#define SMBIOS_PROCESSOR_ENH_VIRT 64 /* BIT(6) */ +#define SMBIOS_PROCESSOR_POW_CON 0x80 /* BIT(7) */ +#define SMBIOS_PROCESSOR_128BIT 0x100 /* BIT(8) */ +#define SMBIOS_PROCESSOR_ARM64_SOCID 0x200 /* BIT(9) */ + +/* + * Cache Information + */ + +#define SMBIOS_CACHE_SIZE_EXT_KB (2047 * 1024) /* 2047 MiB */ +#define SMBIOS_CACHE_HANDLE_NONE 0xffff + +/* System Cache Type */ +#define SMBIOS_CACHE_SYSCACHE_TYPE_OTHER 1 +#define SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN 2 +#define SMBIOS_CACHE_SYSCACHE_TYPE_INST 3 +#define SMBIOS_CACHE_SYSCACHE_TYPE_DATA 4 +#define SMBIOS_CACHE_SYSCACHE_TYPE_UNIFIED 5 + +/* Cache Speed */ +#define SMBIOS_CACHE_SPEED_UNKNOWN 0 + +/* Error Correction Type */ +#define SMBIOS_CACHE_ERRCORR_OTHER 1 +#define SMBIOS_CACHE_ERRCORR_UNKNOWN 2 +#define SMBIOS_CACHE_ERRCORR_NONE 3 +#define SMBIOS_CACHE_ERRCORR_PARITY 4 +#define SMBIOS_CACHE_ERRCORR_SBITECC 5 +#define SMBIOS_CACHE_ERRCORR_MBITECC 6 + +/* Cache Configuration */ +#define SMBIOS_CACHE_LEVEL_1 0 +#define SMBIOS_CACHE_LEVEL_2 1 +#define SMBIOS_CACHE_LEVEL_3 2 +#define SMBIOS_CACHE_LEVEL_4 3 +#define SMBIOS_CACHE_LEVEL_5 4 +#define SMBIOS_CACHE_LEVEL_6 5 +#define SMBIOS_CACHE_LEVEL_7 6 +#define SMBIOS_CACHE_LEVEL_8 7 +#define SMBIOS_CACHE_SOCKETED 8 /* BIT(3) */ +#define SMBIOS_CACHE_LOCATE_EXTERNAL 32 /* BIT(5) */ +#define SMBIOS_CACHE_LOCATE_RESERVED 64 /* BIT(6) */ +#define SMBIOS_CACHE_LOCATE_UNKNOWN 96 /* (BIT(5) | BIT(6)) */ +#define SMBIOS_CACHE_ENABLED 0x80 /* BIT(7) */ +#define SMBIOS_CACHE_OP_WB 0x100 /* BIT(8), Write Back */ +#define SMBIOS_CACHE_OP_VAR 0x200 /* BIT(9), Varies with Memory Address */ +#define SMBIOS_CACHE_OP_UND 0x300 /* (BIT(8) | BIT(9)), Unknown*/ + +/* Cache Granularity */ +#define SMBIOS_CACHE_GRANU_1K 0 +#define SMBIOS_CACHE_GRANU_64K 1 + +/* Cache Associativity */ +#define SMBIOS_CACHE_ASSOC_OTHER 1 +#define SMBIOS_CACHE_ASSOC_UNKNOWN 2 +#define SMBIOS_CACHE_ASSOC_DMAPPED 3 +#define SMBIOS_CACHE_ASSOC_2WAY 4 +#define SMBIOS_CACHE_ASSOC_4WAY 5 +#define SMBIOS_CACHE_ASSOC_FULLY 6 +#define SMBIOS_CACHE_ASSOC_8WAY 7 +#define SMBIOS_CACHE_ASSOC_16WAY 8 +#define SMBIOS_CACHE_ASSOC_12WAY 9 +#define SMBIOS_CACHE_ASSOC_24WAY 10 +#define SMBIOS_CACHE_ASSOC_32WAY 11 +#define SMBIOS_CACHE_ASSOC_48WAY 12 +#define SMBIOS_CACHE_ASSOC_64WAY 13 +#define SMBIOS_CACHE_ASSOC_20WAY 14 + +#endif /* _SMBIOS_DEF_H_ */ diff --git a/lib/smbios.c b/lib/smbios.c index 7c24ea129eb..886c40e7594 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -330,10 +330,10 @@ static int smbios_write_type0(ulong *current, int handle, struct smbios_ctx *ctx) { struct smbios_type0 *t; - int len = sizeof(struct smbios_type0); + int len = sizeof(*t);
t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type0)); + memset(t, 0, len); fill_smbios_header(t, SMBIOS_BIOS_INFORMATION, len, handle); smbios_set_eos(ctx, t->eos); t->vendor = smbios_add_prop(ctx, NULL, "U-Boot"); @@ -374,7 +374,7 @@ static int smbios_write_type0(ulong *current, int handle, t->ec_major_release = 0xff; t->ec_minor_release = 0xff;
- len = t->length + smbios_string_table_len(ctx); + len = t->hdr.length + smbios_string_table_len(ctx); *current += len; unmap_sysmem(t);
@@ -385,11 +385,11 @@ static int smbios_write_type1(ulong *current, int handle, struct smbios_ctx *ctx) { struct smbios_type1 *t; - int len = sizeof(struct smbios_type1); + int len = sizeof(*t); char *serial_str = env_get("serial#");
t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type1)); + memset(t, 0, len); fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, handle); smbios_set_eos(ctx, t->eos); t->manufacturer = smbios_add_prop_si(ctx, "manufacturer", @@ -403,7 +403,7 @@ static int smbios_write_type1(ulong *current, int handle, NULL); if (serial_str) { t->serial_number = smbios_add_prop(ctx, NULL, serial_str); - strncpy((char *)t->uuid, serial_str, sizeof(t->uuid)); + strlcpy((char *)t->uuid, serial_str, sizeof(t->uuid)); } else { t->serial_number = smbios_add_prop_si(ctx, "serial", SYSINFO_ID_SMBIOS_SYSTEM_SERIAL, @@ -415,7 +415,7 @@ static int smbios_write_type1(ulong *current, int handle, t->family = smbios_add_prop_si(ctx, "family", SYSINFO_ID_SMBIOS_SYSTEM_FAMILY, NULL);
- len = t->length + smbios_string_table_len(ctx); + len = t->hdr.length + smbios_string_table_len(ctx); *current += len; unmap_sysmem(t);
@@ -426,10 +426,10 @@ static int smbios_write_type2(ulong *current, int handle, struct smbios_ctx *ctx) { struct smbios_type2 *t; - int len = sizeof(struct smbios_type2); + int len = sizeof(*t);
t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type2)); + memset(t, 0, len); fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, handle); smbios_set_eos(ctx, t->eos); t->manufacturer = smbios_add_prop_si(ctx, "manufacturer", @@ -448,11 +448,11 @@ static int smbios_write_type2(ulong *current, int handle, t->asset_tag_number = smbios_add_prop_si(ctx, "asset-tag", SYSINFO_ID_SMBIOS_BASEBOARD_ASSET_TAG, NULL); - t->feature_flags = SMBIOS_BOARD_FEATURE_HOSTING; - t->board_type = SMBIOS_BOARD_MOTHERBOARD; + t->feature_flags = SMBIOS_BOARD_FEAT_HOST_BOARD; + t->board_type = SMBIOS_BOARD_TYPE_MOTHERBOARD; t->chassis_handle = handle + 1;
- len = t->length + smbios_string_table_len(ctx); + len = t->hdr.length + smbios_string_table_len(ctx); *current += len; unmap_sysmem(t);
@@ -463,10 +463,10 @@ static int smbios_write_type3(ulong *current, int handle, struct smbios_ctx *ctx) { struct smbios_type3 *t; - int len = sizeof(struct smbios_type3); + int len = sizeof(*t);
t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type3)); + memset(t, 0, len); fill_smbios_header(t, SMBIOS_SYSTEM_ENCLOSURE, len, handle); smbios_set_eos(ctx, t->eos); t->manufacturer = smbios_add_prop(ctx, "manufacturer", NULL); @@ -476,7 +476,7 @@ static int smbios_write_type3(ulong *current, int handle, t->thermal_state = SMBIOS_STATE_SAFE; t->security_status = SMBIOS_SECURITY_NONE;
- len = t->length + smbios_string_table_len(ctx); + len = t->hdr.length + smbios_string_table_len(ctx); *current += len; unmap_sysmem(t);
@@ -521,10 +521,10 @@ static int smbios_write_type4(ulong *current, int handle, struct smbios_ctx *ctx) { struct smbios_type4 *t; - int len = sizeof(struct smbios_type4); + int len = sizeof(*t);
t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type4)); + memset(t, 0, len); fill_smbios_header(t, SMBIOS_PROCESSOR_INFORMATION, len, handle); smbios_set_eos(ctx, t->eos); t->processor_type = SMBIOS_PROCESSOR_TYPE_CENTRAL; @@ -535,7 +535,7 @@ static int smbios_write_type4(ulong *current, int handle, t->l2_cache_handle = 0xffff; t->l3_cache_handle = 0xffff;
- len = t->length + smbios_string_table_len(ctx); + len = t->hdr.length + smbios_string_table_len(ctx); *current += len; unmap_sysmem(t);
@@ -546,10 +546,10 @@ static int smbios_write_type32(ulong *current, int handle, struct smbios_ctx *ctx) { struct smbios_type32 *t; - int len = sizeof(struct smbios_type32); + int len = sizeof(*t);
t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type32)); + memset(t, 0, len); fill_smbios_header(t, SMBIOS_SYSTEM_BOOT_INFORMATION, len, handle); smbios_set_eos(ctx, t->eos);
@@ -563,10 +563,10 @@ static int smbios_write_type127(ulong *current, int handle, struct smbios_ctx *ctx) { struct smbios_type127 *t; - int len = sizeof(struct smbios_type127); + int len = sizeof(*t);
t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type127)); + memset(t, 0, len); fill_smbios_header(t, SMBIOS_END_OF_TABLE, len, handle);
*current += len;

On Tue, 22 Oct 2024 at 22:06, Raymond Mao raymond.mao@linaro.org wrote:
Move the smbios field definitions to a separated simple headfile, which is a prerequisite to be included by dts files. Add new definitions for cache information. This patch also includes a few of code optimizations in smbios.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
Changes in v2
- Initial patch.
cmd/smbios.c | 4 +- include/smbios.h | 81 +++--------------- include/smbios_def.h | 191 +++++++++++++++++++++++++++++++++++++++++++ lib/smbios.c | 44 +++++----- 4 files changed, 228 insertions(+), 92 deletions(-) create mode 100644 include/smbios_def.h
Reviewed-by: Simon Glass sjg@chromium.org

Add interface for sysinfo to access a data area from the platform. This is useful to save/read a memory region of platform-specific data.
Signed-off-by: Raymond Mao raymond.mao@linaro.org --- Changes in v2 - None.
drivers/sysinfo/sysinfo-uclass.c | 20 ++++++++++++++++++++ include/sysinfo.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+)
diff --git a/drivers/sysinfo/sysinfo-uclass.c b/drivers/sysinfo/sysinfo-uclass.c index d77d1e3ee44..04a7748834a 100644 --- a/drivers/sysinfo/sysinfo-uclass.c +++ b/drivers/sysinfo/sysinfo-uclass.c @@ -99,6 +99,26 @@ int sysinfo_get_str(struct udevice *dev, int id, size_t size, char *val) return ops->get_str(dev, id, size, val); }
+int sysinfo_get_data(struct udevice *dev, int id, uchar **data, size_t *size) +{ + struct sysinfo_priv *priv; + struct sysinfo_ops *ops; + + if (!dev) + return -ENOSYS; + + priv = dev_get_uclass_priv(dev); + ops = sysinfo_get_ops(dev); + + if (!priv->detected) + return -EPERM; + + if (!ops->get_data) + return -ENOSYS; + + return ops->get_data(dev, id, data, size); +} + UCLASS_DRIVER(sysinfo) = { .id = UCLASS_SYSINFO, .name = "sysinfo", diff --git a/include/sysinfo.h b/include/sysinfo.h index 8a77ef44856..17b2b9c7111 100644 --- a/include/sysinfo.h +++ b/include/sysinfo.h @@ -115,6 +115,18 @@ struct sysinfo_ops { */ int (*get_str)(struct udevice *dev, int id, size_t size, char *val);
+ /** + * get_data() - Read a specific string data value that describes the + * hardware setup. + * @dev: The sysinfo instance to gather the data. + * @id: A unique identifier for the data area to be get. + * @data: Pointer to the address of the data area. + * @size: Pointer to the size of the data area. + * + * Return: 0 if OK, -ve on error. + */ + int (*get_data)(struct udevice *dev, int id, uchar **data, size_t *size); + /** * get_fit_loadable - Get the name of an image to load from FIT * This function can be used to provide the image names based on runtime @@ -186,6 +198,18 @@ int sysinfo_get_int(struct udevice *dev, int id, int *val); */ int sysinfo_get_str(struct udevice *dev, int id, size_t size, char *val);
+/** + * sysinfo_get_data() - Get a data area from the platform. + * @dev: The sysinfo instance to gather the data. + * @id: A unique identifier for the data area to be get. + * @data: Pointer to the address of the data area. + * @size: Pointer to the size of the data area. + * + * Return: 0 if OK, -EPERM if called before sysinfo_detect(), else -ve on + * error. + */ +int sysinfo_get_data(struct udevice *dev, int id, uchar **data, size_t *size); + /** * sysinfo_get() - Return the sysinfo device for the sysinfo in question. * @devp: Pointer to structure to receive the sysinfo device. @@ -241,6 +265,12 @@ static inline int sysinfo_get_str(struct udevice *dev, int id, size_t size, return -ENOSYS; }
+static inline int sysinfo_get_data(struct udevice *dev, int id, uchar **data, + size_t *size) +{ + return -ENOSYS; +} + static inline int sysinfo_get(struct udevice **devp) { return -ENOSYS;

On Tue, 22 Oct 2024 at 22:06, Raymond Mao raymond.mao@linaro.org wrote:
Add interface for sysinfo to access a data area from the platform. This is useful to save/read a memory region of platform-specific data.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
Changes in v2
- None.
drivers/sysinfo/sysinfo-uclass.c | 20 ++++++++++++++++++++ include/sysinfo.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+)
Please update the test for this.
Regards, Simon

Add sysinfo driver to retrieve smbios information (Type 4 and 7). So that the smbios library can use it for getting values from the hardware platform instead of device tree.
Signed-off-by: Raymond Mao raymond.mao@linaro.org --- Changes in v2 - Move the changes to smbios.c instead of creating new file. - Move the headfile to include dir. - Combine with #6(v1) patch. - Clean-up the private data structures. - Clean-up the operations of the strings and common values.
drivers/sysinfo/smbios.c | 228 +++++++++++++++++++++++++++++++++++++++ include/smbios.h | 60 +++++++++++ include/smbios_plat.h | 79 ++++++++++++++ include/sysinfo.h | 95 +++++++++++++++- 4 files changed, 461 insertions(+), 1 deletion(-) create mode 100644 include/smbios_plat.h
diff --git a/drivers/sysinfo/smbios.c b/drivers/sysinfo/smbios.c index a7ac8e3f072..3980845b3ba 100644 --- a/drivers/sysinfo/smbios.c +++ b/drivers/sysinfo/smbios.c @@ -5,14 +5,240 @@ */
#include <dm.h> +#include <smbios_plat.h> #include <sysinfo.h>
+/* platform information storage */ +struct processor_info processor_info; +struct cache_info cache_info[SYSINFO_CACHE_LVL_MAX]; +struct sysinfo_plat sysinfo_smbios_p = { + /* Processor Information */ + .processor = &processor_info, + /* Cache Information */ + .cache = &cache_info[0], +}; + +/* structure for smbios private data storage */ +struct sysinfo_plat_priv { + struct processor_info *t4; + struct smbios_type7 t7[SYSINFO_CACHE_LVL_MAX]; + u16 cache_handles[SYSINFO_CACHE_LVL_MAX]; + u8 cache_level; +}; + +static void smbios_cache_info_dump(struct smbios_type7 *cache_info) +{ + log_debug("SMBIOS Type 7 (Cache Information):\n"); + log_debug("Cache Configuration: 0x%04x\n", cache_info->config.data); + log_debug("Maximum Cache Size: %u KB\n", cache_info->max_size.data); + log_debug("Installed Size: %u KB\n", cache_info->inst_size.data); + log_debug("Supported SRAM Type: 0x%04x\n", + cache_info->supp_sram_type.data); + log_debug("Current SRAM Type: 0x%04x\n", + cache_info->curr_sram_type.data); + log_debug("Cache Speed: %u\n", cache_info->speed); + log_debug("Error Correction Type: %u\n", cache_info->err_corr_type); + log_debug("System Cache Type: %u\n", cache_info->sys_cache_type); + log_debug("Associativity: %u\n", cache_info->associativity); + log_debug("Maximum Cache Size 2: %u KB\n", cache_info->max_size2.data); + log_debug("Installed Cache Size 2: %u KB\n", + cache_info->inst_size2.data); +} + +/* weak function for the platforms not yet supported */ +__weak int sysinfo_get_cache_info(u8 level, struct cache_info *cache_info) +{ + return -ENOSYS; +} + +__weak int sysinfo_get_processor_info(struct processor_info *pinfo) +{ + return -ENOSYS; +} + +void sysinfo_cache_info_default(struct cache_info *ci) +{ + memset(ci, 0, sizeof(*ci)); + ci->config.data = SMBIOS_CACHE_LOCATE_UNKNOWN | SMBIOS_CACHE_OP_UND; + ci->supp_sram_type.fields.unknown = 1; + ci->curr_sram_type.fields.unknown = 1; + ci->speed = SMBIOS_CACHE_SPEED_UNKNOWN; + ci->err_corr_type = SMBIOS_CACHE_ERRCORR_UNKNOWN; + ci->cache_type = SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN; +} + +static int sysinfo_plat_detect(struct udevice *dev) +{ + return 0; +} + +static int sysinfo_plat_get_str(struct udevice *dev, int id, + size_t size, char *val) +{ + struct sysinfo_plat_priv *priv = dev_get_priv(dev); + const char *str = NULL; + + switch (id) { + case SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT: + str = priv->t4->manufacturer; + break; + default: + break; + } + + if (!str) + return -ENOSYS; + + strlcpy(val, str, size); + + return 0; +} + +static int sysinfo_plat_get_int(struct udevice *dev, int id, int *val) +{ + struct sysinfo_plat_priv *priv = dev_get_priv(dev); + u8 i; + + if (id >= SYSINFO_ID_SMBIOS_CACHE_INFO_START && + id <= SYSINFO_ID_SMBIOS_CACHE_INFO_END) { + /* For smbios type 7 */ + for (i = 0; i < priv->cache_level; i++) { + switch (id - i) { + case SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE: + *val = priv->t7[i].max_size.data; + return 0; + case SYSINFO_ID_SMBIOS_CACHE_INST_SIZE: + *val = priv->t7[i].inst_size.data; + return 0; + case SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE: + *val = priv->t7[i].sys_cache_type; + return 0; + case SYSINFO_ID_SMBIOS_CACHE_ASSOC: + *val = priv->t7[i].associativity; + return 0; + case SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2: + *val = priv->t7[i].max_size2.data; + return 0; + case SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2: + *val = priv->t7[i].inst_size2.data; + return 0; + default: + break; + } + } + return -ENOSYS; + } + + switch (id) { + case SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT: + *val = priv->t4->core_count; + break; + case SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN: + *val = priv->t4->core_enabled; + break; + case SYSINFO_ID_SMBIOS_PROCESSOR_CHARA: + *val = priv->t4->characteristics; + break; + case SYSINFO_ID_SMBIOS_CACHE_LEVEL: + if (!priv->cache_level) /* No cache detected */ + return -ENOSYS; + *val = priv->cache_level - 1; + break; + default: + return -ENOSYS; + } + + return 0; +} + +static int sysinfo_plat_get_data(struct udevice *dev, int id, uchar **buf, + size_t *size) +{ + struct sysinfo_plat_priv *priv = dev_get_priv(dev); + + switch (id) { + case SYSINFO_ID_SMBIOS_PROCESSOR_ID: + *buf = (uchar *)priv->t4->id; + *size = sizeof(priv->t4->id); + break; + case SYSINFO_ID_SMBIOS_CACHE_HANDLE: + *buf = (uchar *)(&priv->cache_handles[0]); + *size = sizeof(priv->cache_handles); + break; + default: + return -EOPNOTSUPP; + } + return 0; +} + +static int sysinfo_plat_probe(struct udevice *dev) +{ + struct sysinfo_plat_priv *priv = dev_get_priv(dev); + struct sysinfo_plat *plat = &sysinfo_smbios_p; + u8 level; + + if (!sysinfo_get_processor_info(plat->processor)) + priv->t4 = plat->processor; + + for (level = 0; level < SYSINFO_CACHE_LVL_MAX; level++) { + struct cache_info *pcache = plat->cache + level; + + if (sysinfo_get_cache_info(level, pcache)) + break; /* no more levels */ + + /* + * Fill in the SMBIOS type 7 structure, + * skip the header members (type, length, handle), + * and the ones in DT smbios node. + */ + priv->t7[level].sys_cache_type = pcache->cache_type; + priv->t7[level].associativity = pcache->associativity; + + if (pcache->max_size > SMBIOS_CACHE_SIZE_EXT_KB) { + priv->t7[level].max_size.data = 0xFFFF; + priv->t7[level].max_size2.fields.size = + pcache->max_size / 64; + priv->t7[level].max_size2.fields.granu = + SMBIOS_CACHE_GRANU_64K; + } else { + priv->t7[level].max_size.fields.size = pcache->max_size; + priv->t7[level].max_size.fields.granu = + SMBIOS_CACHE_GRANU_1K; + priv->t7[level].max_size2.data = 0; + } + if (pcache->inst_size > SMBIOS_CACHE_SIZE_EXT_KB) { + priv->t7[level].inst_size.data = 0xFFFF; + priv->t7[level].inst_size2.fields.size = + pcache->inst_size / 64; + priv->t7[level].inst_size2.fields.granu = + SMBIOS_CACHE_GRANU_64K; + } else { + priv->t7[level].inst_size.fields.size = + pcache->inst_size; + priv->t7[level].inst_size.fields.granu = + SMBIOS_CACHE_GRANU_1K; + priv->t7[level].inst_size2.data = 0; + } + smbios_cache_info_dump(&priv->t7[level]); + } + if (!level) /* no cache detected */ + return -ENOSYS; + + priv->cache_level = level; + + return 0; +} + static const struct udevice_id sysinfo_smbios_ids[] = { { .compatible = "u-boot,sysinfo-smbios" }, { /* sentinel */ } };
static const struct sysinfo_ops sysinfo_smbios_ops = { + .detect = sysinfo_plat_detect, + .get_str = sysinfo_plat_get_str, + .get_int = sysinfo_plat_get_int, + .get_data = sysinfo_plat_get_data, };
U_BOOT_DRIVER(sysinfo_smbios) = { @@ -20,4 +246,6 @@ U_BOOT_DRIVER(sysinfo_smbios) = { .id = UCLASS_SYSINFO, .of_match = sysinfo_smbios_ids, .ops = &sysinfo_smbios_ops, + .priv_auto = sizeof(struct sysinfo_plat_priv), + .probe = sysinfo_plat_probe, }; diff --git a/include/smbios.h b/include/smbios.h index 78fd14d881b..cb4b3e08b3a 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -187,6 +187,66 @@ struct __packed smbios_type4 { char eos[SMBIOS_STRUCT_EOS_BYTES]; };
+union cache_config { + struct { + u16 level:3; + u16 bsocketed:1; + u16 rsvd0:1; + u16 locate:2; + u16 benabled:1; + u16 opmode:2; + u16 rsvd1:6; + } fields; + u16 data; +}; + +union cache_size_word { + struct { + u16 size:15; + u16 granu:1; + } fields; + u16 data; +}; + +union cache_size_dword { + struct { + u32 size:31; + u32 granu:1; + } fields; + u32 data; +}; + +union cache_sram_type { + struct { + u16 other:1; + u16 unknown:1; + u16 nonburst:1; + u16 burst:1; + u16 plburst:1; + u16 sync:1; + u16 async:1; + u16 rsvd:9; + } fields; + u16 data; +}; + +struct __packed smbios_type7 { + struct smbios_header hdr; + u8 socket_design; + union cache_config config; + union cache_size_word max_size; + union cache_size_word inst_size; + union cache_sram_type supp_sram_type; + union cache_sram_type curr_sram_type; + u8 speed; + u8 err_corr_type; + u8 sys_cache_type; + u8 associativity; + union cache_size_dword max_size2; + union cache_size_dword inst_size2; + char eos[SMBIOS_STRUCT_EOS_BYTES]; +}; + struct __packed smbios_type32 { u8 type; u8 length; diff --git a/include/smbios_plat.h b/include/smbios_plat.h new file mode 100644 index 00000000000..70089d5a2ba --- /dev/null +++ b/include/smbios_plat.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2024 Linaro Limited + * Author: Raymond Mao raymond.mao@linaro.org + */ +#ifndef __SMBIOS_PLAT_H +#define __SMBIOS_PLAT_H + +#include <smbios.h> + +struct cache_info { + union cache_config config; + union cache_sram_type supp_sram_type; + union cache_sram_type curr_sram_type; + u32 line_size; + u32 associativity; + u32 max_size; + u32 inst_size; + u8 cache_type; + u8 speed; + u8 err_corr_type; + char *socket_design; +}; + +struct processor_info { + u32 id[2]; + u16 ext_clock; + u16 max_speed; + u16 curr_speed; + u16 characteristics; + u16 family2; + u16 core_count2; + u16 core_enabled2; + u16 thread_count2; + u16 thread_enabled; + u8 type; + u8 family; + u8 voltage; + u8 status; + u8 upgrade; + u8 core_count; + u8 core_enabled; + u8 thread_count; + char *socket_design; + char *manufacturer; + char *version; + char *sn; + char *asset_tag; + char *pn; +}; + +struct sysinfo_plat { + struct processor_info *processor; + struct cache_info *cache; + /* add other sysinfo structure here */ +}; + +#if defined CONFIG_SYSINFO_SMBIOS +int sysinfo_get_cache_info(u8 level, struct cache_info *cache_info); +void sysinfo_cache_info_default(struct cache_info *ci); +int sysinfo_get_processor_info(struct processor_info *pinfo); +#else +static inline int sysinfo_get_cache_info(u8 level, + struct cache_info *cache_info) +{ + return -ENOSYS; +} + +static inline void sysinfo_cache_info_default(struct cache_info *ci) +{ +} + +static inline int sysinfo_get_processor_info(struct processor_info *pinfo) +{ + return -ENOSYS; +} +#endif + +#endif /* __SMBIOS_PLAT_H */ diff --git a/include/sysinfo.h b/include/sysinfo.h index 17b2b9c7111..cb08a691270 100644 --- a/include/sysinfo.h +++ b/include/sysinfo.h @@ -11,6 +11,8 @@
struct udevice;
+#define SYSINFO_CACHE_LVL_MAX 3 + /* * This uclass encapsulates hardware methods to gather information about a * sysinfo or a specific device such as hard-wired GPIOs on GPIO expanders, @@ -42,18 +44,109 @@ struct udevice; enum sysinfo_id { SYSINFO_ID_NONE,
- /* For SMBIOS tables */ + /* BIOS Information (Type 0) */ + SYSINFO_ID_SMBIOS_BIOS_VENDOR, + SYSINFO_ID_SMBIOS_BIOS_VER, + SYSINFO_ID_SMBIOS_BIOS_REL_DATE, + + /* System Information (Type 1) */ SYSINFO_ID_SMBIOS_SYSTEM_MANUFACTURER, SYSINFO_ID_SMBIOS_SYSTEM_PRODUCT, SYSINFO_ID_SMBIOS_SYSTEM_VERSION, SYSINFO_ID_SMBIOS_SYSTEM_SERIAL, + SYSINFO_ID_SMBIOS_SYSTEM_WAKEUP, SYSINFO_ID_SMBIOS_SYSTEM_SKU, SYSINFO_ID_SMBIOS_SYSTEM_FAMILY, + + /* Baseboard (or Module) Information (Type 2) */ SYSINFO_ID_SMBIOS_BASEBOARD_MANUFACTURER, SYSINFO_ID_SMBIOS_BASEBOARD_PRODUCT, SYSINFO_ID_SMBIOS_BASEBOARD_VERSION, SYSINFO_ID_SMBIOS_BASEBOARD_SERIAL, SYSINFO_ID_SMBIOS_BASEBOARD_ASSET_TAG, + SYSINFO_ID_SMBIOS_BASEBOARD_FEATURE, + SYSINFO_ID_SMBIOS_BASEBOARD_CHASSIS_LOCAT, + SYSINFO_ID_SMBIOS_BASEBOARD_TYPE, + SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_NUM, + SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_HANDLE, + + /* System Enclosure or Chassis (Type 3) */ + SYSINFO_ID_SMBIOS_ENCLOSURE_MANUFACTURER, + SYSINFO_ID_SMBIOS_ENCLOSURE_VERSION, + SYSINFO_ID_SMBIOS_ENCLOSURE_SERIAL, + SYSINFO_ID_SMBIOS_ENCLOSURE_ASSET_TAG, + SYSINFO_ID_SMBIOS_ENCLOSURE_TYPE, + SYSINFO_ID_SMBIOS_ENCLOSURE_BOOTUP, + SYSINFO_ID_SMBIOS_ENCLOSURE_POW, + SYSINFO_ID_SMBIOS_ENCLOSURE_THERMAL, + SYSINFO_ID_SMBIOS_ENCLOSURE_SECURITY, + SYSINFO_ID_SMBIOS_ENCLOSURE_OEM, + SYSINFO_ID_SMBIOS_ENCLOSURE_HEIGHT, + SYSINFO_ID_SMBIOS_ENCLOSURE_POWCORE_NUM, + SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_CNT, + SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_LEN, + SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENTS, + SYSINFO_ID_SMBIOS_ENCLOSURE_SKU, + + /* Processor Information (Type 4) */ + SYSINFO_ID_SMBIOS_PROCESSOR_SOCKET, + SYSINFO_ID_SMBIOS_PROCESSOR_TYPE, + SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT, + SYSINFO_ID_SMBIOS_PROCESSOR_ID, + SYSINFO_ID_SMBIOS_PROCESSOR_VERSION, + SYSINFO_ID_SMBIOS_PROCESSOR_VOLTAGE, + SYSINFO_ID_SMBIOS_PROCESSOR_EXT_CLOCK, + SYSINFO_ID_SMBIOS_PROCESSOR_MAX_SPEED, + SYSINFO_ID_SMBIOS_PROCESSOR_CUR_SPEED, + SYSINFO_ID_SMBIOS_PROCESSOR_STATUS, + SYSINFO_ID_SMBIOS_PROCESSOR_UPGRADE, + SYSINFO_ID_SMBIOS_PROCESSOR_SN, + SYSINFO_ID_SMBIOS_PROCESSOR_ASSET_TAG, + SYSINFO_ID_SMBIOS_PROCESSOR_PN, + SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT, + SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN, + SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT, + SYSINFO_ID_SMBIOS_PROCESSOR_CHARA, + SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY, + SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY2, + SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT2, + SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN2, + SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT2, + SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_EN, + + /* + * Cache Information (Type 7) + * Each of the id should reserve space for up to + * SYSINFO_CACHE_LVL_MAX levels of cache + */ + SYSINFO_ID_SMBIOS_CACHE_LEVEL, + SYSINFO_ID_SMBIOS_CACHE_HANDLE, + SYSINFO_ID_SMBIOS_CACHE_INFO_START, + SYSINFO_ID_SMBIOS_CACHE_SOCKET = SYSINFO_ID_SMBIOS_CACHE_INFO_START, + SYSINFO_ID_SMBIOS_CACHE_CONFIG = + SYSINFO_ID_SMBIOS_CACHE_SOCKET + SYSINFO_CACHE_LVL_MAX, + SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE = + SYSINFO_ID_SMBIOS_CACHE_CONFIG + SYSINFO_CACHE_LVL_MAX, + SYSINFO_ID_SMBIOS_CACHE_INST_SIZE = + SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE + SYSINFO_CACHE_LVL_MAX, + SYSINFO_ID_SMBIOS_CACHE_SUPSRAM_TYPE = + SYSINFO_ID_SMBIOS_CACHE_INST_SIZE + SYSINFO_CACHE_LVL_MAX, + SYSINFO_ID_SMBIOS_CACHE_CURSRAM_TYPE = + SYSINFO_ID_SMBIOS_CACHE_SUPSRAM_TYPE + SYSINFO_CACHE_LVL_MAX, + SYSINFO_ID_SMBIOS_CACHE_SPEED = + SYSINFO_ID_SMBIOS_CACHE_CURSRAM_TYPE + SYSINFO_CACHE_LVL_MAX, + SYSINFO_ID_SMBIOS_CACHE_ERRCOR_TYPE = + SYSINFO_ID_SMBIOS_CACHE_SPEED + SYSINFO_CACHE_LVL_MAX, + SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE = + SYSINFO_ID_SMBIOS_CACHE_ERRCOR_TYPE + SYSINFO_CACHE_LVL_MAX, + SYSINFO_ID_SMBIOS_CACHE_ASSOC = + SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE + SYSINFO_CACHE_LVL_MAX, + SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2 = + SYSINFO_ID_SMBIOS_CACHE_ASSOC + SYSINFO_CACHE_LVL_MAX, + SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2 = + SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2 + SYSINFO_CACHE_LVL_MAX, + SYSINFO_ID_SMBIOS_CACHE_INFO_END = + SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2 + SYSINFO_CACHE_LVL_MAX - 1,
/* For show_board_info() */ SYSINFO_ID_BOARD_MODEL,

Hi Raymond,
On Tue, 22 Oct 2024 at 22:06, Raymond Mao raymond.mao@linaro.org wrote:
Add sysinfo driver to retrieve smbios information (Type 4 and 7). So that the smbios library can use it for getting values from the hardware platform instead of device tree.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
Changes in v2
- Move the changes to smbios.c instead of creating new file.
- Move the headfile to include dir.
- Combine with #6(v1) patch.
- Clean-up the private data structures.
- Clean-up the operations of the strings and common values.
drivers/sysinfo/smbios.c | 228 +++++++++++++++++++++++++++++++++++++++ include/smbios.h | 60 +++++++++++ include/smbios_plat.h | 79 ++++++++++++++ include/sysinfo.h | 95 +++++++++++++++- 4 files changed, 461 insertions(+), 1 deletion(-) create mode 100644 include/smbios_plat.h
diff --git a/drivers/sysinfo/smbios.c b/drivers/sysinfo/smbios.c index a7ac8e3f072..3980845b3ba 100644 --- a/drivers/sysinfo/smbios.c +++ b/drivers/sysinfo/smbios.c @@ -5,14 +5,240 @@ */
#include <dm.h> +#include <smbios_plat.h> #include <sysinfo.h>
+/* platform information storage */ +struct processor_info processor_info; +struct cache_info cache_info[SYSINFO_CACHE_LVL_MAX]; +struct sysinfo_plat sysinfo_smbios_p = {
/* Processor Information */
.processor = &processor_info,
/* Cache Information */
.cache = &cache_info[0],
+};
+/* structure for smbios private data storage */ +struct sysinfo_plat_priv {
struct processor_info *t4;
struct smbios_type7 t7[SYSINFO_CACHE_LVL_MAX];
u16 cache_handles[SYSINFO_CACHE_LVL_MAX];
u8 cache_level;
+};
+static void smbios_cache_info_dump(struct smbios_type7 *cache_info) +{
log_debug("SMBIOS Type 7 (Cache Information):\n");
log_debug("Cache Configuration: 0x%04x\n",
cache_info->config.data);
log_debug("Maximum Cache Size: %u KB\n",
cache_info->max_size.data);
log_debug("Installed Size: %u KB\n", cache_info->inst_size.data);
log_debug("Supported SRAM Type: 0x%04x\n",
%#04x
cache_info->supp_sram_type.data);
log_debug("Current SRAM Type: 0x%04x\n",
cache_info->curr_sram_type.data);
log_debug("Cache Speed: %u\n", cache_info->speed);
log_debug("Error Correction Type: %u\n",
cache_info->err_corr_type);
log_debug("System Cache Type: %u\n", cache_info->sys_cache_type);
log_debug("Associativity: %u\n", cache_info->associativity);
log_debug("Maximum Cache Size 2: %u KB\n",
cache_info->max_size2.data);
log_debug("Installed Cache Size 2: %u KB\n",
cache_info->inst_size2.data);
+}
+/* weak function for the platforms not yet supported */ +__weak int sysinfo_get_cache_info(u8 level, struct cache_info
*cache_info)
+{
return -ENOSYS;
+}
+__weak int sysinfo_get_processor_info(struct processor_info *pinfo) +{
return -ENOSYS;
+}
+void sysinfo_cache_info_default(struct cache_info *ci) +{
memset(ci, 0, sizeof(*ci));
ci->config.data = SMBIOS_CACHE_LOCATE_UNKNOWN |
SMBIOS_CACHE_OP_UND;
ci->supp_sram_type.fields.unknown = 1;
ci->curr_sram_type.fields.unknown = 1;
ci->speed = SMBIOS_CACHE_SPEED_UNKNOWN;
ci->err_corr_type = SMBIOS_CACHE_ERRCORR_UNKNOWN;
ci->cache_type = SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN;
+}
+static int sysinfo_plat_detect(struct udevice *dev) +{
return 0;
+}
+static int sysinfo_plat_get_str(struct udevice *dev, int id,
size_t size, char *val)
+{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
const char *str = NULL;
switch (id) {
case SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT:
These are getting too long.
How about SYSINFOSM_PROC_MANUF ?
We can use SYSINFOSM as short for SYSINFO_ID_SMBIOS
str = priv->t4->manufacturer;
break;
default:
break;
}
if (!str)
return -ENOSYS;
strlcpy(val, str, size);
return 0;
+}
+static int sysinfo_plat_get_int(struct udevice *dev, int id, int *val) +{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
u8 i;
if (id >= SYSINFO_ID_SMBIOS_CACHE_INFO_START &&
id <= SYSINFO_ID_SMBIOS_CACHE_INFO_END) {
/* For smbios type 7 */
for (i = 0; i < priv->cache_level; i++) {
switch (id - i) {
case SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE:
*val = priv->t7[i].max_size.data;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_INST_SIZE:
*val = priv->t7[i].inst_size.data;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE:
*val = priv->t7[i].sys_cache_type;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_ASSOC:
*val = priv->t7[i].associativity;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2:
*val = priv->t7[i].max_size2.data;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2:
*val = priv->t7[i].inst_size2.data;
return 0;
default:
break;
}
}
return -ENOSYS;
}
switch (id) {
case SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT:
*val = priv->t4->core_count;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN:
*val = priv->t4->core_enabled;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_CHARA:
*val = priv->t4->characteristics;
break;
case SYSINFO_ID_SMBIOS_CACHE_LEVEL:
if (!priv->cache_level) /* No cache detected */
return -ENOSYS;
*val = priv->cache_level - 1;
break;
default:
return -ENOSYS;
}
return 0;
+}
+static int sysinfo_plat_get_data(struct udevice *dev, int id, uchar
**buf,
How about void **, so we don't need to cast below?
size_t *size)
+{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
switch (id) {
case SYSINFO_ID_SMBIOS_PROCESSOR_ID:
*buf = (uchar *)priv->t4->id;
*size = sizeof(priv->t4->id);
break;
case SYSINFO_ID_SMBIOS_CACHE_HANDLE:
*buf = (uchar *)(&priv->cache_handles[0]);
Isn't that the same as:
*buf = (uchar *)&priv->cache_handles;
*size = sizeof(priv->cache_handles);
break;
default:
return -EOPNOTSUPP;
}
return 0;
+}
+static int sysinfo_plat_probe(struct udevice *dev) +{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
struct sysinfo_plat *plat = &sysinfo_smbios_p;
u8 level;
if (!sysinfo_get_processor_info(plat->processor))
priv->t4 = plat->processor;
for (level = 0; level < SYSINFO_CACHE_LVL_MAX; level++) {
struct cache_info *pcache = plat->cache + level;
if (sysinfo_get_cache_info(level, pcache))
break; /* no more levels */
/*
* Fill in the SMBIOS type 7 structure,
* skip the header members (type, length, handle),
* and the ones in DT smbios node.
*/
priv->t7[level].sys_cache_type = pcache->cache_type;
priv->t7[level].associativity = pcache->associativity;
if (pcache->max_size > SMBIOS_CACHE_SIZE_EXT_KB) {
priv->t7[level].max_size.data = 0xFFFF;
priv->t7[level].max_size2.fields.size =
pcache->max_size / 64;
priv->t7[level].max_size2.fields.granu =
SMBIOS_CACHE_GRANU_64K;
} else {
priv->t7[level].max_size.fields.size =
pcache->max_size;
priv->t7[level].max_size.fields.granu =
SMBIOS_CACHE_GRANU_1K;
priv->t7[level].max_size2.data = 0;
}
if (pcache->inst_size > SMBIOS_CACHE_SIZE_EXT_KB) {
priv->t7[level].inst_size.data = 0xFFFF;
priv->t7[level].inst_size2.fields.size =
pcache->inst_size / 64;
priv->t7[level].inst_size2.fields.granu =
SMBIOS_CACHE_GRANU_64K;
} else {
priv->t7[level].inst_size.fields.size =
pcache->inst_size;
priv->t7[level].inst_size.fields.granu =
SMBIOS_CACHE_GRANU_1K;
priv->t7[level].inst_size2.data = 0;
}
smbios_cache_info_dump(&priv->t7[level]);
}
if (!level) /* no cache detected */
return -ENOSYS;
priv->cache_level = level;
return 0;
+}
static const struct udevice_id sysinfo_smbios_ids[] = { { .compatible = "u-boot,sysinfo-smbios" }, { /* sentinel */ } };
static const struct sysinfo_ops sysinfo_smbios_ops = {
.detect = sysinfo_plat_detect,
.get_str = sysinfo_plat_get_str,
.get_int = sysinfo_plat_get_int,
.get_data = sysinfo_plat_get_data,
};
U_BOOT_DRIVER(sysinfo_smbios) = { @@ -20,4 +246,6 @@ U_BOOT_DRIVER(sysinfo_smbios) = { .id = UCLASS_SYSINFO, .of_match = sysinfo_smbios_ids, .ops = &sysinfo_smbios_ops,
.priv_auto = sizeof(struct sysinfo_plat_priv),
.probe = sysinfo_plat_probe,
}; diff --git a/include/smbios.h b/include/smbios.h index 78fd14d881b..cb4b3e08b3a 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -187,6 +187,66 @@ struct __packed smbios_type4 { char eos[SMBIOS_STRUCT_EOS_BYTES]; };
+union cache_config {
struct {
u16 level:3;
u16 bsocketed:1;
u16 rsvd0:1;
u16 locate:2;
u16 benabled:1;
u16 opmode:2;
u16 rsvd1:6;
} fields;
u16 data;
+};
+union cache_size_word {
struct {
u16 size:15;
u16 granu:1;
} fields;
u16 data;
+};
+union cache_size_dword {
struct {
u32 size:31;
u32 granu:1;
} fields;
u32 data;
+};
+union cache_sram_type {
struct {
u16 other:1;
u16 unknown:1;
u16 nonburst:1;
u16 burst:1;
u16 plburst:1;
u16 sync:1;
u16 async:1;
u16 rsvd:9;
} fields;
u16 data;
+};
+struct __packed smbios_type7 {
struct smbios_header hdr;
u8 socket_design;
union cache_config config;
union cache_size_word max_size;
union cache_size_word inst_size;
union cache_sram_type supp_sram_type;
union cache_sram_type curr_sram_type;
u8 speed;
u8 err_corr_type;
u8 sys_cache_type;
u8 associativity;
union cache_size_dword max_size2;
union cache_size_dword inst_size2;
char eos[SMBIOS_STRUCT_EOS_BYTES];
+};
struct __packed smbios_type32 { u8 type; u8 length; diff --git a/include/smbios_plat.h b/include/smbios_plat.h new file mode 100644 index 00000000000..70089d5a2ba --- /dev/null +++ b/include/smbios_plat.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (c) 2024 Linaro Limited
- Author: Raymond Mao raymond.mao@linaro.org
- */
+#ifndef __SMBIOS_PLAT_H +#define __SMBIOS_PLAT_H
+#include <smbios.h>
+struct cache_info {
union cache_config config;
union cache_sram_type supp_sram_type;
union cache_sram_type curr_sram_type;
u32 line_size;
u32 associativity;
u32 max_size;
u32 inst_size;
u8 cache_type;
u8 speed;
u8 err_corr_type;
char *socket_design;
+};
+struct processor_info {
u32 id[2];
u16 ext_clock;
u16 max_speed;
u16 curr_speed;
u16 characteristics;
u16 family2;
u16 core_count2;
u16 core_enabled2;
u16 thread_count2;
u16 thread_enabled;
u8 type;
u8 family;
u8 voltage;
u8 status;
u8 upgrade;
u8 core_count;
u8 core_enabled;
u8 thread_count;
char *socket_design;
char *manufacturer;
char *version;
char *sn;
char *asset_tag;
char *pn;
+};
+struct sysinfo_plat {
struct processor_info *processor;
struct cache_info *cache;
/* add other sysinfo structure here */
+};
+#if defined CONFIG_SYSINFO_SMBIOS +int sysinfo_get_cache_info(u8 level, struct cache_info *cache_info); +void sysinfo_cache_info_default(struct cache_info *ci); +int sysinfo_get_processor_info(struct processor_info *pinfo); +#else +static inline int sysinfo_get_cache_info(u8 level,
struct cache_info *cache_info)
+{
return -ENOSYS;
+}
+static inline void sysinfo_cache_info_default(struct cache_info *ci) +{ +}
+static inline int sysinfo_get_processor_info(struct processor_info
*pinfo)
+{
return -ENOSYS;
+} +#endif
+#endif /* __SMBIOS_PLAT_H */ diff --git a/include/sysinfo.h b/include/sysinfo.h index 17b2b9c7111..cb08a691270 100644 --- a/include/sysinfo.h +++ b/include/sysinfo.h @@ -11,6 +11,8 @@
struct udevice;
+#define SYSINFO_CACHE_LVL_MAX 3
/*
- This uclass encapsulates hardware methods to gather information about
a
- sysinfo or a specific device such as hard-wired GPIOs on GPIO
expanders,
@@ -42,18 +44,109 @@ struct udevice; enum sysinfo_id { SYSINFO_ID_NONE,
/* For SMBIOS tables */
/* BIOS Information (Type 0) */
SYSINFO_ID_SMBIOS_BIOS_VENDOR,
SYSINFO_ID_SMBIOS_BIOS_VER,
SYSINFO_ID_SMBIOS_BIOS_REL_DATE,
/* System Information (Type 1) */ SYSINFO_ID_SMBIOS_SYSTEM_MANUFACTURER, SYSINFO_ID_SMBIOS_SYSTEM_PRODUCT, SYSINFO_ID_SMBIOS_SYSTEM_VERSION, SYSINFO_ID_SMBIOS_SYSTEM_SERIAL,
SYSINFO_ID_SMBIOS_SYSTEM_WAKEUP, SYSINFO_ID_SMBIOS_SYSTEM_SKU, SYSINFO_ID_SMBIOS_SYSTEM_FAMILY,
/* Baseboard (or Module) Information (Type 2) */ SYSINFO_ID_SMBIOS_BASEBOARD_MANUFACTURER, SYSINFO_ID_SMBIOS_BASEBOARD_PRODUCT, SYSINFO_ID_SMBIOS_BASEBOARD_VERSION, SYSINFO_ID_SMBIOS_BASEBOARD_SERIAL, SYSINFO_ID_SMBIOS_BASEBOARD_ASSET_TAG,
SYSINFO_ID_SMBIOS_BASEBOARD_FEATURE,
SYSINFO_ID_SMBIOS_BASEBOARD_CHASSIS_LOCAT,
SYSINFO_ID_SMBIOS_BASEBOARD_TYPE,
SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_NUM,
SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_HANDLE,
/* System Enclosure or Chassis (Type 3) */
SYSINFO_ID_SMBIOS_ENCLOSURE_MANUFACTURER,
SYSINFO_ID_SMBIOS_ENCLOSURE_VERSION,
SYSINFO_ID_SMBIOS_ENCLOSURE_SERIAL,
SYSINFO_ID_SMBIOS_ENCLOSURE_ASSET_TAG,
SYSINFO_ID_SMBIOS_ENCLOSURE_TYPE,
SYSINFO_ID_SMBIOS_ENCLOSURE_BOOTUP,
SYSINFO_ID_SMBIOS_ENCLOSURE_POW,
SYSINFO_ID_SMBIOS_ENCLOSURE_THERMAL,
SYSINFO_ID_SMBIOS_ENCLOSURE_SECURITY,
SYSINFO_ID_SMBIOS_ENCLOSURE_OEM,
SYSINFO_ID_SMBIOS_ENCLOSURE_HEIGHT,
SYSINFO_ID_SMBIOS_ENCLOSURE_POWCORE_NUM,
SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_CNT,
SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_LEN,
SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENTS,
SYSINFO_ID_SMBIOS_ENCLOSURE_SKU,
/* Processor Information (Type 4) */
SYSINFO_ID_SMBIOS_PROCESSOR_SOCKET,
SYSINFO_ID_SMBIOS_PROCESSOR_TYPE,
SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT,
SYSINFO_ID_SMBIOS_PROCESSOR_ID,
SYSINFO_ID_SMBIOS_PROCESSOR_VERSION,
SYSINFO_ID_SMBIOS_PROCESSOR_VOLTAGE,
SYSINFO_ID_SMBIOS_PROCESSOR_EXT_CLOCK,
SYSINFO_ID_SMBIOS_PROCESSOR_MAX_SPEED,
SYSINFO_ID_SMBIOS_PROCESSOR_CUR_SPEED,
SYSINFO_ID_SMBIOS_PROCESSOR_STATUS,
SYSINFO_ID_SMBIOS_PROCESSOR_UPGRADE,
SYSINFO_ID_SMBIOS_PROCESSOR_SN,
SYSINFO_ID_SMBIOS_PROCESSOR_ASSET_TAG,
SYSINFO_ID_SMBIOS_PROCESSOR_PN,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN,
SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT,
SYSINFO_ID_SMBIOS_PROCESSOR_CHARA,
SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY,
SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY2,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT2,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN2,
SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT2,
SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_EN,
/*
* Cache Information (Type 7)
* Each of the id should reserve space for up to
* SYSINFO_CACHE_LVL_MAX levels of cache
*/
SYSINFO_ID_SMBIOS_CACHE_LEVEL,
SYSINFO_ID_SMBIOS_CACHE_HANDLE,
SYSINFO_ID_SMBIOS_CACHE_INFO_START,
SYSINFO_ID_SMBIOS_CACHE_SOCKET =
SYSINFO_ID_SMBIOS_CACHE_INFO_START,
SYSINFO_ID_SMBIOS_CACHE_CONFIG =
SYSINFO_ID_SMBIOS_CACHE_SOCKET + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE =
SYSINFO_ID_SMBIOS_CACHE_CONFIG + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE =
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_SUPSRAM_TYPE =
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_CURSRAM_TYPE =
SYSINFO_ID_SMBIOS_CACHE_SUPSRAM_TYPE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_SPEED =
SYSINFO_ID_SMBIOS_CACHE_CURSRAM_TYPE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_ERRCOR_TYPE =
SYSINFO_ID_SMBIOS_CACHE_SPEED + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE =
SYSINFO_ID_SMBIOS_CACHE_ERRCOR_TYPE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_ASSOC =
SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2 =
SYSINFO_ID_SMBIOS_CACHE_ASSOC + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2 =
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2 + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_INFO_END =
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2 +
SYSINFO_CACHE_LVL_MAX - 1,
This seems to be allocating sequential values for each cache? Instead, we should add a 'seq' parameter to get_data()
/* For show_board_info() */ SYSINFO_ID_BOARD_MODEL,
-- 2.25.1
Regards, Simon

Hi Simon,
On Mon, 28 Oct 2024 at 13:04, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Tue, 22 Oct 2024 at 22:06, Raymond Mao raymond.mao@linaro.org wrote:
Add sysinfo driver to retrieve smbios information (Type 4 and 7). So that the smbios library can use it for getting values from the hardware platform instead of device tree.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
Changes in v2
- Move the changes to smbios.c instead of creating new file.
- Move the headfile to include dir.
- Combine with #6(v1) patch.
- Clean-up the private data structures.
- Clean-up the operations of the strings and common values.
drivers/sysinfo/smbios.c | 228 +++++++++++++++++++++++++++++++++++++++ include/smbios.h | 60 +++++++++++ include/smbios_plat.h | 79 ++++++++++++++ include/sysinfo.h | 95 +++++++++++++++- 4 files changed, 461 insertions(+), 1 deletion(-) create mode 100644 include/smbios_plat.h
diff --git a/drivers/sysinfo/smbios.c b/drivers/sysinfo/smbios.c index a7ac8e3f072..3980845b3ba 100644 --- a/drivers/sysinfo/smbios.c +++ b/drivers/sysinfo/smbios.c @@ -5,14 +5,240 @@ */
#include <dm.h> +#include <smbios_plat.h> #include <sysinfo.h>
+/* platform information storage */ +struct processor_info processor_info; +struct cache_info cache_info[SYSINFO_CACHE_LVL_MAX]; +struct sysinfo_plat sysinfo_smbios_p = {
/* Processor Information */
.processor = &processor_info,
/* Cache Information */
.cache = &cache_info[0],
+};
+/* structure for smbios private data storage */ +struct sysinfo_plat_priv {
struct processor_info *t4;
struct smbios_type7 t7[SYSINFO_CACHE_LVL_MAX];
u16 cache_handles[SYSINFO_CACHE_LVL_MAX];
u8 cache_level;
+};
+static void smbios_cache_info_dump(struct smbios_type7 *cache_info) +{
log_debug("SMBIOS Type 7 (Cache Information):\n");
log_debug("Cache Configuration: 0x%04x\n",
cache_info->config.data);
log_debug("Maximum Cache Size: %u KB\n",
cache_info->max_size.data);
log_debug("Installed Size: %u KB\n", cache_info->inst_size.data);
log_debug("Supported SRAM Type: 0x%04x\n",
%#04x
cache_info->supp_sram_type.data);
log_debug("Current SRAM Type: 0x%04x\n",
cache_info->curr_sram_type.data);
log_debug("Cache Speed: %u\n", cache_info->speed);
log_debug("Error Correction Type: %u\n",
cache_info->err_corr_type);
log_debug("System Cache Type: %u\n", cache_info->sys_cache_type);
log_debug("Associativity: %u\n", cache_info->associativity);
log_debug("Maximum Cache Size 2: %u KB\n",
cache_info->max_size2.data);
log_debug("Installed Cache Size 2: %u KB\n",
cache_info->inst_size2.data);
+}
+/* weak function for the platforms not yet supported */ +__weak int sysinfo_get_cache_info(u8 level, struct cache_info
*cache_info)
+{
return -ENOSYS;
+}
+__weak int sysinfo_get_processor_info(struct processor_info *pinfo) +{
return -ENOSYS;
+}
+void sysinfo_cache_info_default(struct cache_info *ci) +{
memset(ci, 0, sizeof(*ci));
ci->config.data = SMBIOS_CACHE_LOCATE_UNKNOWN |
SMBIOS_CACHE_OP_UND;
ci->supp_sram_type.fields.unknown = 1;
ci->curr_sram_type.fields.unknown = 1;
ci->speed = SMBIOS_CACHE_SPEED_UNKNOWN;
ci->err_corr_type = SMBIOS_CACHE_ERRCORR_UNKNOWN;
ci->cache_type = SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN;
+}
+static int sysinfo_plat_detect(struct udevice *dev) +{
return 0;
+}
+static int sysinfo_plat_get_str(struct udevice *dev, int id,
size_t size, char *val)
+{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
const char *str = NULL;
switch (id) {
case SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT:
These are getting too long.
How about SYSINFOSM_PROC_MANUF ?
We can use SYSINFOSM as short for SYSINFO_ID_SMBIOS
Other existing macros are starting from SYSINFO_ID_, so I guess something
reasonable can be SYSINFO_ID_SMB_PROC_MANU.
str = priv->t4->manufacturer;
break;
default:
break;
}
if (!str)
return -ENOSYS;
strlcpy(val, str, size);
return 0;
+}
+static int sysinfo_plat_get_int(struct udevice *dev, int id, int *val) +{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
u8 i;
if (id >= SYSINFO_ID_SMBIOS_CACHE_INFO_START &&
id <= SYSINFO_ID_SMBIOS_CACHE_INFO_END) {
/* For smbios type 7 */
for (i = 0; i < priv->cache_level; i++) {
switch (id - i) {
case SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE:
*val = priv->t7[i].max_size.data;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_INST_SIZE:
*val = priv->t7[i].inst_size.data;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE:
*val = priv->t7[i].sys_cache_type;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_ASSOC:
*val = priv->t7[i].associativity;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2:
*val = priv->t7[i].max_size2.data;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2:
*val = priv->t7[i].inst_size2.data;
return 0;
default:
break;
}
}
return -ENOSYS;
}
switch (id) {
case SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT:
*val = priv->t4->core_count;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN:
*val = priv->t4->core_enabled;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_CHARA:
*val = priv->t4->characteristics;
break;
case SYSINFO_ID_SMBIOS_CACHE_LEVEL:
if (!priv->cache_level) /* No cache detected */
return -ENOSYS;
*val = priv->cache_level - 1;
break;
default:
return -ENOSYS;
}
return 0;
+}
+static int sysinfo_plat_get_data(struct udevice *dev, int id, uchar
**buf,
How about void **, so we don't need to cast below?
size_t *size)
+{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
switch (id) {
case SYSINFO_ID_SMBIOS_PROCESSOR_ID:
*buf = (uchar *)priv->t4->id;
*size = sizeof(priv->t4->id);
break;
case SYSINFO_ID_SMBIOS_CACHE_HANDLE:
*buf = (uchar *)(&priv->cache_handles[0]);
Isn't that the same as:
*buf = (uchar *)&priv->cache_handles;
*size = sizeof(priv->cache_handles);
break;
default:
return -EOPNOTSUPP;
}
return 0;
+}
+static int sysinfo_plat_probe(struct udevice *dev) +{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
struct sysinfo_plat *plat = &sysinfo_smbios_p;
u8 level;
if (!sysinfo_get_processor_info(plat->processor))
priv->t4 = plat->processor;
for (level = 0; level < SYSINFO_CACHE_LVL_MAX; level++) {
struct cache_info *pcache = plat->cache + level;
if (sysinfo_get_cache_info(level, pcache))
break; /* no more levels */
/*
* Fill in the SMBIOS type 7 structure,
* skip the header members (type, length, handle),
* and the ones in DT smbios node.
*/
priv->t7[level].sys_cache_type = pcache->cache_type;
priv->t7[level].associativity = pcache->associativity;
if (pcache->max_size > SMBIOS_CACHE_SIZE_EXT_KB) {
priv->t7[level].max_size.data = 0xFFFF;
priv->t7[level].max_size2.fields.size =
pcache->max_size / 64;
priv->t7[level].max_size2.fields.granu =
SMBIOS_CACHE_GRANU_64K;
} else {
priv->t7[level].max_size.fields.size =
pcache->max_size;
priv->t7[level].max_size.fields.granu =
SMBIOS_CACHE_GRANU_1K;
priv->t7[level].max_size2.data = 0;
}
if (pcache->inst_size > SMBIOS_CACHE_SIZE_EXT_KB) {
priv->t7[level].inst_size.data = 0xFFFF;
priv->t7[level].inst_size2.fields.size =
pcache->inst_size / 64;
priv->t7[level].inst_size2.fields.granu =
SMBIOS_CACHE_GRANU_64K;
} else {
priv->t7[level].inst_size.fields.size =
pcache->inst_size;
priv->t7[level].inst_size.fields.granu =
SMBIOS_CACHE_GRANU_1K;
priv->t7[level].inst_size2.data = 0;
}
smbios_cache_info_dump(&priv->t7[level]);
}
if (!level) /* no cache detected */
return -ENOSYS;
priv->cache_level = level;
return 0;
+}
static const struct udevice_id sysinfo_smbios_ids[] = { { .compatible = "u-boot,sysinfo-smbios" }, { /* sentinel */ } };
static const struct sysinfo_ops sysinfo_smbios_ops = {
.detect = sysinfo_plat_detect,
.get_str = sysinfo_plat_get_str,
.get_int = sysinfo_plat_get_int,
.get_data = sysinfo_plat_get_data,
};
U_BOOT_DRIVER(sysinfo_smbios) = { @@ -20,4 +246,6 @@ U_BOOT_DRIVER(sysinfo_smbios) = { .id = UCLASS_SYSINFO, .of_match = sysinfo_smbios_ids, .ops = &sysinfo_smbios_ops,
.priv_auto = sizeof(struct sysinfo_plat_priv),
.probe = sysinfo_plat_probe,
}; diff --git a/include/smbios.h b/include/smbios.h index 78fd14d881b..cb4b3e08b3a 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -187,6 +187,66 @@ struct __packed smbios_type4 { char eos[SMBIOS_STRUCT_EOS_BYTES]; };
+union cache_config {
struct {
u16 level:3;
u16 bsocketed:1;
u16 rsvd0:1;
u16 locate:2;
u16 benabled:1;
u16 opmode:2;
u16 rsvd1:6;
} fields;
u16 data;
+};
+union cache_size_word {
struct {
u16 size:15;
u16 granu:1;
} fields;
u16 data;
+};
+union cache_size_dword {
struct {
u32 size:31;
u32 granu:1;
} fields;
u32 data;
+};
+union cache_sram_type {
struct {
u16 other:1;
u16 unknown:1;
u16 nonburst:1;
u16 burst:1;
u16 plburst:1;
u16 sync:1;
u16 async:1;
u16 rsvd:9;
} fields;
u16 data;
+};
+struct __packed smbios_type7 {
struct smbios_header hdr;
u8 socket_design;
union cache_config config;
union cache_size_word max_size;
union cache_size_word inst_size;
union cache_sram_type supp_sram_type;
union cache_sram_type curr_sram_type;
u8 speed;
u8 err_corr_type;
u8 sys_cache_type;
u8 associativity;
union cache_size_dword max_size2;
union cache_size_dword inst_size2;
char eos[SMBIOS_STRUCT_EOS_BYTES];
+};
struct __packed smbios_type32 { u8 type; u8 length; diff --git a/include/smbios_plat.h b/include/smbios_plat.h new file mode 100644 index 00000000000..70089d5a2ba --- /dev/null +++ b/include/smbios_plat.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (c) 2024 Linaro Limited
- Author: Raymond Mao raymond.mao@linaro.org
- */
+#ifndef __SMBIOS_PLAT_H +#define __SMBIOS_PLAT_H
+#include <smbios.h>
+struct cache_info {
union cache_config config;
union cache_sram_type supp_sram_type;
union cache_sram_type curr_sram_type;
u32 line_size;
u32 associativity;
u32 max_size;
u32 inst_size;
u8 cache_type;
u8 speed;
u8 err_corr_type;
char *socket_design;
+};
+struct processor_info {
u32 id[2];
u16 ext_clock;
u16 max_speed;
u16 curr_speed;
u16 characteristics;
u16 family2;
u16 core_count2;
u16 core_enabled2;
u16 thread_count2;
u16 thread_enabled;
u8 type;
u8 family;
u8 voltage;
u8 status;
u8 upgrade;
u8 core_count;
u8 core_enabled;
u8 thread_count;
char *socket_design;
char *manufacturer;
char *version;
char *sn;
char *asset_tag;
char *pn;
+};
+struct sysinfo_plat {
struct processor_info *processor;
struct cache_info *cache;
/* add other sysinfo structure here */
+};
+#if defined CONFIG_SYSINFO_SMBIOS +int sysinfo_get_cache_info(u8 level, struct cache_info *cache_info); +void sysinfo_cache_info_default(struct cache_info *ci); +int sysinfo_get_processor_info(struct processor_info *pinfo); +#else +static inline int sysinfo_get_cache_info(u8 level,
struct cache_info *cache_info)
+{
return -ENOSYS;
+}
+static inline void sysinfo_cache_info_default(struct cache_info *ci) +{ +}
+static inline int sysinfo_get_processor_info(struct processor_info
*pinfo)
+{
return -ENOSYS;
+} +#endif
+#endif /* __SMBIOS_PLAT_H */ diff --git a/include/sysinfo.h b/include/sysinfo.h index 17b2b9c7111..cb08a691270 100644 --- a/include/sysinfo.h +++ b/include/sysinfo.h @@ -11,6 +11,8 @@
struct udevice;
+#define SYSINFO_CACHE_LVL_MAX 3
/*
- This uclass encapsulates hardware methods to gather information
about a
- sysinfo or a specific device such as hard-wired GPIOs on GPIO
expanders,
@@ -42,18 +44,109 @@ struct udevice; enum sysinfo_id { SYSINFO_ID_NONE,
/* For SMBIOS tables */
/* BIOS Information (Type 0) */
SYSINFO_ID_SMBIOS_BIOS_VENDOR,
SYSINFO_ID_SMBIOS_BIOS_VER,
SYSINFO_ID_SMBIOS_BIOS_REL_DATE,
/* System Information (Type 1) */ SYSINFO_ID_SMBIOS_SYSTEM_MANUFACTURER, SYSINFO_ID_SMBIOS_SYSTEM_PRODUCT, SYSINFO_ID_SMBIOS_SYSTEM_VERSION, SYSINFO_ID_SMBIOS_SYSTEM_SERIAL,
SYSINFO_ID_SMBIOS_SYSTEM_WAKEUP, SYSINFO_ID_SMBIOS_SYSTEM_SKU, SYSINFO_ID_SMBIOS_SYSTEM_FAMILY,
/* Baseboard (or Module) Information (Type 2) */ SYSINFO_ID_SMBIOS_BASEBOARD_MANUFACTURER, SYSINFO_ID_SMBIOS_BASEBOARD_PRODUCT, SYSINFO_ID_SMBIOS_BASEBOARD_VERSION, SYSINFO_ID_SMBIOS_BASEBOARD_SERIAL, SYSINFO_ID_SMBIOS_BASEBOARD_ASSET_TAG,
SYSINFO_ID_SMBIOS_BASEBOARD_FEATURE,
SYSINFO_ID_SMBIOS_BASEBOARD_CHASSIS_LOCAT,
SYSINFO_ID_SMBIOS_BASEBOARD_TYPE,
SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_NUM,
SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_HANDLE,
/* System Enclosure or Chassis (Type 3) */
SYSINFO_ID_SMBIOS_ENCLOSURE_MANUFACTURER,
SYSINFO_ID_SMBIOS_ENCLOSURE_VERSION,
SYSINFO_ID_SMBIOS_ENCLOSURE_SERIAL,
SYSINFO_ID_SMBIOS_ENCLOSURE_ASSET_TAG,
SYSINFO_ID_SMBIOS_ENCLOSURE_TYPE,
SYSINFO_ID_SMBIOS_ENCLOSURE_BOOTUP,
SYSINFO_ID_SMBIOS_ENCLOSURE_POW,
SYSINFO_ID_SMBIOS_ENCLOSURE_THERMAL,
SYSINFO_ID_SMBIOS_ENCLOSURE_SECURITY,
SYSINFO_ID_SMBIOS_ENCLOSURE_OEM,
SYSINFO_ID_SMBIOS_ENCLOSURE_HEIGHT,
SYSINFO_ID_SMBIOS_ENCLOSURE_POWCORE_NUM,
SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_CNT,
SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_LEN,
SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENTS,
SYSINFO_ID_SMBIOS_ENCLOSURE_SKU,
/* Processor Information (Type 4) */
SYSINFO_ID_SMBIOS_PROCESSOR_SOCKET,
SYSINFO_ID_SMBIOS_PROCESSOR_TYPE,
SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT,
SYSINFO_ID_SMBIOS_PROCESSOR_ID,
SYSINFO_ID_SMBIOS_PROCESSOR_VERSION,
SYSINFO_ID_SMBIOS_PROCESSOR_VOLTAGE,
SYSINFO_ID_SMBIOS_PROCESSOR_EXT_CLOCK,
SYSINFO_ID_SMBIOS_PROCESSOR_MAX_SPEED,
SYSINFO_ID_SMBIOS_PROCESSOR_CUR_SPEED,
SYSINFO_ID_SMBIOS_PROCESSOR_STATUS,
SYSINFO_ID_SMBIOS_PROCESSOR_UPGRADE,
SYSINFO_ID_SMBIOS_PROCESSOR_SN,
SYSINFO_ID_SMBIOS_PROCESSOR_ASSET_TAG,
SYSINFO_ID_SMBIOS_PROCESSOR_PN,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN,
SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT,
SYSINFO_ID_SMBIOS_PROCESSOR_CHARA,
SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY,
SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY2,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT2,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN2,
SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT2,
SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_EN,
/*
* Cache Information (Type 7)
* Each of the id should reserve space for up to
* SYSINFO_CACHE_LVL_MAX levels of cache
*/
SYSINFO_ID_SMBIOS_CACHE_LEVEL,
SYSINFO_ID_SMBIOS_CACHE_HANDLE,
SYSINFO_ID_SMBIOS_CACHE_INFO_START,
SYSINFO_ID_SMBIOS_CACHE_SOCKET =
SYSINFO_ID_SMBIOS_CACHE_INFO_START,
SYSINFO_ID_SMBIOS_CACHE_CONFIG =
SYSINFO_ID_SMBIOS_CACHE_SOCKET + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE =
SYSINFO_ID_SMBIOS_CACHE_CONFIG + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE =
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_SUPSRAM_TYPE =
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_CURSRAM_TYPE =
SYSINFO_ID_SMBIOS_CACHE_SUPSRAM_TYPE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_SPEED =
SYSINFO_ID_SMBIOS_CACHE_CURSRAM_TYPE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_ERRCOR_TYPE =
SYSINFO_ID_SMBIOS_CACHE_SPEED + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE =
SYSINFO_ID_SMBIOS_CACHE_ERRCOR_TYPE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_ASSOC =
SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2 =
SYSINFO_ID_SMBIOS_CACHE_ASSOC + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2 =
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2 +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_INFO_END =
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2 +
SYSINFO_CACHE_LVL_MAX - 1,
This seems to be allocating sequential values for each cache? Instead, we should add a 'seq' parameter to get_data()
/* For show_board_info() */ SYSINFO_ID_BOARD_MODEL,
-- 2.25.1
Regards, Simon

Hi Raymond,
On Mon, 28 Oct 2024 at 20:44, Raymond Mao raymond.mao@linaro.org wrote:
Hi Simon,
On Mon, 28 Oct 2024 at 13:04, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Tue, 22 Oct 2024 at 22:06, Raymond Mao raymond.mao@linaro.org wrote:
Add sysinfo driver to retrieve smbios information (Type 4 and 7). So that the smbios library can use it for getting values from the hardware platform instead of device tree.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
Changes in v2
- Move the changes to smbios.c instead of creating new file.
- Move the headfile to include dir.
- Combine with #6(v1) patch.
- Clean-up the private data structures.
- Clean-up the operations of the strings and common values.
drivers/sysinfo/smbios.c | 228 +++++++++++++++++++++++++++++++++++++++ include/smbios.h | 60 +++++++++++ include/smbios_plat.h | 79 ++++++++++++++ include/sysinfo.h | 95 +++++++++++++++- 4 files changed, 461 insertions(+), 1 deletion(-) create mode 100644 include/smbios_plat.h
diff --git a/drivers/sysinfo/smbios.c b/drivers/sysinfo/smbios.c index a7ac8e3f072..3980845b3ba 100644 --- a/drivers/sysinfo/smbios.c +++ b/drivers/sysinfo/smbios.c @@ -5,14 +5,240 @@ */
#include <dm.h> +#include <smbios_plat.h> #include <sysinfo.h>
+/* platform information storage */ +struct processor_info processor_info; +struct cache_info cache_info[SYSINFO_CACHE_LVL_MAX]; +struct sysinfo_plat sysinfo_smbios_p = {
/* Processor Information */
.processor = &processor_info,
/* Cache Information */
.cache = &cache_info[0],
+};
+/* structure for smbios private data storage */ +struct sysinfo_plat_priv {
struct processor_info *t4;
struct smbios_type7 t7[SYSINFO_CACHE_LVL_MAX];
u16 cache_handles[SYSINFO_CACHE_LVL_MAX];
u8 cache_level;
+};
+static void smbios_cache_info_dump(struct smbios_type7 *cache_info) +{
log_debug("SMBIOS Type 7 (Cache Information):\n");
log_debug("Cache Configuration: 0x%04x\n", cache_info->config.data);
log_debug("Maximum Cache Size: %u KB\n", cache_info->max_size.data);
log_debug("Installed Size: %u KB\n", cache_info->inst_size.data);
log_debug("Supported SRAM Type: 0x%04x\n",
%#04x
cache_info->supp_sram_type.data);
log_debug("Current SRAM Type: 0x%04x\n",
cache_info->curr_sram_type.data);
log_debug("Cache Speed: %u\n", cache_info->speed);
log_debug("Error Correction Type: %u\n", cache_info->err_corr_type);
log_debug("System Cache Type: %u\n", cache_info->sys_cache_type);
log_debug("Associativity: %u\n", cache_info->associativity);
log_debug("Maximum Cache Size 2: %u KB\n", cache_info->max_size2.data);
log_debug("Installed Cache Size 2: %u KB\n",
cache_info->inst_size2.data);
+}
+/* weak function for the platforms not yet supported */ +__weak int sysinfo_get_cache_info(u8 level, struct cache_info *cache_info) +{
return -ENOSYS;
+}
+__weak int sysinfo_get_processor_info(struct processor_info *pinfo) +{
return -ENOSYS;
+}
+void sysinfo_cache_info_default(struct cache_info *ci) +{
memset(ci, 0, sizeof(*ci));
ci->config.data = SMBIOS_CACHE_LOCATE_UNKNOWN | SMBIOS_CACHE_OP_UND;
ci->supp_sram_type.fields.unknown = 1;
ci->curr_sram_type.fields.unknown = 1;
ci->speed = SMBIOS_CACHE_SPEED_UNKNOWN;
ci->err_corr_type = SMBIOS_CACHE_ERRCORR_UNKNOWN;
ci->cache_type = SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN;
+}
+static int sysinfo_plat_detect(struct udevice *dev) +{
return 0;
+}
+static int sysinfo_plat_get_str(struct udevice *dev, int id,
size_t size, char *val)
+{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
const char *str = NULL;
switch (id) {
case SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT:
These are getting too long.
How about SYSINFOSM_PROC_MANUF ?
We can use SYSINFOSM as short for SYSINFO_ID_SMBIOS
Other existing macros are starting from SYSINFO_ID_, so I guess something reasonable can be SYSINFO_ID_SMB_PROC_MANU.
That is certainly better. Perhaps SYSINFO_ID_ should become SYSID_...?
[..]
Regards, Simon

Hi Simon,
On Mon, 28 Oct 2024 at 13:04, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Tue, 22 Oct 2024 at 22:06, Raymond Mao raymond.mao@linaro.org wrote:
Add sysinfo driver to retrieve smbios information (Type 4 and 7). So that the smbios library can use it for getting values from the hardware platform instead of device tree.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
Changes in v2
- Move the changes to smbios.c instead of creating new file.
- Move the headfile to include dir.
- Combine with #6(v1) patch.
- Clean-up the private data structures.
- Clean-up the operations of the strings and common values.
drivers/sysinfo/smbios.c | 228 +++++++++++++++++++++++++++++++++++++++ include/smbios.h | 60 +++++++++++ include/smbios_plat.h | 79 ++++++++++++++ include/sysinfo.h | 95 +++++++++++++++- 4 files changed, 461 insertions(+), 1 deletion(-) create mode 100644 include/smbios_plat.h
diff --git a/drivers/sysinfo/smbios.c b/drivers/sysinfo/smbios.c index a7ac8e3f072..3980845b3ba 100644 --- a/drivers/sysinfo/smbios.c +++ b/drivers/sysinfo/smbios.c @@ -5,14 +5,240 @@ */
#include <dm.h> +#include <smbios_plat.h> #include <sysinfo.h>
+/* platform information storage */ +struct processor_info processor_info; +struct cache_info cache_info[SYSINFO_CACHE_LVL_MAX]; +struct sysinfo_plat sysinfo_smbios_p = {
/* Processor Information */
.processor = &processor_info,
/* Cache Information */
.cache = &cache_info[0],
+};
+/* structure for smbios private data storage */ +struct sysinfo_plat_priv {
struct processor_info *t4;
struct smbios_type7 t7[SYSINFO_CACHE_LVL_MAX];
u16 cache_handles[SYSINFO_CACHE_LVL_MAX];
u8 cache_level;
+};
+static void smbios_cache_info_dump(struct smbios_type7 *cache_info) +{
log_debug("SMBIOS Type 7 (Cache Information):\n");
log_debug("Cache Configuration: 0x%04x\n",
cache_info->config.data);
log_debug("Maximum Cache Size: %u KB\n",
cache_info->max_size.data);
log_debug("Installed Size: %u KB\n", cache_info->inst_size.data);
log_debug("Supported SRAM Type: 0x%04x\n",
%#04x
cache_info->supp_sram_type.data);
log_debug("Current SRAM Type: 0x%04x\n",
cache_info->curr_sram_type.data);
log_debug("Cache Speed: %u\n", cache_info->speed);
log_debug("Error Correction Type: %u\n",
cache_info->err_corr_type);
log_debug("System Cache Type: %u\n", cache_info->sys_cache_type);
log_debug("Associativity: %u\n", cache_info->associativity);
log_debug("Maximum Cache Size 2: %u KB\n",
cache_info->max_size2.data);
log_debug("Installed Cache Size 2: %u KB\n",
cache_info->inst_size2.data);
+}
+/* weak function for the platforms not yet supported */ +__weak int sysinfo_get_cache_info(u8 level, struct cache_info
*cache_info)
+{
return -ENOSYS;
+}
+__weak int sysinfo_get_processor_info(struct processor_info *pinfo) +{
return -ENOSYS;
+}
+void sysinfo_cache_info_default(struct cache_info *ci) +{
memset(ci, 0, sizeof(*ci));
ci->config.data = SMBIOS_CACHE_LOCATE_UNKNOWN |
SMBIOS_CACHE_OP_UND;
ci->supp_sram_type.fields.unknown = 1;
ci->curr_sram_type.fields.unknown = 1;
ci->speed = SMBIOS_CACHE_SPEED_UNKNOWN;
ci->err_corr_type = SMBIOS_CACHE_ERRCORR_UNKNOWN;
ci->cache_type = SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN;
+}
+static int sysinfo_plat_detect(struct udevice *dev) +{
return 0;
+}
+static int sysinfo_plat_get_str(struct udevice *dev, int id,
size_t size, char *val)
+{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
const char *str = NULL;
switch (id) {
case SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT:
These are getting too long.
How about SYSINFOSM_PROC_MANUF ?
We can use SYSINFOSM as short for SYSINFO_ID_SMBIOS
str = priv->t4->manufacturer;
break;
default:
break;
}
if (!str)
return -ENOSYS;
strlcpy(val, str, size);
return 0;
+}
+static int sysinfo_plat_get_int(struct udevice *dev, int id, int *val) +{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
u8 i;
if (id >= SYSINFO_ID_SMBIOS_CACHE_INFO_START &&
id <= SYSINFO_ID_SMBIOS_CACHE_INFO_END) {
/* For smbios type 7 */
for (i = 0; i < priv->cache_level; i++) {
switch (id - i) {
case SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE:
*val = priv->t7[i].max_size.data;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_INST_SIZE:
*val = priv->t7[i].inst_size.data;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE:
*val = priv->t7[i].sys_cache_type;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_ASSOC:
*val = priv->t7[i].associativity;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2:
*val = priv->t7[i].max_size2.data;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2:
*val = priv->t7[i].inst_size2.data;
return 0;
default:
break;
}
}
return -ENOSYS;
}
switch (id) {
case SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT:
*val = priv->t4->core_count;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN:
*val = priv->t4->core_enabled;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_CHARA:
*val = priv->t4->characteristics;
break;
case SYSINFO_ID_SMBIOS_CACHE_LEVEL:
if (!priv->cache_level) /* No cache detected */
return -ENOSYS;
*val = priv->cache_level - 1;
break;
default:
return -ENOSYS;
}
return 0;
+}
+static int sysinfo_plat_get_data(struct udevice *dev, int id, uchar
**buf,
How about void **, so we don't need to cast below?
size_t *size)
+{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
switch (id) {
case SYSINFO_ID_SMBIOS_PROCESSOR_ID:
*buf = (uchar *)priv->t4->id;
*size = sizeof(priv->t4->id);
break;
case SYSINFO_ID_SMBIOS_CACHE_HANDLE:
*buf = (uchar *)(&priv->cache_handles[0]);
Isn't that the same as:
*buf = (uchar *)&priv->cache_handles;
*size = sizeof(priv->cache_handles);
break;
default:
return -EOPNOTSUPP;
}
return 0;
+}
+static int sysinfo_plat_probe(struct udevice *dev) +{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
struct sysinfo_plat *plat = &sysinfo_smbios_p;
u8 level;
if (!sysinfo_get_processor_info(plat->processor))
priv->t4 = plat->processor;
for (level = 0; level < SYSINFO_CACHE_LVL_MAX; level++) {
struct cache_info *pcache = plat->cache + level;
if (sysinfo_get_cache_info(level, pcache))
break; /* no more levels */
/*
* Fill in the SMBIOS type 7 structure,
* skip the header members (type, length, handle),
* and the ones in DT smbios node.
*/
priv->t7[level].sys_cache_type = pcache->cache_type;
priv->t7[level].associativity = pcache->associativity;
if (pcache->max_size > SMBIOS_CACHE_SIZE_EXT_KB) {
priv->t7[level].max_size.data = 0xFFFF;
priv->t7[level].max_size2.fields.size =
pcache->max_size / 64;
priv->t7[level].max_size2.fields.granu =
SMBIOS_CACHE_GRANU_64K;
} else {
priv->t7[level].max_size.fields.size =
pcache->max_size;
priv->t7[level].max_size.fields.granu =
SMBIOS_CACHE_GRANU_1K;
priv->t7[level].max_size2.data = 0;
}
if (pcache->inst_size > SMBIOS_CACHE_SIZE_EXT_KB) {
priv->t7[level].inst_size.data = 0xFFFF;
priv->t7[level].inst_size2.fields.size =
pcache->inst_size / 64;
priv->t7[level].inst_size2.fields.granu =
SMBIOS_CACHE_GRANU_64K;
} else {
priv->t7[level].inst_size.fields.size =
pcache->inst_size;
priv->t7[level].inst_size.fields.granu =
SMBIOS_CACHE_GRANU_1K;
priv->t7[level].inst_size2.data = 0;
}
smbios_cache_info_dump(&priv->t7[level]);
}
if (!level) /* no cache detected */
return -ENOSYS;
priv->cache_level = level;
return 0;
+}
static const struct udevice_id sysinfo_smbios_ids[] = { { .compatible = "u-boot,sysinfo-smbios" }, { /* sentinel */ } };
static const struct sysinfo_ops sysinfo_smbios_ops = {
.detect = sysinfo_plat_detect,
.get_str = sysinfo_plat_get_str,
.get_int = sysinfo_plat_get_int,
.get_data = sysinfo_plat_get_data,
};
U_BOOT_DRIVER(sysinfo_smbios) = { @@ -20,4 +246,6 @@ U_BOOT_DRIVER(sysinfo_smbios) = { .id = UCLASS_SYSINFO, .of_match = sysinfo_smbios_ids, .ops = &sysinfo_smbios_ops,
.priv_auto = sizeof(struct sysinfo_plat_priv),
.probe = sysinfo_plat_probe,
}; diff --git a/include/smbios.h b/include/smbios.h index 78fd14d881b..cb4b3e08b3a 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -187,6 +187,66 @@ struct __packed smbios_type4 { char eos[SMBIOS_STRUCT_EOS_BYTES]; };
+union cache_config {
struct {
u16 level:3;
u16 bsocketed:1;
u16 rsvd0:1;
u16 locate:2;
u16 benabled:1;
u16 opmode:2;
u16 rsvd1:6;
} fields;
u16 data;
+};
+union cache_size_word {
struct {
u16 size:15;
u16 granu:1;
} fields;
u16 data;
+};
+union cache_size_dword {
struct {
u32 size:31;
u32 granu:1;
} fields;
u32 data;
+};
+union cache_sram_type {
struct {
u16 other:1;
u16 unknown:1;
u16 nonburst:1;
u16 burst:1;
u16 plburst:1;
u16 sync:1;
u16 async:1;
u16 rsvd:9;
} fields;
u16 data;
+};
+struct __packed smbios_type7 {
struct smbios_header hdr;
u8 socket_design;
union cache_config config;
union cache_size_word max_size;
union cache_size_word inst_size;
union cache_sram_type supp_sram_type;
union cache_sram_type curr_sram_type;
u8 speed;
u8 err_corr_type;
u8 sys_cache_type;
u8 associativity;
union cache_size_dword max_size2;
union cache_size_dword inst_size2;
char eos[SMBIOS_STRUCT_EOS_BYTES];
+};
struct __packed smbios_type32 { u8 type; u8 length; diff --git a/include/smbios_plat.h b/include/smbios_plat.h new file mode 100644 index 00000000000..70089d5a2ba --- /dev/null +++ b/include/smbios_plat.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (c) 2024 Linaro Limited
- Author: Raymond Mao raymond.mao@linaro.org
- */
+#ifndef __SMBIOS_PLAT_H +#define __SMBIOS_PLAT_H
+#include <smbios.h>
+struct cache_info {
union cache_config config;
union cache_sram_type supp_sram_type;
union cache_sram_type curr_sram_type;
u32 line_size;
u32 associativity;
u32 max_size;
u32 inst_size;
u8 cache_type;
u8 speed;
u8 err_corr_type;
char *socket_design;
+};
+struct processor_info {
u32 id[2];
u16 ext_clock;
u16 max_speed;
u16 curr_speed;
u16 characteristics;
u16 family2;
u16 core_count2;
u16 core_enabled2;
u16 thread_count2;
u16 thread_enabled;
u8 type;
u8 family;
u8 voltage;
u8 status;
u8 upgrade;
u8 core_count;
u8 core_enabled;
u8 thread_count;
char *socket_design;
char *manufacturer;
char *version;
char *sn;
char *asset_tag;
char *pn;
+};
+struct sysinfo_plat {
struct processor_info *processor;
struct cache_info *cache;
/* add other sysinfo structure here */
+};
+#if defined CONFIG_SYSINFO_SMBIOS +int sysinfo_get_cache_info(u8 level, struct cache_info *cache_info); +void sysinfo_cache_info_default(struct cache_info *ci); +int sysinfo_get_processor_info(struct processor_info *pinfo); +#else +static inline int sysinfo_get_cache_info(u8 level,
struct cache_info *cache_info)
+{
return -ENOSYS;
+}
+static inline void sysinfo_cache_info_default(struct cache_info *ci) +{ +}
+static inline int sysinfo_get_processor_info(struct processor_info
*pinfo)
+{
return -ENOSYS;
+} +#endif
+#endif /* __SMBIOS_PLAT_H */ diff --git a/include/sysinfo.h b/include/sysinfo.h index 17b2b9c7111..cb08a691270 100644 --- a/include/sysinfo.h +++ b/include/sysinfo.h @@ -11,6 +11,8 @@
struct udevice;
+#define SYSINFO_CACHE_LVL_MAX 3
/*
- This uclass encapsulates hardware methods to gather information
about a
- sysinfo or a specific device such as hard-wired GPIOs on GPIO
expanders,
@@ -42,18 +44,109 @@ struct udevice; enum sysinfo_id { SYSINFO_ID_NONE,
/* For SMBIOS tables */
/* BIOS Information (Type 0) */
SYSINFO_ID_SMBIOS_BIOS_VENDOR,
SYSINFO_ID_SMBIOS_BIOS_VER,
SYSINFO_ID_SMBIOS_BIOS_REL_DATE,
/* System Information (Type 1) */ SYSINFO_ID_SMBIOS_SYSTEM_MANUFACTURER, SYSINFO_ID_SMBIOS_SYSTEM_PRODUCT, SYSINFO_ID_SMBIOS_SYSTEM_VERSION, SYSINFO_ID_SMBIOS_SYSTEM_SERIAL,
SYSINFO_ID_SMBIOS_SYSTEM_WAKEUP, SYSINFO_ID_SMBIOS_SYSTEM_SKU, SYSINFO_ID_SMBIOS_SYSTEM_FAMILY,
/* Baseboard (or Module) Information (Type 2) */ SYSINFO_ID_SMBIOS_BASEBOARD_MANUFACTURER, SYSINFO_ID_SMBIOS_BASEBOARD_PRODUCT, SYSINFO_ID_SMBIOS_BASEBOARD_VERSION, SYSINFO_ID_SMBIOS_BASEBOARD_SERIAL, SYSINFO_ID_SMBIOS_BASEBOARD_ASSET_TAG,
SYSINFO_ID_SMBIOS_BASEBOARD_FEATURE,
SYSINFO_ID_SMBIOS_BASEBOARD_CHASSIS_LOCAT,
SYSINFO_ID_SMBIOS_BASEBOARD_TYPE,
SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_NUM,
SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_HANDLE,
/* System Enclosure or Chassis (Type 3) */
SYSINFO_ID_SMBIOS_ENCLOSURE_MANUFACTURER,
SYSINFO_ID_SMBIOS_ENCLOSURE_VERSION,
SYSINFO_ID_SMBIOS_ENCLOSURE_SERIAL,
SYSINFO_ID_SMBIOS_ENCLOSURE_ASSET_TAG,
SYSINFO_ID_SMBIOS_ENCLOSURE_TYPE,
SYSINFO_ID_SMBIOS_ENCLOSURE_BOOTUP,
SYSINFO_ID_SMBIOS_ENCLOSURE_POW,
SYSINFO_ID_SMBIOS_ENCLOSURE_THERMAL,
SYSINFO_ID_SMBIOS_ENCLOSURE_SECURITY,
SYSINFO_ID_SMBIOS_ENCLOSURE_OEM,
SYSINFO_ID_SMBIOS_ENCLOSURE_HEIGHT,
SYSINFO_ID_SMBIOS_ENCLOSURE_POWCORE_NUM,
SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_CNT,
SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_LEN,
SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENTS,
SYSINFO_ID_SMBIOS_ENCLOSURE_SKU,
/* Processor Information (Type 4) */
SYSINFO_ID_SMBIOS_PROCESSOR_SOCKET,
SYSINFO_ID_SMBIOS_PROCESSOR_TYPE,
SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT,
SYSINFO_ID_SMBIOS_PROCESSOR_ID,
SYSINFO_ID_SMBIOS_PROCESSOR_VERSION,
SYSINFO_ID_SMBIOS_PROCESSOR_VOLTAGE,
SYSINFO_ID_SMBIOS_PROCESSOR_EXT_CLOCK,
SYSINFO_ID_SMBIOS_PROCESSOR_MAX_SPEED,
SYSINFO_ID_SMBIOS_PROCESSOR_CUR_SPEED,
SYSINFO_ID_SMBIOS_PROCESSOR_STATUS,
SYSINFO_ID_SMBIOS_PROCESSOR_UPGRADE,
SYSINFO_ID_SMBIOS_PROCESSOR_SN,
SYSINFO_ID_SMBIOS_PROCESSOR_ASSET_TAG,
SYSINFO_ID_SMBIOS_PROCESSOR_PN,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN,
SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT,
SYSINFO_ID_SMBIOS_PROCESSOR_CHARA,
SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY,
SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY2,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT2,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN2,
SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT2,
SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_EN,
/*
* Cache Information (Type 7)
* Each of the id should reserve space for up to
* SYSINFO_CACHE_LVL_MAX levels of cache
*/
SYSINFO_ID_SMBIOS_CACHE_LEVEL,
SYSINFO_ID_SMBIOS_CACHE_HANDLE,
SYSINFO_ID_SMBIOS_CACHE_INFO_START,
SYSINFO_ID_SMBIOS_CACHE_SOCKET =
SYSINFO_ID_SMBIOS_CACHE_INFO_START,
SYSINFO_ID_SMBIOS_CACHE_CONFIG =
SYSINFO_ID_SMBIOS_CACHE_SOCKET + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE =
SYSINFO_ID_SMBIOS_CACHE_CONFIG + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE =
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_SUPSRAM_TYPE =
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_CURSRAM_TYPE =
SYSINFO_ID_SMBIOS_CACHE_SUPSRAM_TYPE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_SPEED =
SYSINFO_ID_SMBIOS_CACHE_CURSRAM_TYPE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_ERRCOR_TYPE =
SYSINFO_ID_SMBIOS_CACHE_SPEED + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE =
SYSINFO_ID_SMBIOS_CACHE_ERRCOR_TYPE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_ASSOC =
SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2 =
SYSINFO_ID_SMBIOS_CACHE_ASSOC + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2 =
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2 +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_INFO_END =
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2 +
SYSINFO_CACHE_LVL_MAX - 1,
This seems to be allocating sequential values for each cache? Instead, we should add a 'seq' parameter to get_data()
Sorry for not responding to this comment, actually I would prefer to use
get_str or get_val as it allows to check whether values from sysinfo driver are missing and fallback to the value from dt node one by one.
[snip]
Regards, Raymond

Hi Raymond,
On Thu, 5 Dec 2024 at 10:28, Raymond Mao raymond.mao@linaro.org wrote:
Hi Simon,
On Mon, 28 Oct 2024 at 13:04, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Tue, 22 Oct 2024 at 22:06, Raymond Mao raymond.mao@linaro.org wrote:
Add sysinfo driver to retrieve smbios information (Type 4 and 7). So that the smbios library can use it for getting values from the hardware platform instead of device tree.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
Changes in v2
- Move the changes to smbios.c instead of creating new file.
- Move the headfile to include dir.
- Combine with #6(v1) patch.
- Clean-up the private data structures.
- Clean-up the operations of the strings and common values.
drivers/sysinfo/smbios.c | 228 +++++++++++++++++++++++++++++++++++++++ include/smbios.h | 60 +++++++++++ include/smbios_plat.h | 79 ++++++++++++++ include/sysinfo.h | 95 +++++++++++++++- 4 files changed, 461 insertions(+), 1 deletion(-) create mode 100644 include/smbios_plat.h
diff --git a/drivers/sysinfo/smbios.c b/drivers/sysinfo/smbios.c index a7ac8e3f072..3980845b3ba 100644 --- a/drivers/sysinfo/smbios.c +++ b/drivers/sysinfo/smbios.c @@ -5,14 +5,240 @@ */
#include <dm.h> +#include <smbios_plat.h> #include <sysinfo.h>
+/* platform information storage */ +struct processor_info processor_info; +struct cache_info cache_info[SYSINFO_CACHE_LVL_MAX]; +struct sysinfo_plat sysinfo_smbios_p = {
/* Processor Information */
.processor = &processor_info,
/* Cache Information */
.cache = &cache_info[0],
+};
+/* structure for smbios private data storage */ +struct sysinfo_plat_priv {
struct processor_info *t4;
struct smbios_type7 t7[SYSINFO_CACHE_LVL_MAX];
u16 cache_handles[SYSINFO_CACHE_LVL_MAX];
u8 cache_level;
+};
+static void smbios_cache_info_dump(struct smbios_type7 *cache_info) +{
log_debug("SMBIOS Type 7 (Cache Information):\n");
log_debug("Cache Configuration: 0x%04x\n", cache_info->config.data);
log_debug("Maximum Cache Size: %u KB\n", cache_info->max_size.data);
log_debug("Installed Size: %u KB\n", cache_info->inst_size.data);
log_debug("Supported SRAM Type: 0x%04x\n",
%#04x
cache_info->supp_sram_type.data);
log_debug("Current SRAM Type: 0x%04x\n",
cache_info->curr_sram_type.data);
log_debug("Cache Speed: %u\n", cache_info->speed);
log_debug("Error Correction Type: %u\n", cache_info->err_corr_type);
log_debug("System Cache Type: %u\n", cache_info->sys_cache_type);
log_debug("Associativity: %u\n", cache_info->associativity);
log_debug("Maximum Cache Size 2: %u KB\n", cache_info->max_size2.data);
log_debug("Installed Cache Size 2: %u KB\n",
cache_info->inst_size2.data);
+}
+/* weak function for the platforms not yet supported */ +__weak int sysinfo_get_cache_info(u8 level, struct cache_info *cache_info) +{
return -ENOSYS;
+}
+__weak int sysinfo_get_processor_info(struct processor_info *pinfo) +{
return -ENOSYS;
+}
+void sysinfo_cache_info_default(struct cache_info *ci) +{
memset(ci, 0, sizeof(*ci));
ci->config.data = SMBIOS_CACHE_LOCATE_UNKNOWN | SMBIOS_CACHE_OP_UND;
ci->supp_sram_type.fields.unknown = 1;
ci->curr_sram_type.fields.unknown = 1;
ci->speed = SMBIOS_CACHE_SPEED_UNKNOWN;
ci->err_corr_type = SMBIOS_CACHE_ERRCORR_UNKNOWN;
ci->cache_type = SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN;
+}
+static int sysinfo_plat_detect(struct udevice *dev) +{
return 0;
+}
+static int sysinfo_plat_get_str(struct udevice *dev, int id,
size_t size, char *val)
+{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
const char *str = NULL;
switch (id) {
case SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT:
These are getting too long.
How about SYSINFOSM_PROC_MANUF ?
We can use SYSINFOSM as short for SYSINFO_ID_SMBIOS
str = priv->t4->manufacturer;
break;
default:
break;
}
if (!str)
return -ENOSYS;
strlcpy(val, str, size);
return 0;
+}
+static int sysinfo_plat_get_int(struct udevice *dev, int id, int *val) +{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
u8 i;
if (id >= SYSINFO_ID_SMBIOS_CACHE_INFO_START &&
id <= SYSINFO_ID_SMBIOS_CACHE_INFO_END) {
/* For smbios type 7 */
for (i = 0; i < priv->cache_level; i++) {
switch (id - i) {
case SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE:
*val = priv->t7[i].max_size.data;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_INST_SIZE:
*val = priv->t7[i].inst_size.data;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE:
*val = priv->t7[i].sys_cache_type;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_ASSOC:
*val = priv->t7[i].associativity;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2:
*val = priv->t7[i].max_size2.data;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2:
*val = priv->t7[i].inst_size2.data;
return 0;
default:
break;
}
}
return -ENOSYS;
}
switch (id) {
case SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT:
*val = priv->t4->core_count;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN:
*val = priv->t4->core_enabled;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_CHARA:
*val = priv->t4->characteristics;
break;
case SYSINFO_ID_SMBIOS_CACHE_LEVEL:
if (!priv->cache_level) /* No cache detected */
return -ENOSYS;
*val = priv->cache_level - 1;
break;
default:
return -ENOSYS;
}
return 0;
+}
+static int sysinfo_plat_get_data(struct udevice *dev, int id, uchar **buf,
How about void **, so we don't need to cast below?
size_t *size)
+{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
switch (id) {
case SYSINFO_ID_SMBIOS_PROCESSOR_ID:
*buf = (uchar *)priv->t4->id;
*size = sizeof(priv->t4->id);
break;
case SYSINFO_ID_SMBIOS_CACHE_HANDLE:
*buf = (uchar *)(&priv->cache_handles[0]);
Isn't that the same as:
*buf = (uchar *)&priv->cache_handles;
*size = sizeof(priv->cache_handles);
break;
default:
return -EOPNOTSUPP;
}
return 0;
+}
+static int sysinfo_plat_probe(struct udevice *dev) +{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
struct sysinfo_plat *plat = &sysinfo_smbios_p;
u8 level;
if (!sysinfo_get_processor_info(plat->processor))
priv->t4 = plat->processor;
for (level = 0; level < SYSINFO_CACHE_LVL_MAX; level++) {
struct cache_info *pcache = plat->cache + level;
if (sysinfo_get_cache_info(level, pcache))
break; /* no more levels */
/*
* Fill in the SMBIOS type 7 structure,
* skip the header members (type, length, handle),
* and the ones in DT smbios node.
*/
priv->t7[level].sys_cache_type = pcache->cache_type;
priv->t7[level].associativity = pcache->associativity;
if (pcache->max_size > SMBIOS_CACHE_SIZE_EXT_KB) {
priv->t7[level].max_size.data = 0xFFFF;
priv->t7[level].max_size2.fields.size =
pcache->max_size / 64;
priv->t7[level].max_size2.fields.granu =
SMBIOS_CACHE_GRANU_64K;
} else {
priv->t7[level].max_size.fields.size = pcache->max_size;
priv->t7[level].max_size.fields.granu =
SMBIOS_CACHE_GRANU_1K;
priv->t7[level].max_size2.data = 0;
}
if (pcache->inst_size > SMBIOS_CACHE_SIZE_EXT_KB) {
priv->t7[level].inst_size.data = 0xFFFF;
priv->t7[level].inst_size2.fields.size =
pcache->inst_size / 64;
priv->t7[level].inst_size2.fields.granu =
SMBIOS_CACHE_GRANU_64K;
} else {
priv->t7[level].inst_size.fields.size =
pcache->inst_size;
priv->t7[level].inst_size.fields.granu =
SMBIOS_CACHE_GRANU_1K;
priv->t7[level].inst_size2.data = 0;
}
smbios_cache_info_dump(&priv->t7[level]);
}
if (!level) /* no cache detected */
return -ENOSYS;
priv->cache_level = level;
return 0;
+}
static const struct udevice_id sysinfo_smbios_ids[] = { { .compatible = "u-boot,sysinfo-smbios" }, { /* sentinel */ } };
static const struct sysinfo_ops sysinfo_smbios_ops = {
.detect = sysinfo_plat_detect,
.get_str = sysinfo_plat_get_str,
.get_int = sysinfo_plat_get_int,
.get_data = sysinfo_plat_get_data,
};
U_BOOT_DRIVER(sysinfo_smbios) = { @@ -20,4 +246,6 @@ U_BOOT_DRIVER(sysinfo_smbios) = { .id = UCLASS_SYSINFO, .of_match = sysinfo_smbios_ids, .ops = &sysinfo_smbios_ops,
.priv_auto = sizeof(struct sysinfo_plat_priv),
.probe = sysinfo_plat_probe,
}; diff --git a/include/smbios.h b/include/smbios.h index 78fd14d881b..cb4b3e08b3a 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -187,6 +187,66 @@ struct __packed smbios_type4 { char eos[SMBIOS_STRUCT_EOS_BYTES]; };
+union cache_config {
struct {
u16 level:3;
u16 bsocketed:1;
u16 rsvd0:1;
u16 locate:2;
u16 benabled:1;
u16 opmode:2;
u16 rsvd1:6;
} fields;
u16 data;
+};
+union cache_size_word {
struct {
u16 size:15;
u16 granu:1;
} fields;
u16 data;
+};
+union cache_size_dword {
struct {
u32 size:31;
u32 granu:1;
} fields;
u32 data;
+};
+union cache_sram_type {
struct {
u16 other:1;
u16 unknown:1;
u16 nonburst:1;
u16 burst:1;
u16 plburst:1;
u16 sync:1;
u16 async:1;
u16 rsvd:9;
} fields;
u16 data;
+};
+struct __packed smbios_type7 {
struct smbios_header hdr;
u8 socket_design;
union cache_config config;
union cache_size_word max_size;
union cache_size_word inst_size;
union cache_sram_type supp_sram_type;
union cache_sram_type curr_sram_type;
u8 speed;
u8 err_corr_type;
u8 sys_cache_type;
u8 associativity;
union cache_size_dword max_size2;
union cache_size_dword inst_size2;
char eos[SMBIOS_STRUCT_EOS_BYTES];
+};
struct __packed smbios_type32 { u8 type; u8 length; diff --git a/include/smbios_plat.h b/include/smbios_plat.h new file mode 100644 index 00000000000..70089d5a2ba --- /dev/null +++ b/include/smbios_plat.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (c) 2024 Linaro Limited
- Author: Raymond Mao raymond.mao@linaro.org
- */
+#ifndef __SMBIOS_PLAT_H +#define __SMBIOS_PLAT_H
+#include <smbios.h>
+struct cache_info {
union cache_config config;
union cache_sram_type supp_sram_type;
union cache_sram_type curr_sram_type;
u32 line_size;
u32 associativity;
u32 max_size;
u32 inst_size;
u8 cache_type;
u8 speed;
u8 err_corr_type;
char *socket_design;
+};
+struct processor_info {
u32 id[2];
u16 ext_clock;
u16 max_speed;
u16 curr_speed;
u16 characteristics;
u16 family2;
u16 core_count2;
u16 core_enabled2;
u16 thread_count2;
u16 thread_enabled;
u8 type;
u8 family;
u8 voltage;
u8 status;
u8 upgrade;
u8 core_count;
u8 core_enabled;
u8 thread_count;
char *socket_design;
char *manufacturer;
char *version;
char *sn;
char *asset_tag;
char *pn;
+};
+struct sysinfo_plat {
struct processor_info *processor;
struct cache_info *cache;
/* add other sysinfo structure here */
+};
+#if defined CONFIG_SYSINFO_SMBIOS +int sysinfo_get_cache_info(u8 level, struct cache_info *cache_info); +void sysinfo_cache_info_default(struct cache_info *ci); +int sysinfo_get_processor_info(struct processor_info *pinfo); +#else +static inline int sysinfo_get_cache_info(u8 level,
struct cache_info *cache_info)
+{
return -ENOSYS;
+}
+static inline void sysinfo_cache_info_default(struct cache_info *ci) +{ +}
+static inline int sysinfo_get_processor_info(struct processor_info *pinfo) +{
return -ENOSYS;
+} +#endif
+#endif /* __SMBIOS_PLAT_H */ diff --git a/include/sysinfo.h b/include/sysinfo.h index 17b2b9c7111..cb08a691270 100644 --- a/include/sysinfo.h +++ b/include/sysinfo.h @@ -11,6 +11,8 @@
struct udevice;
+#define SYSINFO_CACHE_LVL_MAX 3
/*
- This uclass encapsulates hardware methods to gather information about a
- sysinfo or a specific device such as hard-wired GPIOs on GPIO expanders,
@@ -42,18 +44,109 @@ struct udevice; enum sysinfo_id { SYSINFO_ID_NONE,
/* For SMBIOS tables */
/* BIOS Information (Type 0) */
SYSINFO_ID_SMBIOS_BIOS_VENDOR,
SYSINFO_ID_SMBIOS_BIOS_VER,
SYSINFO_ID_SMBIOS_BIOS_REL_DATE,
/* System Information (Type 1) */ SYSINFO_ID_SMBIOS_SYSTEM_MANUFACTURER, SYSINFO_ID_SMBIOS_SYSTEM_PRODUCT, SYSINFO_ID_SMBIOS_SYSTEM_VERSION, SYSINFO_ID_SMBIOS_SYSTEM_SERIAL,
SYSINFO_ID_SMBIOS_SYSTEM_WAKEUP, SYSINFO_ID_SMBIOS_SYSTEM_SKU, SYSINFO_ID_SMBIOS_SYSTEM_FAMILY,
/* Baseboard (or Module) Information (Type 2) */ SYSINFO_ID_SMBIOS_BASEBOARD_MANUFACTURER, SYSINFO_ID_SMBIOS_BASEBOARD_PRODUCT, SYSINFO_ID_SMBIOS_BASEBOARD_VERSION, SYSINFO_ID_SMBIOS_BASEBOARD_SERIAL, SYSINFO_ID_SMBIOS_BASEBOARD_ASSET_TAG,
SYSINFO_ID_SMBIOS_BASEBOARD_FEATURE,
SYSINFO_ID_SMBIOS_BASEBOARD_CHASSIS_LOCAT,
SYSINFO_ID_SMBIOS_BASEBOARD_TYPE,
SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_NUM,
SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_HANDLE,
/* System Enclosure or Chassis (Type 3) */
SYSINFO_ID_SMBIOS_ENCLOSURE_MANUFACTURER,
SYSINFO_ID_SMBIOS_ENCLOSURE_VERSION,
SYSINFO_ID_SMBIOS_ENCLOSURE_SERIAL,
SYSINFO_ID_SMBIOS_ENCLOSURE_ASSET_TAG,
SYSINFO_ID_SMBIOS_ENCLOSURE_TYPE,
SYSINFO_ID_SMBIOS_ENCLOSURE_BOOTUP,
SYSINFO_ID_SMBIOS_ENCLOSURE_POW,
SYSINFO_ID_SMBIOS_ENCLOSURE_THERMAL,
SYSINFO_ID_SMBIOS_ENCLOSURE_SECURITY,
SYSINFO_ID_SMBIOS_ENCLOSURE_OEM,
SYSINFO_ID_SMBIOS_ENCLOSURE_HEIGHT,
SYSINFO_ID_SMBIOS_ENCLOSURE_POWCORE_NUM,
SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_CNT,
SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_LEN,
SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENTS,
SYSINFO_ID_SMBIOS_ENCLOSURE_SKU,
/* Processor Information (Type 4) */
SYSINFO_ID_SMBIOS_PROCESSOR_SOCKET,
SYSINFO_ID_SMBIOS_PROCESSOR_TYPE,
SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT,
SYSINFO_ID_SMBIOS_PROCESSOR_ID,
SYSINFO_ID_SMBIOS_PROCESSOR_VERSION,
SYSINFO_ID_SMBIOS_PROCESSOR_VOLTAGE,
SYSINFO_ID_SMBIOS_PROCESSOR_EXT_CLOCK,
SYSINFO_ID_SMBIOS_PROCESSOR_MAX_SPEED,
SYSINFO_ID_SMBIOS_PROCESSOR_CUR_SPEED,
SYSINFO_ID_SMBIOS_PROCESSOR_STATUS,
SYSINFO_ID_SMBIOS_PROCESSOR_UPGRADE,
SYSINFO_ID_SMBIOS_PROCESSOR_SN,
SYSINFO_ID_SMBIOS_PROCESSOR_ASSET_TAG,
SYSINFO_ID_SMBIOS_PROCESSOR_PN,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN,
SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT,
SYSINFO_ID_SMBIOS_PROCESSOR_CHARA,
SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY,
SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY2,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT2,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN2,
SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT2,
SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_EN,
/*
* Cache Information (Type 7)
* Each of the id should reserve space for up to
* SYSINFO_CACHE_LVL_MAX levels of cache
*/
SYSINFO_ID_SMBIOS_CACHE_LEVEL,
SYSINFO_ID_SMBIOS_CACHE_HANDLE,
SYSINFO_ID_SMBIOS_CACHE_INFO_START,
SYSINFO_ID_SMBIOS_CACHE_SOCKET = SYSINFO_ID_SMBIOS_CACHE_INFO_START,
SYSINFO_ID_SMBIOS_CACHE_CONFIG =
SYSINFO_ID_SMBIOS_CACHE_SOCKET + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE =
SYSINFO_ID_SMBIOS_CACHE_CONFIG + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE =
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_SUPSRAM_TYPE =
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_CURSRAM_TYPE =
SYSINFO_ID_SMBIOS_CACHE_SUPSRAM_TYPE + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_SPEED =
SYSINFO_ID_SMBIOS_CACHE_CURSRAM_TYPE + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_ERRCOR_TYPE =
SYSINFO_ID_SMBIOS_CACHE_SPEED + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE =
SYSINFO_ID_SMBIOS_CACHE_ERRCOR_TYPE + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_ASSOC =
SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2 =
SYSINFO_ID_SMBIOS_CACHE_ASSOC + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2 =
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2 + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_INFO_END =
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2 + SYSINFO_CACHE_LVL_MAX - 1,
This seems to be allocating sequential values for each cache? Instead, we should add a 'seq' parameter to get_data()
Sorry for not responding to this comment, actually I would prefer to use get_str or get_val as it allows to check whether values from sysinfo driver are missing and fallback to the value from dt node one by one.
Yes that is good...I had assumed this was just data, rather than string/int.
My main point is that we need an indexed lookup, where on SYSINFO_ID can be used to lookup up multiple values, with an index, since the scheme in this patch is a little unwieldy.
[snip]
Regards, Simon

Hi Simon,
On Fri, 6 Dec 2024 at 10:31, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Thu, 5 Dec 2024 at 10:28, Raymond Mao raymond.mao@linaro.org wrote:
Hi Simon,
On Mon, 28 Oct 2024 at 13:04, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Tue, 22 Oct 2024 at 22:06, Raymond Mao raymond.mao@linaro.org
wrote:
Add sysinfo driver to retrieve smbios information (Type 4 and 7). So that the smbios library can use it for getting values from the hardware platform instead of device tree.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
Changes in v2
- Move the changes to smbios.c instead of creating new file.
- Move the headfile to include dir.
- Combine with #6(v1) patch.
- Clean-up the private data structures.
- Clean-up the operations of the strings and common values.
drivers/sysinfo/smbios.c | 228
+++++++++++++++++++++++++++++++++++++++
include/smbios.h | 60 +++++++++++ include/smbios_plat.h | 79 ++++++++++++++ include/sysinfo.h | 95 +++++++++++++++- 4 files changed, 461 insertions(+), 1 deletion(-) create mode 100644 include/smbios_plat.h
diff --git a/drivers/sysinfo/smbios.c b/drivers/sysinfo/smbios.c index a7ac8e3f072..3980845b3ba 100644 --- a/drivers/sysinfo/smbios.c +++ b/drivers/sysinfo/smbios.c @@ -5,14 +5,240 @@ */
#include <dm.h> +#include <smbios_plat.h> #include <sysinfo.h>
+/* platform information storage */ +struct processor_info processor_info; +struct cache_info cache_info[SYSINFO_CACHE_LVL_MAX]; +struct sysinfo_plat sysinfo_smbios_p = {
/* Processor Information */
.processor = &processor_info,
/* Cache Information */
.cache = &cache_info[0],
+};
+/* structure for smbios private data storage */ +struct sysinfo_plat_priv {
struct processor_info *t4;
struct smbios_type7 t7[SYSINFO_CACHE_LVL_MAX];
u16 cache_handles[SYSINFO_CACHE_LVL_MAX];
u8 cache_level;
+};
+static void smbios_cache_info_dump(struct smbios_type7 *cache_info) +{
log_debug("SMBIOS Type 7 (Cache Information):\n");
log_debug("Cache Configuration: 0x%04x\n",
cache_info->config.data);
log_debug("Maximum Cache Size: %u KB\n",
cache_info->max_size.data);
log_debug("Installed Size: %u KB\n",
cache_info->inst_size.data);
log_debug("Supported SRAM Type: 0x%04x\n",
%#04x
cache_info->supp_sram_type.data);
log_debug("Current SRAM Type: 0x%04x\n",
cache_info->curr_sram_type.data);
log_debug("Cache Speed: %u\n", cache_info->speed);
log_debug("Error Correction Type: %u\n",
cache_info->err_corr_type);
log_debug("System Cache Type: %u\n",
cache_info->sys_cache_type);
log_debug("Associativity: %u\n", cache_info->associativity);
log_debug("Maximum Cache Size 2: %u KB\n",
cache_info->max_size2.data);
log_debug("Installed Cache Size 2: %u KB\n",
cache_info->inst_size2.data);
+}
+/* weak function for the platforms not yet supported */ +__weak int sysinfo_get_cache_info(u8 level, struct cache_info
*cache_info)
+{
return -ENOSYS;
+}
+__weak int sysinfo_get_processor_info(struct processor_info *pinfo) +{
return -ENOSYS;
+}
+void sysinfo_cache_info_default(struct cache_info *ci) +{
memset(ci, 0, sizeof(*ci));
ci->config.data = SMBIOS_CACHE_LOCATE_UNKNOWN |
SMBIOS_CACHE_OP_UND;
ci->supp_sram_type.fields.unknown = 1;
ci->curr_sram_type.fields.unknown = 1;
ci->speed = SMBIOS_CACHE_SPEED_UNKNOWN;
ci->err_corr_type = SMBIOS_CACHE_ERRCORR_UNKNOWN;
ci->cache_type = SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN;
+}
+static int sysinfo_plat_detect(struct udevice *dev) +{
return 0;
+}
+static int sysinfo_plat_get_str(struct udevice *dev, int id,
size_t size, char *val)
+{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
const char *str = NULL;
switch (id) {
case SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT:
These are getting too long.
How about SYSINFOSM_PROC_MANUF ?
We can use SYSINFOSM as short for SYSINFO_ID_SMBIOS
str = priv->t4->manufacturer;
break;
default:
break;
}
if (!str)
return -ENOSYS;
strlcpy(val, str, size);
return 0;
+}
+static int sysinfo_plat_get_int(struct udevice *dev, int id, int
*val)
+{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
u8 i;
if (id >= SYSINFO_ID_SMBIOS_CACHE_INFO_START &&
id <= SYSINFO_ID_SMBIOS_CACHE_INFO_END) {
/* For smbios type 7 */
for (i = 0; i < priv->cache_level; i++) {
switch (id - i) {
case SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE:
*val = priv->t7[i].max_size.data;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_INST_SIZE:
*val = priv->t7[i].inst_size.data;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE:
*val = priv->t7[i].sys_cache_type;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_ASSOC:
*val = priv->t7[i].associativity;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2:
*val = priv->t7[i].max_size2.data;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2:
*val = priv->t7[i].inst_size2.data;
return 0;
default:
break;
}
}
return -ENOSYS;
}
switch (id) {
case SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT:
*val = priv->t4->core_count;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN:
*val = priv->t4->core_enabled;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_CHARA:
*val = priv->t4->characteristics;
break;
case SYSINFO_ID_SMBIOS_CACHE_LEVEL:
if (!priv->cache_level) /* No cache detected */
return -ENOSYS;
*val = priv->cache_level - 1;
break;
default:
return -ENOSYS;
}
return 0;
+}
+static int sysinfo_plat_get_data(struct udevice *dev, int id, uchar
**buf,
How about void **, so we don't need to cast below?
size_t *size)
+{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
switch (id) {
case SYSINFO_ID_SMBIOS_PROCESSOR_ID:
*buf = (uchar *)priv->t4->id;
*size = sizeof(priv->t4->id);
break;
case SYSINFO_ID_SMBIOS_CACHE_HANDLE:
*buf = (uchar *)(&priv->cache_handles[0]);
Isn't that the same as:
*buf = (uchar *)&priv->cache_handles;
*size = sizeof(priv->cache_handles);
break;
default:
return -EOPNOTSUPP;
}
return 0;
+}
+static int sysinfo_plat_probe(struct udevice *dev) +{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
struct sysinfo_plat *plat = &sysinfo_smbios_p;
u8 level;
if (!sysinfo_get_processor_info(plat->processor))
priv->t4 = plat->processor;
for (level = 0; level < SYSINFO_CACHE_LVL_MAX; level++) {
struct cache_info *pcache = plat->cache + level;
if (sysinfo_get_cache_info(level, pcache))
break; /* no more levels */
/*
* Fill in the SMBIOS type 7 structure,
* skip the header members (type, length, handle),
* and the ones in DT smbios node.
*/
priv->t7[level].sys_cache_type = pcache->cache_type;
priv->t7[level].associativity = pcache->associativity;
if (pcache->max_size > SMBIOS_CACHE_SIZE_EXT_KB) {
priv->t7[level].max_size.data = 0xFFFF;
priv->t7[level].max_size2.fields.size =
pcache->max_size / 64;
priv->t7[level].max_size2.fields.granu =
SMBIOS_CACHE_GRANU_64K;
} else {
priv->t7[level].max_size.fields.size =
pcache->max_size;
priv->t7[level].max_size.fields.granu =
SMBIOS_CACHE_GRANU_1K;
priv->t7[level].max_size2.data = 0;
}
if (pcache->inst_size > SMBIOS_CACHE_SIZE_EXT_KB) {
priv->t7[level].inst_size.data = 0xFFFF;
priv->t7[level].inst_size2.fields.size =
pcache->inst_size / 64;
priv->t7[level].inst_size2.fields.granu =
SMBIOS_CACHE_GRANU_64K;
} else {
priv->t7[level].inst_size.fields.size =
pcache->inst_size;
priv->t7[level].inst_size.fields.granu =
SMBIOS_CACHE_GRANU_1K;
priv->t7[level].inst_size2.data = 0;
}
smbios_cache_info_dump(&priv->t7[level]);
}
if (!level) /* no cache detected */
return -ENOSYS;
priv->cache_level = level;
return 0;
+}
static const struct udevice_id sysinfo_smbios_ids[] = { { .compatible = "u-boot,sysinfo-smbios" }, { /* sentinel */ } };
static const struct sysinfo_ops sysinfo_smbios_ops = {
.detect = sysinfo_plat_detect,
.get_str = sysinfo_plat_get_str,
.get_int = sysinfo_plat_get_int,
.get_data = sysinfo_plat_get_data,
};
U_BOOT_DRIVER(sysinfo_smbios) = { @@ -20,4 +246,6 @@ U_BOOT_DRIVER(sysinfo_smbios) = { .id = UCLASS_SYSINFO, .of_match = sysinfo_smbios_ids, .ops = &sysinfo_smbios_ops,
.priv_auto = sizeof(struct sysinfo_plat_priv),
.probe = sysinfo_plat_probe,
}; diff --git a/include/smbios.h b/include/smbios.h index 78fd14d881b..cb4b3e08b3a 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -187,6 +187,66 @@ struct __packed smbios_type4 { char eos[SMBIOS_STRUCT_EOS_BYTES]; };
+union cache_config {
struct {
u16 level:3;
u16 bsocketed:1;
u16 rsvd0:1;
u16 locate:2;
u16 benabled:1;
u16 opmode:2;
u16 rsvd1:6;
} fields;
u16 data;
+};
+union cache_size_word {
struct {
u16 size:15;
u16 granu:1;
} fields;
u16 data;
+};
+union cache_size_dword {
struct {
u32 size:31;
u32 granu:1;
} fields;
u32 data;
+};
+union cache_sram_type {
struct {
u16 other:1;
u16 unknown:1;
u16 nonburst:1;
u16 burst:1;
u16 plburst:1;
u16 sync:1;
u16 async:1;
u16 rsvd:9;
} fields;
u16 data;
+};
+struct __packed smbios_type7 {
struct smbios_header hdr;
u8 socket_design;
union cache_config config;
union cache_size_word max_size;
union cache_size_word inst_size;
union cache_sram_type supp_sram_type;
union cache_sram_type curr_sram_type;
u8 speed;
u8 err_corr_type;
u8 sys_cache_type;
u8 associativity;
union cache_size_dword max_size2;
union cache_size_dword inst_size2;
char eos[SMBIOS_STRUCT_EOS_BYTES];
+};
struct __packed smbios_type32 { u8 type; u8 length; diff --git a/include/smbios_plat.h b/include/smbios_plat.h new file mode 100644 index 00000000000..70089d5a2ba --- /dev/null +++ b/include/smbios_plat.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (c) 2024 Linaro Limited
- Author: Raymond Mao raymond.mao@linaro.org
- */
+#ifndef __SMBIOS_PLAT_H +#define __SMBIOS_PLAT_H
+#include <smbios.h>
+struct cache_info {
union cache_config config;
union cache_sram_type supp_sram_type;
union cache_sram_type curr_sram_type;
u32 line_size;
u32 associativity;
u32 max_size;
u32 inst_size;
u8 cache_type;
u8 speed;
u8 err_corr_type;
char *socket_design;
+};
+struct processor_info {
u32 id[2];
u16 ext_clock;
u16 max_speed;
u16 curr_speed;
u16 characteristics;
u16 family2;
u16 core_count2;
u16 core_enabled2;
u16 thread_count2;
u16 thread_enabled;
u8 type;
u8 family;
u8 voltage;
u8 status;
u8 upgrade;
u8 core_count;
u8 core_enabled;
u8 thread_count;
char *socket_design;
char *manufacturer;
char *version;
char *sn;
char *asset_tag;
char *pn;
+};
+struct sysinfo_plat {
struct processor_info *processor;
struct cache_info *cache;
/* add other sysinfo structure here */
+};
+#if defined CONFIG_SYSINFO_SMBIOS +int sysinfo_get_cache_info(u8 level, struct cache_info *cache_info); +void sysinfo_cache_info_default(struct cache_info *ci); +int sysinfo_get_processor_info(struct processor_info *pinfo); +#else +static inline int sysinfo_get_cache_info(u8 level,
struct cache_info
*cache_info)
+{
return -ENOSYS;
+}
+static inline void sysinfo_cache_info_default(struct cache_info *ci) +{ +}
+static inline int sysinfo_get_processor_info(struct processor_info
*pinfo)
+{
return -ENOSYS;
+} +#endif
+#endif /* __SMBIOS_PLAT_H */ diff --git a/include/sysinfo.h b/include/sysinfo.h index 17b2b9c7111..cb08a691270 100644 --- a/include/sysinfo.h +++ b/include/sysinfo.h @@ -11,6 +11,8 @@
struct udevice;
+#define SYSINFO_CACHE_LVL_MAX 3
/*
- This uclass encapsulates hardware methods to gather information
about a
- sysinfo or a specific device such as hard-wired GPIOs on GPIO
expanders,
@@ -42,18 +44,109 @@ struct udevice; enum sysinfo_id { SYSINFO_ID_NONE,
/* For SMBIOS tables */
/* BIOS Information (Type 0) */
SYSINFO_ID_SMBIOS_BIOS_VENDOR,
SYSINFO_ID_SMBIOS_BIOS_VER,
SYSINFO_ID_SMBIOS_BIOS_REL_DATE,
/* System Information (Type 1) */ SYSINFO_ID_SMBIOS_SYSTEM_MANUFACTURER, SYSINFO_ID_SMBIOS_SYSTEM_PRODUCT, SYSINFO_ID_SMBIOS_SYSTEM_VERSION, SYSINFO_ID_SMBIOS_SYSTEM_SERIAL,
SYSINFO_ID_SMBIOS_SYSTEM_WAKEUP, SYSINFO_ID_SMBIOS_SYSTEM_SKU, SYSINFO_ID_SMBIOS_SYSTEM_FAMILY,
/* Baseboard (or Module) Information (Type 2) */ SYSINFO_ID_SMBIOS_BASEBOARD_MANUFACTURER, SYSINFO_ID_SMBIOS_BASEBOARD_PRODUCT, SYSINFO_ID_SMBIOS_BASEBOARD_VERSION, SYSINFO_ID_SMBIOS_BASEBOARD_SERIAL, SYSINFO_ID_SMBIOS_BASEBOARD_ASSET_TAG,
SYSINFO_ID_SMBIOS_BASEBOARD_FEATURE,
SYSINFO_ID_SMBIOS_BASEBOARD_CHASSIS_LOCAT,
SYSINFO_ID_SMBIOS_BASEBOARD_TYPE,
SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_NUM,
SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_HANDLE,
/* System Enclosure or Chassis (Type 3) */
SYSINFO_ID_SMBIOS_ENCLOSURE_MANUFACTURER,
SYSINFO_ID_SMBIOS_ENCLOSURE_VERSION,
SYSINFO_ID_SMBIOS_ENCLOSURE_SERIAL,
SYSINFO_ID_SMBIOS_ENCLOSURE_ASSET_TAG,
SYSINFO_ID_SMBIOS_ENCLOSURE_TYPE,
SYSINFO_ID_SMBIOS_ENCLOSURE_BOOTUP,
SYSINFO_ID_SMBIOS_ENCLOSURE_POW,
SYSINFO_ID_SMBIOS_ENCLOSURE_THERMAL,
SYSINFO_ID_SMBIOS_ENCLOSURE_SECURITY,
SYSINFO_ID_SMBIOS_ENCLOSURE_OEM,
SYSINFO_ID_SMBIOS_ENCLOSURE_HEIGHT,
SYSINFO_ID_SMBIOS_ENCLOSURE_POWCORE_NUM,
SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_CNT,
SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_LEN,
SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENTS,
SYSINFO_ID_SMBIOS_ENCLOSURE_SKU,
/* Processor Information (Type 4) */
SYSINFO_ID_SMBIOS_PROCESSOR_SOCKET,
SYSINFO_ID_SMBIOS_PROCESSOR_TYPE,
SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT,
SYSINFO_ID_SMBIOS_PROCESSOR_ID,
SYSINFO_ID_SMBIOS_PROCESSOR_VERSION,
SYSINFO_ID_SMBIOS_PROCESSOR_VOLTAGE,
SYSINFO_ID_SMBIOS_PROCESSOR_EXT_CLOCK,
SYSINFO_ID_SMBIOS_PROCESSOR_MAX_SPEED,
SYSINFO_ID_SMBIOS_PROCESSOR_CUR_SPEED,
SYSINFO_ID_SMBIOS_PROCESSOR_STATUS,
SYSINFO_ID_SMBIOS_PROCESSOR_UPGRADE,
SYSINFO_ID_SMBIOS_PROCESSOR_SN,
SYSINFO_ID_SMBIOS_PROCESSOR_ASSET_TAG,
SYSINFO_ID_SMBIOS_PROCESSOR_PN,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN,
SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT,
SYSINFO_ID_SMBIOS_PROCESSOR_CHARA,
SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY,
SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY2,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT2,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN2,
SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT2,
SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_EN,
/*
* Cache Information (Type 7)
* Each of the id should reserve space for up to
* SYSINFO_CACHE_LVL_MAX levels of cache
*/
SYSINFO_ID_SMBIOS_CACHE_LEVEL,
SYSINFO_ID_SMBIOS_CACHE_HANDLE,
SYSINFO_ID_SMBIOS_CACHE_INFO_START,
SYSINFO_ID_SMBIOS_CACHE_SOCKET =
SYSINFO_ID_SMBIOS_CACHE_INFO_START,
SYSINFO_ID_SMBIOS_CACHE_CONFIG =
SYSINFO_ID_SMBIOS_CACHE_SOCKET +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE =
SYSINFO_ID_SMBIOS_CACHE_CONFIG +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE =
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_SUPSRAM_TYPE =
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_CURSRAM_TYPE =
SYSINFO_ID_SMBIOS_CACHE_SUPSRAM_TYPE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_SPEED =
SYSINFO_ID_SMBIOS_CACHE_CURSRAM_TYPE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_ERRCOR_TYPE =
SYSINFO_ID_SMBIOS_CACHE_SPEED + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE =
SYSINFO_ID_SMBIOS_CACHE_ERRCOR_TYPE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_ASSOC =
SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2 =
SYSINFO_ID_SMBIOS_CACHE_ASSOC + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2 =
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2 +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_INFO_END =
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2 +
SYSINFO_CACHE_LVL_MAX - 1,
This seems to be allocating sequential values for each cache? Instead,
we should add a 'seq' parameter to get_data()
Sorry for not responding to this comment, actually I would prefer to use
get_str or get_val as it allows
to check whether values from sysinfo driver are missing and fallback to
the value from dt node one by one.
Yes that is good...I had assumed this was just data, rather than string/int.
My main point is that we need an indexed lookup, where on SYSINFO_ID can be used to lookup up multiple values, with an index, since the scheme in this patch is a little unwieldy.
I understand what you are concerned about.
Using a unique id for one value allows each field to independently fallback to the value from the dt node. For the scenario of cache information, the values from each level should be independently retrieved from either sysinfo driver or dt node. But if we group the values from multiple levels using the same id, we lose the independence. The only disadvantage here is some of the SYSINFO_IDs are reserved in an implicit manner which is a trade-off.
Regards, Raymond

Hi Raymond,
On Fri, 6 Dec 2024 at 08:54, Raymond Mao raymond.mao@linaro.org wrote:
Hi Simon,
On Fri, 6 Dec 2024 at 10:31, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Thu, 5 Dec 2024 at 10:28, Raymond Mao raymond.mao@linaro.org wrote:
Hi Simon,
On Mon, 28 Oct 2024 at 13:04, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Tue, 22 Oct 2024 at 22:06, Raymond Mao raymond.mao@linaro.org wrote:
Add sysinfo driver to retrieve smbios information (Type 4 and 7). So that the smbios library can use it for getting values from the hardware platform instead of device tree.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
Changes in v2
- Move the changes to smbios.c instead of creating new file.
- Move the headfile to include dir.
- Combine with #6(v1) patch.
- Clean-up the private data structures.
- Clean-up the operations of the strings and common values.
drivers/sysinfo/smbios.c | 228 +++++++++++++++++++++++++++++++++++++++ include/smbios.h | 60 +++++++++++ include/smbios_plat.h | 79 ++++++++++++++ include/sysinfo.h | 95 +++++++++++++++- 4 files changed, 461 insertions(+), 1 deletion(-) create mode 100644 include/smbios_plat.h
diff --git a/drivers/sysinfo/smbios.c b/drivers/sysinfo/smbios.c index a7ac8e3f072..3980845b3ba 100644 --- a/drivers/sysinfo/smbios.c +++ b/drivers/sysinfo/smbios.c @@ -5,14 +5,240 @@ */
#include <dm.h> +#include <smbios_plat.h> #include <sysinfo.h>
+/* platform information storage */ +struct processor_info processor_info; +struct cache_info cache_info[SYSINFO_CACHE_LVL_MAX]; +struct sysinfo_plat sysinfo_smbios_p = {
/* Processor Information */
.processor = &processor_info,
/* Cache Information */
.cache = &cache_info[0],
+};
+/* structure for smbios private data storage */ +struct sysinfo_plat_priv {
struct processor_info *t4;
struct smbios_type7 t7[SYSINFO_CACHE_LVL_MAX];
u16 cache_handles[SYSINFO_CACHE_LVL_MAX];
u8 cache_level;
+};
+static void smbios_cache_info_dump(struct smbios_type7 *cache_info) +{
log_debug("SMBIOS Type 7 (Cache Information):\n");
log_debug("Cache Configuration: 0x%04x\n", cache_info->config.data);
log_debug("Maximum Cache Size: %u KB\n", cache_info->max_size.data);
log_debug("Installed Size: %u KB\n", cache_info->inst_size.data);
log_debug("Supported SRAM Type: 0x%04x\n",
%#04x
cache_info->supp_sram_type.data);
log_debug("Current SRAM Type: 0x%04x\n",
cache_info->curr_sram_type.data);
log_debug("Cache Speed: %u\n", cache_info->speed);
log_debug("Error Correction Type: %u\n", cache_info->err_corr_type);
log_debug("System Cache Type: %u\n", cache_info->sys_cache_type);
log_debug("Associativity: %u\n", cache_info->associativity);
log_debug("Maximum Cache Size 2: %u KB\n", cache_info->max_size2.data);
log_debug("Installed Cache Size 2: %u KB\n",
cache_info->inst_size2.data);
+}
+/* weak function for the platforms not yet supported */ +__weak int sysinfo_get_cache_info(u8 level, struct cache_info *cache_info) +{
return -ENOSYS;
+}
+__weak int sysinfo_get_processor_info(struct processor_info *pinfo) +{
return -ENOSYS;
+}
+void sysinfo_cache_info_default(struct cache_info *ci) +{
memset(ci, 0, sizeof(*ci));
ci->config.data = SMBIOS_CACHE_LOCATE_UNKNOWN | SMBIOS_CACHE_OP_UND;
ci->supp_sram_type.fields.unknown = 1;
ci->curr_sram_type.fields.unknown = 1;
ci->speed = SMBIOS_CACHE_SPEED_UNKNOWN;
ci->err_corr_type = SMBIOS_CACHE_ERRCORR_UNKNOWN;
ci->cache_type = SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN;
+}
+static int sysinfo_plat_detect(struct udevice *dev) +{
return 0;
+}
+static int sysinfo_plat_get_str(struct udevice *dev, int id,
size_t size, char *val)
+{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
const char *str = NULL;
switch (id) {
case SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT:
These are getting too long.
How about SYSINFOSM_PROC_MANUF ?
We can use SYSINFOSM as short for SYSINFO_ID_SMBIOS
str = priv->t4->manufacturer;
break;
default:
break;
}
if (!str)
return -ENOSYS;
strlcpy(val, str, size);
return 0;
+}
+static int sysinfo_plat_get_int(struct udevice *dev, int id, int *val) +{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
u8 i;
if (id >= SYSINFO_ID_SMBIOS_CACHE_INFO_START &&
id <= SYSINFO_ID_SMBIOS_CACHE_INFO_END) {
/* For smbios type 7 */
for (i = 0; i < priv->cache_level; i++) {
switch (id - i) {
case SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE:
*val = priv->t7[i].max_size.data;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_INST_SIZE:
*val = priv->t7[i].inst_size.data;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE:
*val = priv->t7[i].sys_cache_type;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_ASSOC:
*val = priv->t7[i].associativity;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2:
*val = priv->t7[i].max_size2.data;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2:
*val = priv->t7[i].inst_size2.data;
return 0;
default:
break;
}
}
return -ENOSYS;
}
switch (id) {
case SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT:
*val = priv->t4->core_count;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN:
*val = priv->t4->core_enabled;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_CHARA:
*val = priv->t4->characteristics;
break;
case SYSINFO_ID_SMBIOS_CACHE_LEVEL:
if (!priv->cache_level) /* No cache detected */
return -ENOSYS;
*val = priv->cache_level - 1;
break;
default:
return -ENOSYS;
}
return 0;
+}
+static int sysinfo_plat_get_data(struct udevice *dev, int id, uchar **buf,
How about void **, so we don't need to cast below?
size_t *size)
+{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
switch (id) {
case SYSINFO_ID_SMBIOS_PROCESSOR_ID:
*buf = (uchar *)priv->t4->id;
*size = sizeof(priv->t4->id);
break;
case SYSINFO_ID_SMBIOS_CACHE_HANDLE:
*buf = (uchar *)(&priv->cache_handles[0]);
Isn't that the same as:
*buf = (uchar *)&priv->cache_handles;
*size = sizeof(priv->cache_handles);
break;
default:
return -EOPNOTSUPP;
}
return 0;
+}
+static int sysinfo_plat_probe(struct udevice *dev) +{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
struct sysinfo_plat *plat = &sysinfo_smbios_p;
u8 level;
if (!sysinfo_get_processor_info(plat->processor))
priv->t4 = plat->processor;
for (level = 0; level < SYSINFO_CACHE_LVL_MAX; level++) {
struct cache_info *pcache = plat->cache + level;
if (sysinfo_get_cache_info(level, pcache))
break; /* no more levels */
/*
* Fill in the SMBIOS type 7 structure,
* skip the header members (type, length, handle),
* and the ones in DT smbios node.
*/
priv->t7[level].sys_cache_type = pcache->cache_type;
priv->t7[level].associativity = pcache->associativity;
if (pcache->max_size > SMBIOS_CACHE_SIZE_EXT_KB) {
priv->t7[level].max_size.data = 0xFFFF;
priv->t7[level].max_size2.fields.size =
pcache->max_size / 64;
priv->t7[level].max_size2.fields.granu =
SMBIOS_CACHE_GRANU_64K;
} else {
priv->t7[level].max_size.fields.size = pcache->max_size;
priv->t7[level].max_size.fields.granu =
SMBIOS_CACHE_GRANU_1K;
priv->t7[level].max_size2.data = 0;
}
if (pcache->inst_size > SMBIOS_CACHE_SIZE_EXT_KB) {
priv->t7[level].inst_size.data = 0xFFFF;
priv->t7[level].inst_size2.fields.size =
pcache->inst_size / 64;
priv->t7[level].inst_size2.fields.granu =
SMBIOS_CACHE_GRANU_64K;
} else {
priv->t7[level].inst_size.fields.size =
pcache->inst_size;
priv->t7[level].inst_size.fields.granu =
SMBIOS_CACHE_GRANU_1K;
priv->t7[level].inst_size2.data = 0;
}
smbios_cache_info_dump(&priv->t7[level]);
}
if (!level) /* no cache detected */
return -ENOSYS;
priv->cache_level = level;
return 0;
+}
static const struct udevice_id sysinfo_smbios_ids[] = { { .compatible = "u-boot,sysinfo-smbios" }, { /* sentinel */ } };
static const struct sysinfo_ops sysinfo_smbios_ops = {
.detect = sysinfo_plat_detect,
.get_str = sysinfo_plat_get_str,
.get_int = sysinfo_plat_get_int,
.get_data = sysinfo_plat_get_data,
};
U_BOOT_DRIVER(sysinfo_smbios) = { @@ -20,4 +246,6 @@ U_BOOT_DRIVER(sysinfo_smbios) = { .id = UCLASS_SYSINFO, .of_match = sysinfo_smbios_ids, .ops = &sysinfo_smbios_ops,
.priv_auto = sizeof(struct sysinfo_plat_priv),
.probe = sysinfo_plat_probe,
}; diff --git a/include/smbios.h b/include/smbios.h index 78fd14d881b..cb4b3e08b3a 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -187,6 +187,66 @@ struct __packed smbios_type4 { char eos[SMBIOS_STRUCT_EOS_BYTES]; };
+union cache_config {
struct {
u16 level:3;
u16 bsocketed:1;
u16 rsvd0:1;
u16 locate:2;
u16 benabled:1;
u16 opmode:2;
u16 rsvd1:6;
} fields;
u16 data;
+};
+union cache_size_word {
struct {
u16 size:15;
u16 granu:1;
} fields;
u16 data;
+};
+union cache_size_dword {
struct {
u32 size:31;
u32 granu:1;
} fields;
u32 data;
+};
+union cache_sram_type {
struct {
u16 other:1;
u16 unknown:1;
u16 nonburst:1;
u16 burst:1;
u16 plburst:1;
u16 sync:1;
u16 async:1;
u16 rsvd:9;
} fields;
u16 data;
+};
+struct __packed smbios_type7 {
struct smbios_header hdr;
u8 socket_design;
union cache_config config;
union cache_size_word max_size;
union cache_size_word inst_size;
union cache_sram_type supp_sram_type;
union cache_sram_type curr_sram_type;
u8 speed;
u8 err_corr_type;
u8 sys_cache_type;
u8 associativity;
union cache_size_dword max_size2;
union cache_size_dword inst_size2;
char eos[SMBIOS_STRUCT_EOS_BYTES];
+};
struct __packed smbios_type32 { u8 type; u8 length; diff --git a/include/smbios_plat.h b/include/smbios_plat.h new file mode 100644 index 00000000000..70089d5a2ba --- /dev/null +++ b/include/smbios_plat.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (c) 2024 Linaro Limited
- Author: Raymond Mao raymond.mao@linaro.org
- */
+#ifndef __SMBIOS_PLAT_H +#define __SMBIOS_PLAT_H
+#include <smbios.h>
+struct cache_info {
union cache_config config;
union cache_sram_type supp_sram_type;
union cache_sram_type curr_sram_type;
u32 line_size;
u32 associativity;
u32 max_size;
u32 inst_size;
u8 cache_type;
u8 speed;
u8 err_corr_type;
char *socket_design;
+};
+struct processor_info {
u32 id[2];
u16 ext_clock;
u16 max_speed;
u16 curr_speed;
u16 characteristics;
u16 family2;
u16 core_count2;
u16 core_enabled2;
u16 thread_count2;
u16 thread_enabled;
u8 type;
u8 family;
u8 voltage;
u8 status;
u8 upgrade;
u8 core_count;
u8 core_enabled;
u8 thread_count;
char *socket_design;
char *manufacturer;
char *version;
char *sn;
char *asset_tag;
char *pn;
+};
+struct sysinfo_plat {
struct processor_info *processor;
struct cache_info *cache;
/* add other sysinfo structure here */
+};
+#if defined CONFIG_SYSINFO_SMBIOS +int sysinfo_get_cache_info(u8 level, struct cache_info *cache_info); +void sysinfo_cache_info_default(struct cache_info *ci); +int sysinfo_get_processor_info(struct processor_info *pinfo); +#else +static inline int sysinfo_get_cache_info(u8 level,
struct cache_info *cache_info)
+{
return -ENOSYS;
+}
+static inline void sysinfo_cache_info_default(struct cache_info *ci) +{ +}
+static inline int sysinfo_get_processor_info(struct processor_info *pinfo) +{
return -ENOSYS;
+} +#endif
+#endif /* __SMBIOS_PLAT_H */ diff --git a/include/sysinfo.h b/include/sysinfo.h index 17b2b9c7111..cb08a691270 100644 --- a/include/sysinfo.h +++ b/include/sysinfo.h @@ -11,6 +11,8 @@
struct udevice;
+#define SYSINFO_CACHE_LVL_MAX 3
/*
- This uclass encapsulates hardware methods to gather information about a
- sysinfo or a specific device such as hard-wired GPIOs on GPIO expanders,
@@ -42,18 +44,109 @@ struct udevice; enum sysinfo_id { SYSINFO_ID_NONE,
/* For SMBIOS tables */
/* BIOS Information (Type 0) */
SYSINFO_ID_SMBIOS_BIOS_VENDOR,
SYSINFO_ID_SMBIOS_BIOS_VER,
SYSINFO_ID_SMBIOS_BIOS_REL_DATE,
/* System Information (Type 1) */ SYSINFO_ID_SMBIOS_SYSTEM_MANUFACTURER, SYSINFO_ID_SMBIOS_SYSTEM_PRODUCT, SYSINFO_ID_SMBIOS_SYSTEM_VERSION, SYSINFO_ID_SMBIOS_SYSTEM_SERIAL,
SYSINFO_ID_SMBIOS_SYSTEM_WAKEUP, SYSINFO_ID_SMBIOS_SYSTEM_SKU, SYSINFO_ID_SMBIOS_SYSTEM_FAMILY,
/* Baseboard (or Module) Information (Type 2) */ SYSINFO_ID_SMBIOS_BASEBOARD_MANUFACTURER, SYSINFO_ID_SMBIOS_BASEBOARD_PRODUCT, SYSINFO_ID_SMBIOS_BASEBOARD_VERSION, SYSINFO_ID_SMBIOS_BASEBOARD_SERIAL, SYSINFO_ID_SMBIOS_BASEBOARD_ASSET_TAG,
SYSINFO_ID_SMBIOS_BASEBOARD_FEATURE,
SYSINFO_ID_SMBIOS_BASEBOARD_CHASSIS_LOCAT,
SYSINFO_ID_SMBIOS_BASEBOARD_TYPE,
SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_NUM,
SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_HANDLE,
/* System Enclosure or Chassis (Type 3) */
SYSINFO_ID_SMBIOS_ENCLOSURE_MANUFACTURER,
SYSINFO_ID_SMBIOS_ENCLOSURE_VERSION,
SYSINFO_ID_SMBIOS_ENCLOSURE_SERIAL,
SYSINFO_ID_SMBIOS_ENCLOSURE_ASSET_TAG,
SYSINFO_ID_SMBIOS_ENCLOSURE_TYPE,
SYSINFO_ID_SMBIOS_ENCLOSURE_BOOTUP,
SYSINFO_ID_SMBIOS_ENCLOSURE_POW,
SYSINFO_ID_SMBIOS_ENCLOSURE_THERMAL,
SYSINFO_ID_SMBIOS_ENCLOSURE_SECURITY,
SYSINFO_ID_SMBIOS_ENCLOSURE_OEM,
SYSINFO_ID_SMBIOS_ENCLOSURE_HEIGHT,
SYSINFO_ID_SMBIOS_ENCLOSURE_POWCORE_NUM,
SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_CNT,
SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_LEN,
SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENTS,
SYSINFO_ID_SMBIOS_ENCLOSURE_SKU,
/* Processor Information (Type 4) */
SYSINFO_ID_SMBIOS_PROCESSOR_SOCKET,
SYSINFO_ID_SMBIOS_PROCESSOR_TYPE,
SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT,
SYSINFO_ID_SMBIOS_PROCESSOR_ID,
SYSINFO_ID_SMBIOS_PROCESSOR_VERSION,
SYSINFO_ID_SMBIOS_PROCESSOR_VOLTAGE,
SYSINFO_ID_SMBIOS_PROCESSOR_EXT_CLOCK,
SYSINFO_ID_SMBIOS_PROCESSOR_MAX_SPEED,
SYSINFO_ID_SMBIOS_PROCESSOR_CUR_SPEED,
SYSINFO_ID_SMBIOS_PROCESSOR_STATUS,
SYSINFO_ID_SMBIOS_PROCESSOR_UPGRADE,
SYSINFO_ID_SMBIOS_PROCESSOR_SN,
SYSINFO_ID_SMBIOS_PROCESSOR_ASSET_TAG,
SYSINFO_ID_SMBIOS_PROCESSOR_PN,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN,
SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT,
SYSINFO_ID_SMBIOS_PROCESSOR_CHARA,
SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY,
SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY2,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT2,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN2,
SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT2,
SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_EN,
/*
* Cache Information (Type 7)
* Each of the id should reserve space for up to
* SYSINFO_CACHE_LVL_MAX levels of cache
*/
SYSINFO_ID_SMBIOS_CACHE_LEVEL,
SYSINFO_ID_SMBIOS_CACHE_HANDLE,
SYSINFO_ID_SMBIOS_CACHE_INFO_START,
SYSINFO_ID_SMBIOS_CACHE_SOCKET = SYSINFO_ID_SMBIOS_CACHE_INFO_START,
SYSINFO_ID_SMBIOS_CACHE_CONFIG =
SYSINFO_ID_SMBIOS_CACHE_SOCKET + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE =
SYSINFO_ID_SMBIOS_CACHE_CONFIG + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE =
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_SUPSRAM_TYPE =
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_CURSRAM_TYPE =
SYSINFO_ID_SMBIOS_CACHE_SUPSRAM_TYPE + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_SPEED =
SYSINFO_ID_SMBIOS_CACHE_CURSRAM_TYPE + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_ERRCOR_TYPE =
SYSINFO_ID_SMBIOS_CACHE_SPEED + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE =
SYSINFO_ID_SMBIOS_CACHE_ERRCOR_TYPE + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_ASSOC =
SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2 =
SYSINFO_ID_SMBIOS_CACHE_ASSOC + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2 =
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2 + SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_INFO_END =
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2 + SYSINFO_CACHE_LVL_MAX - 1,
This seems to be allocating sequential values for each cache? Instead, we should add a 'seq' parameter to get_data()
Sorry for not responding to this comment, actually I would prefer to use get_str or get_val as it allows to check whether values from sysinfo driver are missing and fallback to the value from dt node one by one.
Yes that is good...I had assumed this was just data, rather than string/int.
My main point is that we need an indexed lookup, where on SYSINFO_ID can be used to lookup up multiple values, with an index, since the scheme in this patch is a little unwieldy.
I understand what you are concerned about. Using a unique id for one value allows each field to independently fallback to the value from the dt node. For the scenario of cache information, the values from each level should be independently retrieved from either sysinfo driver or dt node. But if we group the values from multiple levels using the same id, we lose the independence. The only disadvantage here is some of the SYSINFO_IDs are reserved in an implicit manner which is a trade-off.
Could you give an example of what the DT node looks like?
Do we expect to put the cache info in a DT node...I wonder if it might be OK to not allow that?
But if we need it, the proper DT way would be to have a list, e.g.
level0 { associativity = ... max-size = ... }; level1 { associativity = ... max-size = ... }
Would that work?
Regards, Simon

Hi Simon,
On Fri, 6 Dec 2024 at 18:44, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Fri, 6 Dec 2024 at 08:54, Raymond Mao raymond.mao@linaro.org wrote:
Hi Simon,
On Fri, 6 Dec 2024 at 10:31, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Thu, 5 Dec 2024 at 10:28, Raymond Mao raymond.mao@linaro.org
wrote:
Hi Simon,
On Mon, 28 Oct 2024 at 13:04, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Tue, 22 Oct 2024 at 22:06, Raymond Mao raymond.mao@linaro.org
wrote:
Add sysinfo driver to retrieve smbios information (Type 4 and 7). So that the smbios library can use it for getting values from the hardware platform instead of device tree.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
Changes in v2
- Move the changes to smbios.c instead of creating new file.
- Move the headfile to include dir.
- Combine with #6(v1) patch.
- Clean-up the private data structures.
- Clean-up the operations of the strings and common values.
drivers/sysinfo/smbios.c | 228
+++++++++++++++++++++++++++++++++++++++
include/smbios.h | 60 +++++++++++ include/smbios_plat.h | 79 ++++++++++++++ include/sysinfo.h | 95 +++++++++++++++- 4 files changed, 461 insertions(+), 1 deletion(-) create mode 100644 include/smbios_plat.h
diff --git a/drivers/sysinfo/smbios.c b/drivers/sysinfo/smbios.c index a7ac8e3f072..3980845b3ba 100644 --- a/drivers/sysinfo/smbios.c +++ b/drivers/sysinfo/smbios.c @@ -5,14 +5,240 @@ */
#include <dm.h> +#include <smbios_plat.h> #include <sysinfo.h>
+/* platform information storage */ +struct processor_info processor_info; +struct cache_info cache_info[SYSINFO_CACHE_LVL_MAX]; +struct sysinfo_plat sysinfo_smbios_p = {
/* Processor Information */
.processor = &processor_info,
/* Cache Information */
.cache = &cache_info[0],
+};
+/* structure for smbios private data storage */ +struct sysinfo_plat_priv {
struct processor_info *t4;
struct smbios_type7 t7[SYSINFO_CACHE_LVL_MAX];
u16 cache_handles[SYSINFO_CACHE_LVL_MAX];
u8 cache_level;
+};
+static void smbios_cache_info_dump(struct smbios_type7
*cache_info)
+{
log_debug("SMBIOS Type 7 (Cache Information):\n");
log_debug("Cache Configuration: 0x%04x\n",
cache_info->config.data);
log_debug("Maximum Cache Size: %u KB\n",
cache_info->max_size.data);
log_debug("Installed Size: %u KB\n",
cache_info->inst_size.data);
log_debug("Supported SRAM Type: 0x%04x\n",
%#04x
cache_info->supp_sram_type.data);
log_debug("Current SRAM Type: 0x%04x\n",
cache_info->curr_sram_type.data);
log_debug("Cache Speed: %u\n", cache_info->speed);
log_debug("Error Correction Type: %u\n",
cache_info->err_corr_type);
log_debug("System Cache Type: %u\n",
cache_info->sys_cache_type);
log_debug("Associativity: %u\n",
cache_info->associativity);
log_debug("Maximum Cache Size 2: %u KB\n",
cache_info->max_size2.data);
log_debug("Installed Cache Size 2: %u KB\n",
cache_info->inst_size2.data);
+}
+/* weak function for the platforms not yet supported */ +__weak int sysinfo_get_cache_info(u8 level, struct cache_info
*cache_info)
+{
return -ENOSYS;
+}
+__weak int sysinfo_get_processor_info(struct processor_info
*pinfo)
+{
return -ENOSYS;
+}
+void sysinfo_cache_info_default(struct cache_info *ci) +{
memset(ci, 0, sizeof(*ci));
ci->config.data = SMBIOS_CACHE_LOCATE_UNKNOWN |
SMBIOS_CACHE_OP_UND;
ci->supp_sram_type.fields.unknown = 1;
ci->curr_sram_type.fields.unknown = 1;
ci->speed = SMBIOS_CACHE_SPEED_UNKNOWN;
ci->err_corr_type = SMBIOS_CACHE_ERRCORR_UNKNOWN;
ci->cache_type = SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN;
+}
+static int sysinfo_plat_detect(struct udevice *dev) +{
return 0;
+}
+static int sysinfo_plat_get_str(struct udevice *dev, int id,
size_t size, char *val)
+{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
const char *str = NULL;
switch (id) {
case SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT:
These are getting too long.
How about SYSINFOSM_PROC_MANUF ?
We can use SYSINFOSM as short for SYSINFO_ID_SMBIOS
str = priv->t4->manufacturer;
break;
default:
break;
}
if (!str)
return -ENOSYS;
strlcpy(val, str, size);
return 0;
+}
+static int sysinfo_plat_get_int(struct udevice *dev, int id, int
*val)
+{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
u8 i;
if (id >= SYSINFO_ID_SMBIOS_CACHE_INFO_START &&
id <= SYSINFO_ID_SMBIOS_CACHE_INFO_END) {
/* For smbios type 7 */
for (i = 0; i < priv->cache_level; i++) {
switch (id - i) {
case SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE:
*val = priv->t7[i].max_size.data;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_INST_SIZE:
*val = priv->t7[i].inst_size.data;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE:
*val = priv->t7[i].sys_cache_type;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_ASSOC:
*val = priv->t7[i].associativity;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2:
*val = priv->t7[i].max_size2.data;
return 0;
case SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2:
*val = priv->t7[i].inst_size2.data;
return 0;
default:
break;
}
}
return -ENOSYS;
}
switch (id) {
case SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT:
*val = priv->t4->core_count;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN:
*val = priv->t4->core_enabled;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_CHARA:
*val = priv->t4->characteristics;
break;
case SYSINFO_ID_SMBIOS_CACHE_LEVEL:
if (!priv->cache_level) /* No cache detected */
return -ENOSYS;
*val = priv->cache_level - 1;
break;
default:
return -ENOSYS;
}
return 0;
+}
+static int sysinfo_plat_get_data(struct udevice *dev, int id,
uchar **buf,
How about void **, so we don't need to cast below?
size_t *size)
+{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
switch (id) {
case SYSINFO_ID_SMBIOS_PROCESSOR_ID:
*buf = (uchar *)priv->t4->id;
*size = sizeof(priv->t4->id);
break;
case SYSINFO_ID_SMBIOS_CACHE_HANDLE:
*buf = (uchar *)(&priv->cache_handles[0]);
Isn't that the same as:
*buf = (uchar *)&priv->cache_handles;
*size = sizeof(priv->cache_handles);
break;
default:
return -EOPNOTSUPP;
}
return 0;
+}
+static int sysinfo_plat_probe(struct udevice *dev) +{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
struct sysinfo_plat *plat = &sysinfo_smbios_p;
u8 level;
if (!sysinfo_get_processor_info(plat->processor))
priv->t4 = plat->processor;
for (level = 0; level < SYSINFO_CACHE_LVL_MAX; level++) {
struct cache_info *pcache = plat->cache + level;
if (sysinfo_get_cache_info(level, pcache))
break; /* no more levels */
/*
* Fill in the SMBIOS type 7 structure,
* skip the header members (type, length, handle),
* and the ones in DT smbios node.
*/
priv->t7[level].sys_cache_type =
pcache->cache_type;
priv->t7[level].associativity =
pcache->associativity;
if (pcache->max_size > SMBIOS_CACHE_SIZE_EXT_KB) {
priv->t7[level].max_size.data = 0xFFFF;
priv->t7[level].max_size2.fields.size =
pcache->max_size / 64;
priv->t7[level].max_size2.fields.granu =
SMBIOS_CACHE_GRANU_64K;
} else {
priv->t7[level].max_size.fields.size =
pcache->max_size;
priv->t7[level].max_size.fields.granu =
SMBIOS_CACHE_GRANU_1K;
priv->t7[level].max_size2.data = 0;
}
if (pcache->inst_size > SMBIOS_CACHE_SIZE_EXT_KB) {
priv->t7[level].inst_size.data = 0xFFFF;
priv->t7[level].inst_size2.fields.size =
pcache->inst_size / 64;
priv->t7[level].inst_size2.fields.granu =
SMBIOS_CACHE_GRANU_64K;
} else {
priv->t7[level].inst_size.fields.size =
pcache->inst_size;
priv->t7[level].inst_size.fields.granu =
SMBIOS_CACHE_GRANU_1K;
priv->t7[level].inst_size2.data = 0;
}
smbios_cache_info_dump(&priv->t7[level]);
}
if (!level) /* no cache detected */
return -ENOSYS;
priv->cache_level = level;
return 0;
+}
static const struct udevice_id sysinfo_smbios_ids[] = { { .compatible = "u-boot,sysinfo-smbios" }, { /* sentinel */ } };
static const struct sysinfo_ops sysinfo_smbios_ops = {
.detect = sysinfo_plat_detect,
.get_str = sysinfo_plat_get_str,
.get_int = sysinfo_plat_get_int,
.get_data = sysinfo_plat_get_data,
};
U_BOOT_DRIVER(sysinfo_smbios) = { @@ -20,4 +246,6 @@ U_BOOT_DRIVER(sysinfo_smbios) = { .id = UCLASS_SYSINFO, .of_match = sysinfo_smbios_ids, .ops = &sysinfo_smbios_ops,
.priv_auto = sizeof(struct sysinfo_plat_priv),
.probe = sysinfo_plat_probe,
}; diff --git a/include/smbios.h b/include/smbios.h index 78fd14d881b..cb4b3e08b3a 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -187,6 +187,66 @@ struct __packed smbios_type4 { char eos[SMBIOS_STRUCT_EOS_BYTES]; };
+union cache_config {
struct {
u16 level:3;
u16 bsocketed:1;
u16 rsvd0:1;
u16 locate:2;
u16 benabled:1;
u16 opmode:2;
u16 rsvd1:6;
} fields;
u16 data;
+};
+union cache_size_word {
struct {
u16 size:15;
u16 granu:1;
} fields;
u16 data;
+};
+union cache_size_dword {
struct {
u32 size:31;
u32 granu:1;
} fields;
u32 data;
+};
+union cache_sram_type {
struct {
u16 other:1;
u16 unknown:1;
u16 nonburst:1;
u16 burst:1;
u16 plburst:1;
u16 sync:1;
u16 async:1;
u16 rsvd:9;
} fields;
u16 data;
+};
+struct __packed smbios_type7 {
struct smbios_header hdr;
u8 socket_design;
union cache_config config;
union cache_size_word max_size;
union cache_size_word inst_size;
union cache_sram_type supp_sram_type;
union cache_sram_type curr_sram_type;
u8 speed;
u8 err_corr_type;
u8 sys_cache_type;
u8 associativity;
union cache_size_dword max_size2;
union cache_size_dword inst_size2;
char eos[SMBIOS_STRUCT_EOS_BYTES];
+};
struct __packed smbios_type32 { u8 type; u8 length; diff --git a/include/smbios_plat.h b/include/smbios_plat.h new file mode 100644 index 00000000000..70089d5a2ba --- /dev/null +++ b/include/smbios_plat.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (c) 2024 Linaro Limited
- Author: Raymond Mao raymond.mao@linaro.org
- */
+#ifndef __SMBIOS_PLAT_H +#define __SMBIOS_PLAT_H
+#include <smbios.h>
+struct cache_info {
union cache_config config;
union cache_sram_type supp_sram_type;
union cache_sram_type curr_sram_type;
u32 line_size;
u32 associativity;
u32 max_size;
u32 inst_size;
u8 cache_type;
u8 speed;
u8 err_corr_type;
char *socket_design;
+};
+struct processor_info {
u32 id[2];
u16 ext_clock;
u16 max_speed;
u16 curr_speed;
u16 characteristics;
u16 family2;
u16 core_count2;
u16 core_enabled2;
u16 thread_count2;
u16 thread_enabled;
u8 type;
u8 family;
u8 voltage;
u8 status;
u8 upgrade;
u8 core_count;
u8 core_enabled;
u8 thread_count;
char *socket_design;
char *manufacturer;
char *version;
char *sn;
char *asset_tag;
char *pn;
+};
+struct sysinfo_plat {
struct processor_info *processor;
struct cache_info *cache;
/* add other sysinfo structure here */
+};
+#if defined CONFIG_SYSINFO_SMBIOS +int sysinfo_get_cache_info(u8 level, struct cache_info
*cache_info);
+void sysinfo_cache_info_default(struct cache_info *ci); +int sysinfo_get_processor_info(struct processor_info *pinfo); +#else +static inline int sysinfo_get_cache_info(u8 level,
struct cache_info
*cache_info)
+{
return -ENOSYS;
+}
+static inline void sysinfo_cache_info_default(struct cache_info
*ci)
+{ +}
+static inline int sysinfo_get_processor_info(struct
processor_info *pinfo)
+{
return -ENOSYS;
+} +#endif
+#endif /* __SMBIOS_PLAT_H */ diff --git a/include/sysinfo.h b/include/sysinfo.h index 17b2b9c7111..cb08a691270 100644 --- a/include/sysinfo.h +++ b/include/sysinfo.h @@ -11,6 +11,8 @@
struct udevice;
+#define SYSINFO_CACHE_LVL_MAX 3
/*
- This uclass encapsulates hardware methods to gather
information about a
- sysinfo or a specific device such as hard-wired GPIOs on GPIO
expanders,
@@ -42,18 +44,109 @@ struct udevice; enum sysinfo_id { SYSINFO_ID_NONE,
/* For SMBIOS tables */
/* BIOS Information (Type 0) */
SYSINFO_ID_SMBIOS_BIOS_VENDOR,
SYSINFO_ID_SMBIOS_BIOS_VER,
SYSINFO_ID_SMBIOS_BIOS_REL_DATE,
/* System Information (Type 1) */ SYSINFO_ID_SMBIOS_SYSTEM_MANUFACTURER, SYSINFO_ID_SMBIOS_SYSTEM_PRODUCT, SYSINFO_ID_SMBIOS_SYSTEM_VERSION, SYSINFO_ID_SMBIOS_SYSTEM_SERIAL,
SYSINFO_ID_SMBIOS_SYSTEM_WAKEUP, SYSINFO_ID_SMBIOS_SYSTEM_SKU, SYSINFO_ID_SMBIOS_SYSTEM_FAMILY,
/* Baseboard (or Module) Information (Type 2) */ SYSINFO_ID_SMBIOS_BASEBOARD_MANUFACTURER, SYSINFO_ID_SMBIOS_BASEBOARD_PRODUCT, SYSINFO_ID_SMBIOS_BASEBOARD_VERSION, SYSINFO_ID_SMBIOS_BASEBOARD_SERIAL, SYSINFO_ID_SMBIOS_BASEBOARD_ASSET_TAG,
SYSINFO_ID_SMBIOS_BASEBOARD_FEATURE,
SYSINFO_ID_SMBIOS_BASEBOARD_CHASSIS_LOCAT,
SYSINFO_ID_SMBIOS_BASEBOARD_TYPE,
SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_NUM,
SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_HANDLE,
/* System Enclosure or Chassis (Type 3) */
SYSINFO_ID_SMBIOS_ENCLOSURE_MANUFACTURER,
SYSINFO_ID_SMBIOS_ENCLOSURE_VERSION,
SYSINFO_ID_SMBIOS_ENCLOSURE_SERIAL,
SYSINFO_ID_SMBIOS_ENCLOSURE_ASSET_TAG,
SYSINFO_ID_SMBIOS_ENCLOSURE_TYPE,
SYSINFO_ID_SMBIOS_ENCLOSURE_BOOTUP,
SYSINFO_ID_SMBIOS_ENCLOSURE_POW,
SYSINFO_ID_SMBIOS_ENCLOSURE_THERMAL,
SYSINFO_ID_SMBIOS_ENCLOSURE_SECURITY,
SYSINFO_ID_SMBIOS_ENCLOSURE_OEM,
SYSINFO_ID_SMBIOS_ENCLOSURE_HEIGHT,
SYSINFO_ID_SMBIOS_ENCLOSURE_POWCORE_NUM,
SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_CNT,
SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_LEN,
SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENTS,
SYSINFO_ID_SMBIOS_ENCLOSURE_SKU,
/* Processor Information (Type 4) */
SYSINFO_ID_SMBIOS_PROCESSOR_SOCKET,
SYSINFO_ID_SMBIOS_PROCESSOR_TYPE,
SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT,
SYSINFO_ID_SMBIOS_PROCESSOR_ID,
SYSINFO_ID_SMBIOS_PROCESSOR_VERSION,
SYSINFO_ID_SMBIOS_PROCESSOR_VOLTAGE,
SYSINFO_ID_SMBIOS_PROCESSOR_EXT_CLOCK,
SYSINFO_ID_SMBIOS_PROCESSOR_MAX_SPEED,
SYSINFO_ID_SMBIOS_PROCESSOR_CUR_SPEED,
SYSINFO_ID_SMBIOS_PROCESSOR_STATUS,
SYSINFO_ID_SMBIOS_PROCESSOR_UPGRADE,
SYSINFO_ID_SMBIOS_PROCESSOR_SN,
SYSINFO_ID_SMBIOS_PROCESSOR_ASSET_TAG,
SYSINFO_ID_SMBIOS_PROCESSOR_PN,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN,
SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT,
SYSINFO_ID_SMBIOS_PROCESSOR_CHARA,
SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY,
SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY2,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT2,
SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN2,
SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT2,
SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_EN,
/*
* Cache Information (Type 7)
* Each of the id should reserve space for up to
* SYSINFO_CACHE_LVL_MAX levels of cache
*/
SYSINFO_ID_SMBIOS_CACHE_LEVEL,
SYSINFO_ID_SMBIOS_CACHE_HANDLE,
SYSINFO_ID_SMBIOS_CACHE_INFO_START,
SYSINFO_ID_SMBIOS_CACHE_SOCKET =
SYSINFO_ID_SMBIOS_CACHE_INFO_START,
SYSINFO_ID_SMBIOS_CACHE_CONFIG =
SYSINFO_ID_SMBIOS_CACHE_SOCKET +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE =
SYSINFO_ID_SMBIOS_CACHE_CONFIG +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE =
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_SUPSRAM_TYPE =
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_CURSRAM_TYPE =
SYSINFO_ID_SMBIOS_CACHE_SUPSRAM_TYPE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_SPEED =
SYSINFO_ID_SMBIOS_CACHE_CURSRAM_TYPE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_ERRCOR_TYPE =
SYSINFO_ID_SMBIOS_CACHE_SPEED +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE =
SYSINFO_ID_SMBIOS_CACHE_ERRCOR_TYPE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_ASSOC =
SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2 =
SYSINFO_ID_SMBIOS_CACHE_ASSOC +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2 =
SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2 +
SYSINFO_CACHE_LVL_MAX,
SYSINFO_ID_SMBIOS_CACHE_INFO_END =
SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2 +
SYSINFO_CACHE_LVL_MAX - 1,
This seems to be allocating sequential values for each cache?
Instead, we should add a 'seq' parameter to get_data()
Sorry for not responding to this comment, actually I would prefer to
use get_str or get_val as it allows
to check whether values from sysinfo driver are missing and fallback
to the value from dt node one by one.
Yes that is good...I had assumed this was just data, rather than
string/int.
My main point is that we need an indexed lookup, where on SYSINFO_ID can be used to lookup up multiple values, with an index, since the scheme in this patch is a little unwieldy.
I understand what you are concerned about. Using a unique id for one value allows each field to independently
fallback to the value from the dt node.
For the scenario of cache information, the values from each level should
be independently retrieved from
either sysinfo driver or dt node. But if we group the values from multiple levels using the same id, we
lose the independence.
The only disadvantage here is some of the SYSINFO_IDs are reserved in an
implicit manner which is a
trade-off.
Could you give an example of what the DT node looks like?
Do we expect to put the cache info in a DT node...I wonder if it might be OK to not allow that?
But if we need it, the proper DT way would be to have a list, e.g.
level0 { associativity = ... max-size = ... }; level1 { associativity = ... max-size = ... }
Would that work?
Below is an example of a full cache SMBIOS sub-node (Maybe I should add it into the commit message):
``` cache { l1-cache { socket-design = ""; config = <(SMBIOS_CACHE_LEVEL_1 | SMBIOS_CACHE_ENABLED | SMBIOS_CACHE_OP_WB)>; max-size = <0>; installed-size = <0>; supported-sram-type = <SMBIOS_CACHE_SRAM_TYPE_UNKNOWN>; speed = <0>; error-correction-type = <SMBIOS_CACHE_ERRCORR_UNKNOWN>; system-cache-type = <SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN>; associativity = <SMBIOS_CACHE_ASSOC_UNKNOWN>; max-size2 = <0>; installed-size2 = <0>; }; l2-cache { socket-design = ""; config = <(SMBIOS_CACHE_LEVEL_2 | SMBIOS_CACHE_ENABLED | SMBIOS_CACHE_OP_WB)>; max-size = <0>; installed-size = <0>; supported-sram-type = <SMBIOS_CACHE_SRAM_TYPE_UNKNOWN>; speed = <0>; error-correction-type = <SMBIOS_CACHE_ERRCORR_UNKNOWN>; system-cache-type = <SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN>; associativity = <SMBIOS_CACHE_ASSOC_UNKNOWN>; max-size2 = <0>; installed-size2 = <0>; }; }; ```
Aarch64 platforms can retrieve the "arch-specific" values from the sysinfo driver I implemented with this series, for example, max-size, installed-size, max-size2, installed-size2 and associativity, these fields are optional in the DT, the driver will search for the values from sysinfo driver first - that is why I prefer to have independent SYSID for each of the values.
For those "vendor-specific" values, there is no way to retrieve them from arm registers, the only way is through the DT node. If user don't want to specify a value for them, just ignore them from the DT and "smbios_get_val_si()" allows passing in a default value.
So it is flexible to allow specifying values through arch-specific driver, DT node, or user defined default values.
Regards, Raymond

Current smbios library does not fully match to the specification. It hardcodes values instead of exposing values from the device. It does not support dynamic length for contained object handles or elements and misses the handling of a few of fields.
The refactoring of this patch includes: 1. Expose values from device via sysinfo interface. 2. Replace smbios_add_prop with smbios_add_prop_si to allow getting string values from sysinfo. 3. Add smbios_get_val_si to get int values from sysinfo. 4. Use sysinfo_get_data to get data area. 5. Miscellaneous fixes in smbios.
Moreover, this patch adds SMBIOS type 7 (cache information) write functions. Link cache handles from type 7 to type 4.
Signed-off-by: Raymond Mao raymond.mao@linaro.org --- Changes in v2 - Combine with #7(v1) patch. - Move the changes of cmd/smbios.c to a separated patch. - Refactor smbios_get_val_si to get values from dt when values are not available from sysinfo driver. - Miscellaneous refactoring.
include/smbios.h | 14 +- lib/smbios.c | 420 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 383 insertions(+), 51 deletions(-)
diff --git a/include/smbios.h b/include/smbios.h index cb4b3e08b3a..18f568f9b0d 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -122,6 +122,8 @@ struct __packed smbios_type1 { char eos[SMBIOS_STRUCT_EOS_BYTES]; };
+#define SMBIOS_TYPE2_CON_OBJ_HANDLE_SIZE sizeof(u16) + struct __packed smbios_type2 { struct smbios_header hdr; u8 manufacturer; @@ -134,6 +136,10 @@ struct __packed smbios_type2 { u16 chassis_handle; u8 board_type; u8 number_contained_objects; + /* + * Dynamic bytes will be inserted here to store the objects. + * length is equal to 'number_contained_objects'. + */ char eos[SMBIOS_STRUCT_EOS_BYTES]; };
@@ -153,12 +159,17 @@ struct __packed smbios_type3 { u8 number_of_power_cords; u8 element_count; u8 element_record_length; + /* + * Dynamic bytes will be inserted here to store the elements. + * length is equal to 'element_record_length' * 'element_record_length' + */ + u8 sku_number; char eos[SMBIOS_STRUCT_EOS_BYTES]; };
struct __packed smbios_type4 { struct smbios_header hdr; - u8 socket_designation; + u8 socket_design; u8 processor_type; u8 processor_family; u8 processor_manufacturer; @@ -184,6 +195,7 @@ struct __packed smbios_type4 { u16 core_count2; u16 core_enabled2; u16 thread_count2; + u16 thread_enabled; char eos[SMBIOS_STRUCT_EOS_BYTES]; };
diff --git a/lib/smbios.c b/lib/smbios.c index 886c40e7594..c2763d036a7 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -206,6 +206,34 @@ void get_str_from_dt(const struct map_sysinfo *nprop, char *str, size_t size) } }
+/** + * smbios_get_val_si() - Get value from the devicetree or sysinfo + * + * @ctx: context of SMBIOS + * @prop: property to read + * @sysinfo_id: unique identifier for the value to be read + * Return: 0 if not found, else value from the devicetree or sysinfo + */ +static int smbios_get_val_si(struct smbios_ctx *ctx, const char *prop, + int sysinfo_id) +{ + int val; + + if (!sysinfo_id || !ctx->dev) + return 0; + + if (!sysinfo_get_int(ctx->dev, sysinfo_id, &val)) + return val; + + if (!IS_ENABLED(CONFIG_OF_CONTROL) || !prop || !ofnode_valid(ctx->node)) + return 0; + + if (!ofnode_read_u32(ctx->node, prop, &val)) + return val; + + return 0; +} + /** * smbios_add_prop_si() - Add a property from the devicetree or sysinfo * @@ -225,9 +253,6 @@ static int smbios_add_prop_si(struct smbios_ctx *ctx, const char *prop, if (!dval || !*dval) dval = NULL;
- if (!prop) - return smbios_add_string(ctx, dval); - if (sysinfo_id && ctx->dev) { char val[SMBIOS_STR_MAX];
@@ -235,6 +260,9 @@ static int smbios_add_prop_si(struct smbios_ctx *ctx, const char *prop, if (!ret) return smbios_add_string(ctx, val); } + if (!prop) + return smbios_add_string(ctx, dval); + if (IS_ENABLED(CONFIG_OF_CONTROL)) { const char *str = NULL; char str_dt[128] = { 0 }; @@ -336,9 +364,12 @@ static int smbios_write_type0(ulong *current, int handle, memset(t, 0, len); fill_smbios_header(t, SMBIOS_BIOS_INFORMATION, len, handle); smbios_set_eos(ctx, t->eos); - t->vendor = smbios_add_prop(ctx, NULL, "U-Boot"); + t->vendor = smbios_add_prop_si(ctx, NULL, SYSINFO_ID_SMBIOS_BIOS_VENDOR, + "U-Boot");
- t->bios_ver = smbios_add_prop(ctx, "version", PLAIN_VERSION); + t->bios_ver = smbios_add_prop_si(ctx, "version", + SYSINFO_ID_SMBIOS_BIOS_VER, + PLAIN_VERSION); if (t->bios_ver) gd->smbios_version = ctx->last_str; log_debug("smbios_version = %p: '%s'\n", gd->smbios_version, @@ -347,7 +378,9 @@ static int smbios_write_type0(ulong *current, int handle, print_buffer((ulong)gd->smbios_version, gd->smbios_version, 1, strlen(gd->smbios_version) + 1, 0); #endif - t->bios_release_date = smbios_add_prop(ctx, NULL, U_BOOT_DMI_DATE); + t->bios_release_date = + smbios_add_prop_si(ctx, NULL, SYSINFO_ID_SMBIOS_BIOS_REL_DATE, + U_BOOT_DMI_DATE); #ifdef CONFIG_ROM_SIZE if (CONFIG_ROM_SIZE < SZ_16M) { t->bios_rom_size = (CONFIG_ROM_SIZE / 65536) - 1; @@ -392,9 +425,11 @@ static int smbios_write_type1(ulong *current, int handle, memset(t, 0, len); fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, handle); smbios_set_eos(ctx, t->eos); - t->manufacturer = smbios_add_prop_si(ctx, "manufacturer", - SYSINFO_ID_SMBIOS_SYSTEM_MANUFACTURER, - NULL); + + t->manufacturer = + smbios_add_prop_si(ctx, "manufacturer", + SYSINFO_ID_SMBIOS_SYSTEM_MANUFACTURER, + NULL); t->product_name = smbios_add_prop_si(ctx, "product", SYSINFO_ID_SMBIOS_SYSTEM_PRODUCT, NULL); @@ -405,11 +440,14 @@ static int smbios_write_type1(ulong *current, int handle, t->serial_number = smbios_add_prop(ctx, NULL, serial_str); strlcpy((char *)t->uuid, serial_str, sizeof(t->uuid)); } else { - t->serial_number = smbios_add_prop_si(ctx, "serial", - SYSINFO_ID_SMBIOS_SYSTEM_SERIAL, - NULL); + t->serial_number = + smbios_add_prop_si(ctx, "serial", + SYSINFO_ID_SMBIOS_SYSTEM_SERIAL, + NULL); } - t->wakeup_type = SMBIOS_WAKEUP_TYPE_UNKNOWN; + t->wakeup_type = + smbios_get_val_si(ctx, "wakeup-type", + SYSINFO_ID_SMBIOS_SYSTEM_WAKEUP); t->sku_number = smbios_add_prop_si(ctx, "sku", SYSINFO_ID_SMBIOS_SYSTEM_SKU, NULL); t->family = smbios_add_prop_si(ctx, "family", @@ -427,29 +465,59 @@ static int smbios_write_type2(ulong *current, int handle, { struct smbios_type2 *t; int len = sizeof(*t); + u8 *eos_addr;
+ /* + * reserve the space for the dynamic bytes of contained object handles. + * TODO: len += <obj_handle_num> * SMBIOS_TYPE2_CON_OBJ_HANDLE_SIZE + * obj_handle_num can be from DT node "baseboard" or sysinfo driver. + */ t = map_sysmem(*current, len); memset(t, 0, len); fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, handle); - smbios_set_eos(ctx, t->eos); - t->manufacturer = smbios_add_prop_si(ctx, "manufacturer", - SYSINFO_ID_SMBIOS_BASEBOARD_MANUFACTURER, - NULL); - t->product_name = smbios_add_prop_si(ctx, "product", - SYSINFO_ID_SMBIOS_BASEBOARD_PRODUCT, - NULL); - t->version = smbios_add_prop_si(ctx, "version", - SYSINFO_ID_SMBIOS_BASEBOARD_VERSION, - NULL);
- t->serial_number = smbios_add_prop_si(ctx, "serial", - SYSINFO_ID_SMBIOS_BASEBOARD_SERIAL, - NULL); - t->asset_tag_number = smbios_add_prop_si(ctx, "asset-tag", - SYSINFO_ID_SMBIOS_BASEBOARD_ASSET_TAG, - NULL); - t->feature_flags = SMBIOS_BOARD_FEAT_HOST_BOARD; - t->board_type = SMBIOS_BOARD_TYPE_MOTHERBOARD; + /* eos is at the end of the structure */ + eos_addr = (u8 *)t + len - sizeof(t->eos); + smbios_set_eos(ctx, eos_addr); + + t->manufacturer = + smbios_add_prop_si(ctx, "manufacturer", + SYSINFO_ID_SMBIOS_BASEBOARD_MANUFACTURER, + NULL); + t->product_name = + smbios_add_prop_si(ctx, "product", + SYSINFO_ID_SMBIOS_BASEBOARD_PRODUCT, + NULL); + t->version = + smbios_add_prop_si(ctx, "version", + SYSINFO_ID_SMBIOS_BASEBOARD_VERSION, + NULL); + t->serial_number = + smbios_add_prop_si(ctx, "serial", + SYSINFO_ID_SMBIOS_BASEBOARD_SERIAL, + NULL); + t->asset_tag_number = + smbios_add_prop_si(ctx, "asset-tag", + SYSINFO_ID_SMBIOS_BASEBOARD_ASSET_TAG, + NULL); + t->feature_flags = + smbios_get_val_si(ctx, "feature-flags", + SYSINFO_ID_SMBIOS_BASEBOARD_FEATURE); + + t->chassis_location = + smbios_add_prop_si(ctx, "chassis-location", + SYSINFO_ID_SMBIOS_BASEBOARD_CHASSIS_LOCAT, + NULL); + t->board_type = + smbios_get_val_si(ctx, "board-type", + SYSINFO_ID_SMBIOS_BASEBOARD_TYPE); + + /* + * TODO: + * Populate the Contained Object Handles if they exist + * t->number_contained_objects = <obj_handle_num>; + */ + t->chassis_handle = handle + 1;
len = t->hdr.length + smbios_string_table_len(ctx); @@ -464,17 +532,73 @@ static int smbios_write_type3(ulong *current, int handle, { struct smbios_type3 *t; int len = sizeof(*t); + u8 *elem_addr, *eos_addr, *sku_num_addr; + size_t elem_size = 0; + + /* + * reserve the space for the dynamic bytes of contained elements. + * TODO: elem_size = <element_count> * <element_record_length> + * element_count and element_record_length can be from DT node + * "chassis" or sysinfo driver. + */ + len += elem_size;
t = map_sysmem(*current, len); memset(t, 0, len); fill_smbios_header(t, SMBIOS_SYSTEM_ENCLOSURE, len, handle); - smbios_set_eos(ctx, t->eos); - t->manufacturer = smbios_add_prop(ctx, "manufacturer", NULL); - t->chassis_type = SMBIOS_ENCLOSURE_DESKTOP; - t->bootup_state = SMBIOS_STATE_SAFE; - t->power_supply_state = SMBIOS_STATE_SAFE; - t->thermal_state = SMBIOS_STATE_SAFE; - t->security_status = SMBIOS_SECURITY_NONE; + elem_addr = (u8 *)t + offsetof(struct smbios_type3, sku_number); + sku_num_addr = elem_addr + elem_size; + + /* eos is at the end of the structure */ + eos_addr = (u8 *)t + len - sizeof(t->eos); + smbios_set_eos(ctx, eos_addr); + + t->manufacturer = + smbios_add_prop_si(ctx, "manufacturer", + SYSINFO_ID_SMBIOS_ENCLOSURE_MANUFACTURER, + NULL); + + t->chassis_type = smbios_get_val_si(ctx, "chassis-type", + SYSINFO_ID_SMBIOS_ENCLOSURE_TYPE); + t->version = smbios_add_prop_si(ctx, "version", + SYSINFO_ID_SMBIOS_ENCLOSURE_VERSION, + NULL); + t->serial_number = + smbios_add_prop_si(ctx, "serial", + SYSINFO_ID_SMBIOS_ENCLOSURE_SERIAL, + NULL); + t->asset_tag_number = + smbios_add_prop_si(ctx, "asset-tag", + SYSINFO_ID_SMBIOS_BASEBOARD_ASSET_TAG, + NULL); + t->bootup_state = smbios_get_val_si(ctx, "bootup-state", + SYSINFO_ID_SMBIOS_ENCLOSURE_BOOTUP); + t->power_supply_state = + smbios_get_val_si(ctx, "power-supply-state", + SYSINFO_ID_SMBIOS_ENCLOSURE_POW); + t->thermal_state = + smbios_get_val_si(ctx, "thermal-state", + SYSINFO_ID_SMBIOS_ENCLOSURE_THERMAL); + t->security_status = + smbios_get_val_si(ctx, "security-status", + SYSINFO_ID_SMBIOS_ENCLOSURE_SECURITY); + t->oem_defined = smbios_get_val_si(ctx, "oem-defined", + SYSINFO_ID_SMBIOS_ENCLOSURE_OEM); + t->height = smbios_get_val_si(ctx, "height", + SYSINFO_ID_SMBIOS_ENCLOSURE_HEIGHT); + t->number_of_power_cords = + smbios_get_val_si(ctx, "number-of-power-cords", + SYSINFO_ID_SMBIOS_ENCLOSURE_POWCORE_NUM); + + /* + * TODO: Populate the Contained Element Record if they exist + * t->element_count = <element_num>; + * t->element_record_length = <element_len>; + */ + + *sku_num_addr = + smbios_add_prop_si(ctx, "sku", SYSINFO_ID_SMBIOS_ENCLOSURE_SKU, + NULL);
len = t->hdr.length + smbios_string_table_len(ctx); *current += len; @@ -489,6 +613,8 @@ static void smbios_write_type4_dm(struct smbios_type4 *t, u16 processor_family = SMBIOS_PROCESSOR_FAMILY_UNKNOWN; const char *vendor = NULL; const char *name = NULL; + u8 *id_data = NULL; + size_t id_size = 0;
#ifdef CONFIG_CPU char processor_name[49]; @@ -510,11 +636,33 @@ static void smbios_write_type4_dm(struct smbios_type4 *t, name = processor_name; } #endif + if (processor_family == SMBIOS_PROCESSOR_FAMILY_UNKNOWN) + processor_family = + smbios_get_val_si(ctx, "family", + SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY); + + if (processor_family == SMBIOS_PROCESSOR_FAMILY_EXT) + t->processor_family2 = + smbios_get_val_si(ctx, "family2", + SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY2); + + t->processor_family = processor_family; + t->processor_manufacturer = + smbios_add_prop_si(ctx, "manufacturer", + SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT, + vendor); + t->processor_version = + smbios_add_prop_si(ctx, "version", + SYSINFO_ID_SMBIOS_PROCESSOR_VERSION, + name); + + if (t->processor_id[0] || t->processor_id[1] || + sysinfo_get_data(ctx->dev, SYSINFO_ID_SMBIOS_PROCESSOR_ID, + &id_data, &id_size)) + return;
- t->processor_family = 0xfe; - t->processor_family2 = processor_family; - t->processor_manufacturer = smbios_add_prop(ctx, NULL, vendor); - t->processor_version = smbios_add_prop(ctx, NULL, name); + if (id_data && id_size == sizeof(t->processor_id)) + memcpy((u8 *)t->processor_id, id_data, id_size); }
static int smbios_write_type4(ulong *current, int handle, @@ -522,18 +670,96 @@ static int smbios_write_type4(ulong *current, int handle, { struct smbios_type4 *t; int len = sizeof(*t); + u8 *hdl; + size_t hdl_size;
t = map_sysmem(*current, len); memset(t, 0, len); fill_smbios_header(t, SMBIOS_PROCESSOR_INFORMATION, len, handle); smbios_set_eos(ctx, t->eos); - t->processor_type = SMBIOS_PROCESSOR_TYPE_CENTRAL; + t->socket_design = + smbios_add_prop_si(ctx, "socket-design", + SYSINFO_ID_SMBIOS_PROCESSOR_SOCKET, + NULL); + t->processor_type = + smbios_get_val_si(ctx, "processor-type", + SYSINFO_ID_SMBIOS_PROCESSOR_TYPE); smbios_write_type4_dm(t, ctx); - t->status = SMBIOS_PROCESSOR_STATUS_ENABLED; - t->processor_upgrade = SMBIOS_PROCESSOR_UPGRADE_NONE; - t->l1_cache_handle = 0xffff; - t->l2_cache_handle = 0xffff; - t->l3_cache_handle = 0xffff; + + t->voltage = + smbios_get_val_si(ctx, "voltage", + SYSINFO_ID_SMBIOS_PROCESSOR_VOLTAGE); + t->external_clock = + smbios_get_val_si(ctx, "external-clock", + SYSINFO_ID_SMBIOS_PROCESSOR_EXT_CLOCK); + t->max_speed = + smbios_get_val_si(ctx, "max-speed", + SYSINFO_ID_SMBIOS_PROCESSOR_MAX_SPEED); + t->current_speed = + smbios_get_val_si(ctx, "current-speed", + SYSINFO_ID_SMBIOS_PROCESSOR_CUR_SPEED); + t->status = + smbios_get_val_si(ctx, "processor-status", + SYSINFO_ID_SMBIOS_PROCESSOR_STATUS); + t->processor_upgrade = + smbios_get_val_si(ctx, "upgrade", + SYSINFO_ID_SMBIOS_PROCESSOR_UPGRADE); + + t->l1_cache_handle = SMBIOS_CACHE_HANDLE_NONE; + t->l2_cache_handle = SMBIOS_CACHE_HANDLE_NONE; + t->l3_cache_handle = SMBIOS_CACHE_HANDLE_NONE; + + /* Read the cache handles */ + if (!sysinfo_get_data(ctx->dev, SYSINFO_ID_SMBIOS_CACHE_HANDLE, + &hdl, &hdl_size) && + (hdl_size == SYSINFO_CACHE_LVL_MAX * sizeof(u16))) { + u16 *handle = (u16 *)hdl; + + if (*handle) + t->l1_cache_handle = *handle; + + handle++; + if (*handle) + t->l2_cache_handle = *handle; + + handle++; + if (*handle) + t->l3_cache_handle = *handle; + } + + t->serial_number = smbios_add_prop_si(ctx, "serial", + SYSINFO_ID_SMBIOS_PROCESSOR_SN, + NULL); + t->asset_tag = smbios_add_prop_si(ctx, "asset-tag", + SYSINFO_ID_SMBIOS_PROCESSOR_ASSET_TAG, + NULL); + t->part_number = smbios_add_prop_si(ctx, "part-number", + SYSINFO_ID_SMBIOS_PROCESSOR_PN, + NULL); + t->core_count = + smbios_get_val_si(ctx, "core-count", + SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT); + t->core_enabled = + smbios_get_val_si(ctx, "core-enabled", + SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN); + t->thread_count = + smbios_get_val_si(ctx, "thread-count", + SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT); + t->processor_characteristics = + smbios_get_val_si(ctx, "characteristics", + SYSINFO_ID_SMBIOS_PROCESSOR_CHARA); + t->core_count2 = + smbios_get_val_si(ctx, "core-count2", + SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT2); + t->core_enabled2 = + smbios_get_val_si(ctx, "core-enabled2", + SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN2); + t->thread_count2 = + smbios_get_val_si(ctx, "thread-count2", + SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT2); + t->thread_enabled = + smbios_get_val_si(ctx, "thread-enabled", + SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_EN);
len = t->hdr.length + smbios_string_table_len(ctx); *current += len; @@ -542,6 +768,98 @@ static int smbios_write_type4(ulong *current, int handle, return len; }
+static int smbios_write_type7_1level(ulong *current, int handle, + struct smbios_ctx *ctx, int level) +{ + struct smbios_type7 *t; + int len = sizeof(*t); + u8 *hdl; + size_t hdl_size; + + t = map_sysmem(*current, len); + memset(t, 0, len); + fill_smbios_header(t, SMBIOS_CACHE_INFORMATION, len, handle); + smbios_set_eos(ctx, t->eos); + + t->socket_design = + smbios_add_prop_si(ctx, "socket-design", + SYSINFO_ID_SMBIOS_CACHE_SOCKET + level, + NULL); + t->config.data = + smbios_get_val_si(ctx, "config", + SYSINFO_ID_SMBIOS_CACHE_CONFIG + level); + t->max_size.data = + smbios_get_val_si(ctx, "max-size", + SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE + level); + t->inst_size.data = + smbios_get_val_si(ctx, "installed-size", + SYSINFO_ID_SMBIOS_CACHE_INST_SIZE + level); + t->supp_sram_type.data = + smbios_get_val_si(ctx, "supported-sram-type", + SYSINFO_ID_SMBIOS_CACHE_SUPSRAM_TYPE + level); + t->curr_sram_type.data = + smbios_get_val_si(ctx, "current-sram-type", + SYSINFO_ID_SMBIOS_CACHE_CURSRAM_TYPE + level); + t->speed = smbios_get_val_si(ctx, "speed", + SYSINFO_ID_SMBIOS_CACHE_SPEED + level); + t->err_corr_type = + smbios_get_val_si(ctx, "error-correction-type", + SYSINFO_ID_SMBIOS_CACHE_ERRCOR_TYPE + level); + t->sys_cache_type = + smbios_get_val_si(ctx, "system-cache-type", + SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE + level); + t->associativity = + smbios_get_val_si(ctx, "associativity", + SYSINFO_ID_SMBIOS_CACHE_ASSOC + level); + t->max_size2.data = + smbios_get_val_si(ctx, "max-size2", + SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2 + level); + t->inst_size2.data = + smbios_get_val_si(ctx, "installed-size2", + SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2 + level); + + /* Save the cache handles */ + if (!sysinfo_get_data(ctx->dev, SYSINFO_ID_SMBIOS_CACHE_HANDLE, + &hdl, &hdl_size)) { + if (hdl_size == SYSINFO_CACHE_LVL_MAX * sizeof(u16)) + *((u16 *)hdl + level) = handle; + } + + len = t->hdr.length + smbios_string_table_len(ctx); + *current += len; + unmap_sysmem(t); + + return len; +} + +static int smbios_write_type7(ulong *current, int handle, + struct smbios_ctx *ctx) +{ + int len = 0; + int i, level; + ofnode parent = ctx->node; + struct smbios_ctx ctx_bak; + + memcpy(&ctx_bak, ctx, sizeof(ctx_bak)); + + /* Get the number of level */ + level = smbios_get_val_si(ctx, NULL, SYSINFO_ID_SMBIOS_CACHE_LEVEL); + if (level >= SYSINFO_CACHE_LVL_MAX) /* Error, return 0-length */ + return 0; + + for (i = 0; i <= level; i++) { + char buf[9] = ""; + + if (!snprintf(buf, sizeof(buf), "l%d-cache", i + 1)) + return 0; + ctx->subnode_name = buf; + ctx->node = ofnode_find_subnode(parent, ctx->subnode_name); + len += smbios_write_type7_1level(current, handle++, ctx, i); + memcpy(ctx, &ctx_bak, sizeof(*ctx)); + } + return len; +} + static int smbios_write_type32(ulong *current, int handle, struct smbios_ctx *ctx) { @@ -581,7 +899,9 @@ static struct smbios_write_method smbios_write_funcs[] = { { smbios_write_type2, "baseboard", }, /* Type 3 must immediately follow type 2 due to chassis handle. */ { smbios_write_type3, "chassis", }, - { smbios_write_type4, }, + /* Type 7 must ahead of type 4 to get cache handles. */ + { smbios_write_type7, "cache", }, + { smbios_write_type4, "processor"}, { smbios_write_type32, }, { smbios_write_type127 }, }; @@ -598,7 +918,7 @@ ulong write_smbios_table(ulong addr) int i;
ctx.node = ofnode_null(); - if (IS_ENABLED(CONFIG_OF_CONTROL) && CONFIG_IS_ENABLED(SYSINFO)) { + if (CONFIG_IS_ENABLED(SYSINFO)) { uclass_first_device(UCLASS_SYSINFO, &ctx.dev); if (ctx.dev) { int ret;

Hi Raymond,
On Tue, 22 Oct 2024 at 22:07, Raymond Mao raymond.mao@linaro.org wrote:
Current smbios library does not fully match to the specification. It hardcodes values instead of exposing values from the device. It does not support dynamic length for contained object handles or elements and misses the handling of a few of fields.
The refactoring of this patch includes:
- Expose values from device via sysinfo interface.
- Replace smbios_add_prop with smbios_add_prop_si to allow getting string values from sysinfo.
- Add smbios_get_val_si to get int values from sysinfo.
- Use sysinfo_get_data to get data area.
- Miscellaneous fixes in smbios.
Moreover, this patch adds SMBIOS type 7 (cache information) write functions. Link cache handles from type 7 to type 4.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
Changes in v2
- Combine with #7(v1) patch.
- Move the changes of cmd/smbios.c to a separated patch.
- Refactor smbios_get_val_si to get values from dt when values are not available from sysinfo driver.
- Miscellaneous refactoring.
include/smbios.h | 14 +- lib/smbios.c | 420 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 383 insertions(+), 51 deletions(-)
There's an awful lot in this patch.
Can it be split up?
Regards, Simon

Add sysinfo platform driver for all armv8 platforms to retrieve hardware information on processor and cache.
Signed-off-by: Raymond Mao raymond.mao@linaro.org --- Changes in v2 - Combine with #8(v1) patch. - Remove the handling of the common strings and values.
arch/arm/cpu/armv8/Makefile | 2 + arch/arm/cpu/armv8/sysinfo.c | 292 +++++++++++++++++++++++++++++++++++ 2 files changed, 294 insertions(+) create mode 100644 arch/arm/cpu/armv8/sysinfo.c
diff --git a/arch/arm/cpu/armv8/Makefile b/arch/arm/cpu/armv8/Makefile index bba4f570dbb..3eac8cd932b 100644 --- a/arch/arm/cpu/armv8/Makefile +++ b/arch/arm/cpu/armv8/Makefile @@ -45,3 +45,5 @@ obj-$(CONFIG_TARGET_BCMNS3) += bcmns3/ obj-$(CONFIG_XEN) += xen/ obj-$(CONFIG_ARMV8_CE_SHA1) += sha1_ce_glue.o sha1_ce_core.o obj-$(CONFIG_ARMV8_CE_SHA256) += sha256_ce_glue.o sha256_ce_core.o + +obj-$(CONFIG_SYSINFO_SMBIOS) += sysinfo.o diff --git a/arch/arm/cpu/armv8/sysinfo.c b/arch/arm/cpu/armv8/sysinfo.c new file mode 100644 index 00000000000..850142da37d --- /dev/null +++ b/arch/arm/cpu/armv8/sysinfo.c @@ -0,0 +1,292 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2024 Linaro Limited + * Author: Raymond Mao raymond.mao@linaro.org + */ +#include <dm.h> +#include <smbios_plat.h> +#include <stdio.h> +#include <sysinfo.h> + +union ccsidr_el1 { + struct { + u64 linesize:3; + u64 associativity:10; + u64 numsets:15; + u64 unknown:4; + u64 reserved:32; + } no_ccidx; + struct { + u64 linesize:3; + u64 associativity:21; + u64 reserved1:8; + u64 numsets:24; + u64 reserved2:8; + } ccidx_aarch64; + struct { + u64 linesize:3; + u64 associativity:21; + u64 reserved:8; + u64 unallocated:32; + } ccidx_aarch32; + u64 data; +}; + +union midr_el1 { + struct { + u64 revision:4; + u64 partnum:12; + u64 architecture:4; + u64 variant:4; + u64 implementer:8; + u64 reserved:32; + } fields; + u64 data; +}; + +enum { + CACHE_NONE, + CACHE_INST_ONLY, + CACHE_DATA_ONLY, + CACHE_INST_WITH_DATA, + CACHE_UNIFIED, +}; + +enum { + CACHE_ASSOC_DIRECT_MAPPED = 1, + CACHE_ASSOC_2WAY = 2, + CACHE_ASSOC_4WAY = 4, + CACHE_ASSOC_8WAY = 8, + CACHE_ASSOC_16WAY = 16, + CACHE_ASSOC_12WAY = 12, + CACHE_ASSOC_24WAY = 24, + CACHE_ASSOC_32WAY = 32, + CACHE_ASSOC_48WAY = 48, + CACHE_ASSOC_64WAY = 64, + CACHE_ASSOC_20WAY = 20, +}; + +enum { + VENDOR_RESERVED = 0, + VENDOR_ARM = 0x41, + VENDOR_BROADCOM = 0x42, + VENDOR_CAVIUM = 0x43, + VENDOR_DEC = 0x44, + VENDOR_FUJITSU = 0x46, + VENDOR_INFINEON = 0x49, + VENDOR_FREESCALE = 0x4d, + VENDOR_NVIDIA = 0x4e, + VENDOR_AMCC = 0x50, + VENDOR_QUALCOMM = 0x51, + VENDOR_MARVELL = 0x56, + VENDOR_INTEL = 0x69, + VENDOR_AMPERE = 0xc0, +}; + +/* + * TODO: + * To support ARMv8.3, we need to read "CCIDX, bits [23:20]" from + * ID_AA64MMFR2_EL1 to get the format of CCSIDR_EL1: + * + * 0b0000 - 32-bit format implemented for all levels of the CCSIDR_EL1. + * 0b0001 - 64-bit format implemented for all levels of the CCSIDR_EL1. + * + * Here we assume to use CCSIDR_EL1 in no CCIDX layout: + * NumSets, bits [27:13]: (Number of sets in cache) - 1 + * Associativity, bits [12:3]: (Associativity of cache) - 1 + * LineSize, bits [2:0]: (Log2(Number of bytes in cache line)) - 4 + */ +int sysinfo_get_cache_info(u8 level, struct cache_info *cinfo) +{ + u64 clidr_el1; + u32 csselr_el1; + u32 num_sets; + union ccsidr_el1 creg; + int cache_type; + + sysinfo_cache_info_default(cinfo); + + /* Read CLIDR_EL1 */ + asm volatile("mrs %0, clidr_el1" : "=r" (clidr_el1)); + debug("CLIDR_EL1: 0x%llx\n", clidr_el1); + + cache_type = (clidr_el1 >> (3 * level)) & 0x7; + if (cache_type == CACHE_NONE) /* level does not exist */ + return -1; + + switch (cache_type) { + case CACHE_INST_ONLY: + cinfo->cache_type = SMBIOS_CACHE_SYSCACHE_TYPE_INST; + break; + case CACHE_DATA_ONLY: + cinfo->cache_type = SMBIOS_CACHE_SYSCACHE_TYPE_DATA; + break; + case CACHE_UNIFIED: + cinfo->cache_type = SMBIOS_CACHE_SYSCACHE_TYPE_UNIFIED; + break; + case CACHE_INST_WITH_DATA: + cinfo->cache_type = SMBIOS_CACHE_SYSCACHE_TYPE_OTHER; + break; + default: + cinfo->cache_type = SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN; + break; + } + + /* Select cache level */ + csselr_el1 = (level << 1); + asm volatile("msr csselr_el1, %0" : : "r" (csselr_el1)); + + /* Read CCSIDR_EL1 */ + asm volatile("mrs %0, ccsidr_el1" : "=r" (creg.data)); + debug("CCSIDR_EL1 (Level %d): 0x%llx\n", level + 1, creg.data); + + /* Extract cache size and associativity */ + cinfo->line_size = 1 << (creg.no_ccidx.linesize + 4); + + /* Map the associativity value */ + switch (creg.no_ccidx.associativity + 1) { + case CACHE_ASSOC_DIRECT_MAPPED: + cinfo->associativity = SMBIOS_CACHE_ASSOC_DMAPPED; + break; + case CACHE_ASSOC_2WAY: + cinfo->associativity = SMBIOS_CACHE_ASSOC_2WAY; + break; + case CACHE_ASSOC_4WAY: + cinfo->associativity = SMBIOS_CACHE_ASSOC_4WAY; + break; + case CACHE_ASSOC_8WAY: + cinfo->associativity = SMBIOS_CACHE_ASSOC_8WAY; + break; + case CACHE_ASSOC_16WAY: + cinfo->associativity = SMBIOS_CACHE_ASSOC_16WAY; + break; + case CACHE_ASSOC_12WAY: + cinfo->associativity = SMBIOS_CACHE_ASSOC_12WAY; + break; + case CACHE_ASSOC_24WAY: + cinfo->associativity = SMBIOS_CACHE_ASSOC_24WAY; + break; + case CACHE_ASSOC_32WAY: + cinfo->associativity = SMBIOS_CACHE_ASSOC_32WAY; + break; + case CACHE_ASSOC_48WAY: + cinfo->associativity = SMBIOS_CACHE_ASSOC_48WAY; + break; + case CACHE_ASSOC_64WAY: + cinfo->associativity = SMBIOS_CACHE_ASSOC_64WAY; + break; + case CACHE_ASSOC_20WAY: + cinfo->associativity = SMBIOS_CACHE_ASSOC_20WAY; + break; + default: + cinfo->associativity = SMBIOS_CACHE_ASSOC_UNKNOWN; + break; + } + + num_sets = creg.no_ccidx.numsets + 1; + /* Size in KB */ + cinfo->max_size = (cinfo->associativity * num_sets * cinfo->line_size) / + 1024; + + debug("L%d Cache:\n", level + 1); + debug("Number of bytes in cache line:%u\n", cinfo->line_size); + debug("Associativity of cache:%u\n", cinfo->associativity); + debug("Number of sets in cache:%u\n", num_sets); + debug("Cache size in KB:%u\n", cinfo->max_size); + + cinfo->inst_size = cinfo->max_size; + + /* + * Below fields with common values are placed under DT smbios node + * socket-design, config + * Other fields are typically specific to the implementation of the ARM + * processor by the silicon vendor: + * supp_sram_type, curr_sram_type, speed, err_corr_type + */ + + return 0; +} + +int sysinfo_get_processor_info(struct processor_info *pinfo) +{ + u64 mpidr, core_count; + union midr_el1 midr; + + /* Read the MIDR_EL1 register */ + asm volatile("mrs %0, MIDR_EL1" : "=r"(midr.data)); + /* Read the MPIDR_EL1 register */ + asm volatile("mrs %0, MPIDR_EL1" : "=r"(mpidr)); + + debug("MIDR: 0x%016llx\n", midr.data); + debug("MPIDR: 0x%016llx\n", mpidr); + debug("CPU Implementer: 0x%02x\n", midr.fields.implementer); + + switch (midr.fields.implementer) { + case VENDOR_ARM: + pinfo->manufacturer = "ARM Limited"; + break; + case VENDOR_BROADCOM: + pinfo->manufacturer = "Broadcom Corporation"; + break; + case VENDOR_CAVIUM: + pinfo->manufacturer = "Cavium Inc"; + break; + case VENDOR_DEC: + pinfo->manufacturer = "Digital Equipment Corporation"; + break; + case VENDOR_FUJITSU: + pinfo->manufacturer = "Fujitsu Ltd"; + break; + case VENDOR_INFINEON: + pinfo->manufacturer = "Infineon Technologies AG"; + break; + case VENDOR_FREESCALE: + pinfo->manufacturer = "Freescale Semiconductor Inc"; + break; + case VENDOR_NVIDIA: + pinfo->manufacturer = "NVIDIA Corporation"; + break; + case VENDOR_AMCC: + pinfo->manufacturer = + "Applied Micro Circuits Corporation"; + break; + case VENDOR_QUALCOMM: + pinfo->manufacturer = "Qualcomm Inc"; + break; + case VENDOR_MARVELL: + pinfo->manufacturer = "Marvell International Ltd"; + break; + case VENDOR_INTEL: + pinfo->manufacturer = "Intel Corporation"; + break; + case VENDOR_AMPERE: + pinfo->manufacturer = "Ampere Computing"; + break; + default: + pinfo->manufacturer = "Unknown"; + break; + } + debug("CPU part number: 0x%x\n", midr.fields.partnum); + debug("CPU revision: 0x%x\n", midr.fields.revision); + debug("CPU architecture: 0x%x\n", midr.fields.architecture); + debug("CPU variant: 0x%x\n", midr.fields.variant); + + /* Extract number of cores */ + core_count = (mpidr >> 0) & 0xFF; + pinfo->core_count = core_count + 1; + debug("CPU Core Count: %d\n", pinfo->core_count); + + pinfo->core_enabled = pinfo->core_count; + pinfo->characteristics = SMBIOS_PROCESSOR_64BIT | + SMBIOS_PROCESSOR_ARM64_SOCID; + if (pinfo->core_count > 1) + pinfo->characteristics |= SMBIOS_PROCESSOR_MULTICORE; + + /* + * Below fields with common values are placed under DT smbios node + * version, processor-type, processor-status, upgrade, family2, + * socket-design, serial, asset-tag, part-number + */ + + return 0; +}

Hi Raymond,
On Tue, 22 Oct 2024 at 22:07, Raymond Mao raymond.mao@linaro.org wrote:
Add sysinfo platform driver for all armv8 platforms to retrieve hardware information on processor and cache.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
Changes in v2
- Combine with #8(v1) patch.
- Remove the handling of the common strings and values.
arch/arm/cpu/armv8/Makefile | 2 + arch/arm/cpu/armv8/sysinfo.c | 292 +++++++++++++++++++++++++++++++++++ 2 files changed, 294 insertions(+) create mode 100644 arch/arm/cpu/armv8/sysinfo.c
Reviewed-by: Simon Glass sjg@chromium.org
I have to wonder who wants this information. Doesn't Linux know it already, based on the compatible string?
Regards, Simon

Hi Simon,
On Mon, 28 Oct 2024 at 13:04, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Tue, 22 Oct 2024 at 22:07, Raymond Mao raymond.mao@linaro.org wrote:
Add sysinfo platform driver for all armv8 platforms to retrieve hardware information on processor and cache.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
Changes in v2
- Combine with #8(v1) patch.
- Remove the handling of the common strings and values.
arch/arm/cpu/armv8/Makefile | 2 + arch/arm/cpu/armv8/sysinfo.c | 292 +++++++++++++++++++++++++++++++++++ 2 files changed, 294 insertions(+) create mode 100644 arch/arm/cpu/armv8/sysinfo.c
Reviewed-by: Simon Glass sjg@chromium.org
I have to wonder who wants this information. Doesn't Linux know it already, based on the compatible string?
Not all platforms have those compatible strings, so this patch provides
those register-based common values for all arm64 platforms. The idea is to read SMBIOS values following below sequence of priority: 1. sysinfo driver if it exists (for arch register-based values). 2. sysinfo-smbios subnode if it exists (for common strings or enum values). 3. search in the entire DTB (for those ones expected to exist in DTB like memory or slot type, which is WIP and not included in this patch set yet).
Regards, Raymond

Add common smbios information that can be used by all armv8 platforms and set it as default for qemu-arm64.
From now smbios library can load values from here for those fields
doesn't exist in the sysinfo driver.
To run this with QEMU arm64, please dump the generated DTB from QEMU first, merge it with the one we build and then re-run QEMU with the merged DTB. ``` qemu-system-arm -machine virt -machine dumpdtb=qemu.dtb cat <(dtc -I dtb qemu.dtb) <(dtc -I dtb ./dts/dt.dtb | \ grep -v /dts-v1/) | dtc - -o merged.dtb qemu-system-arm -machine virt -nographic -bios u-boot.bin \ -dtb merged.dtb ``` For details please take reference on dt_qemu.rst
Signed-off-by: Raymond Mao raymond.mao@linaro.org --- Changes in v2 - Initial patch.
arch/arm/dts/qemu-arm64.dts | 4 ++ arch/arm/dts/smbios_generic.dtsi | 82 ++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 arch/arm/dts/smbios_generic.dtsi
diff --git a/arch/arm/dts/qemu-arm64.dts b/arch/arm/dts/qemu-arm64.dts index 096b3910728..95fcf53ed74 100644 --- a/arch/arm/dts/qemu-arm64.dts +++ b/arch/arm/dts/qemu-arm64.dts @@ -7,5 +7,9 @@
/dts-v1/;
+#if defined(CONFIG_SYSINFO_SMBIOS) && !defined(QFW_SMBIOS) +#include "smbios_generic.dtsi" +#endif + / { }; diff --git a/arch/arm/dts/smbios_generic.dtsi b/arch/arm/dts/smbios_generic.dtsi new file mode 100644 index 00000000000..c9f07283403 --- /dev/null +++ b/arch/arm/dts/smbios_generic.dtsi @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Default SMBIOS information for Arm64 platforms + * + * Copyright (c) 2024 Linaro Limited + * Author: Raymond Mao raymond.mao@linaro.org + */ +#include <config.h> +#include <smbios_def.h> + +/ { + smbios { + compatible = "u-boot,sysinfo-smbios"; + + smbios { + system { + manufacturer = CONFIG_SYS_VENDOR; + product = CONFIG_SYS_BOARD; + version = "Not Specified"; + serial = "Not Specified"; + wakeup-type = <SMBIOS_WAKEUP_TYPE_UNKNOWN>; + sku = "Not Specified"; + family = "armv8"; + }; + + baseboard { + manufacturer = CONFIG_SYS_VENDOR; + product = CONFIG_SYS_BOARD; + version = "Not Specified"; + serial = "Not Specified"; + asset-tag = "Not Specified"; + chassis-location = "Not Specified"; + feature-flags = <SMBIOS_BOARD_FEAT_HOST_BOARD>; + board-type = <SMBIOS_BOARD_TYPE_MOTHERBOARD>; + }; + + chassis { + manufacturer = CONFIG_SYS_VENDOR; + version = "Not Specified"; + serial = "Not Specified"; + asset-tag = "Not Specified"; + chassis-type = <SMBIOS_ENCLOSURE_DESKTOP>; + bootup-state = <SMBIOS_STATE_SAFE>; + power-supply-state = <SMBIOS_STATE_SAFE>; + thermal-state = <SMBIOS_STATE_SAFE>; + security-status = <SMBIOS_SECURITY_NONE>; + oem-defined = <SMBIOS_ENCLOSURE_OEM_UND>; + height = <SMBIOS_ENCLOSURE_HEIGHT_UND>; + number-of-power-cords = <SMBIOS_POWCORD_NUM_UND>; + }; + + processor { + version = "Not Specified"; + processor-type = <SMBIOS_PROCESSOR_TYPE_CENTRAL>; + processor-status = <SMBIOS_PROCESSOR_STATUS_ENABLED>; + upgrade = <SMBIOS_PROCESSOR_UPGRADE_NONE>; + family = <SMBIOS_PROCESSOR_FAMILY_EXT>; + family2 = <SMBIOS_PROCESSOR_FAMILY_ARMV8>; + socket-design = "Not Specified"; + serial = "Not Specified"; + asset-tag = "Not Specified"; + part-number = "Not Specified"; + }; + + cache { + l1-cache { + socket-design = "Not Specified"; + config = <(SMBIOS_CACHE_LEVEL_1 | + SMBIOS_CACHE_ENABLED | + SMBIOS_CACHE_OP_WB)>; + }; + + l2-cache { + socket-design = "Not Specified"; + config = <(SMBIOS_CACHE_LEVEL_2 | + SMBIOS_CACHE_ENABLED | + SMBIOS_CACHE_OP_WB)>; + }; + }; + }; + }; +};

Hi Raymond,
On Tue, 22 Oct 2024 at 22:07, Raymond Mao raymond.mao@linaro.org wrote:
Add common smbios information that can be used by all armv8 platforms and set it as default for qemu-arm64. From now smbios library can load values from here for those fields doesn't exist in the sysinfo driver.
To run this with QEMU arm64, please dump the generated DTB from QEMU first, merge it with the one we build and then re-run QEMU with the merged DTB.
qemu-system-arm -machine virt -machine dumpdtb=qemu.dtb cat <(dtc -I dtb qemu.dtb) <(dtc -I dtb ./dts/dt.dtb | \ grep -v /dts-v1/) | dtc - -o merged.dtb qemu-system-arm -machine virt -nographic -bios u-boot.bin \ -dtb merged.dtb
and please talk to Peter about accepting my patch[1]
For details please take reference on dt_qemu.rst Signed-off-by: Raymond Mao <raymond.mao@linaro.org> --- Changes in v2 - Initial patch. arch/arm/dts/qemu-arm64.dts | 4 ++ arch/arm/dts/smbios_generic.dtsi | 82 ++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 arch/arm/dts/smbios_generic.dtsi diff --git a/arch/arm/dts/qemu-arm64.dts b/arch/arm/dts/qemu-arm64.dts index 096b3910728..95fcf53ed74 100644 --- a/arch/arm/dts/qemu-arm64.dts +++ b/arch/arm/dts/qemu-arm64.dts @@ -7,5 +7,9 @@ /dts-v1/; +#if defined(CONFIG_SYSINFO_SMBIOS) && !defined(QFW_SMBIOS) +#include "smbios_generic.dtsi" +#endif + / { }; diff --git a/arch/arm/dts/smbios_generic.dtsi
b/arch/arm/dts/smbios_generic.dtsi
new file mode 100644 index 00000000000..c9f07283403 --- /dev/null +++ b/arch/arm/dts/smbios_generic.dtsi @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Default SMBIOS information for Arm64 platforms
- Copyright (c) 2024 Linaro Limited
- Author: Raymond Mao raymond.mao@linaro.org
- */
+#include <config.h> +#include <smbios_def.h>
+/ {
smbios {
compatible = "u-boot,sysinfo-smbios";
smbios {
system {
manufacturer = CONFIG_SYS_VENDOR;
product = CONFIG_SYS_BOARD;
version = "Not Specified";
serial = "Not Specified";
Does it make sense to add these strings? Perhaps if the property is missing in the DT, it should be missing in the SMBIOS table? Is 'Not Specified' a special string in the SMBIO spec?
wakeup-type =
<SMBIOS_WAKEUP_TYPE_UNKNOWN>;
sku = "Not Specified";
family = "armv8";
};
baseboard {
manufacturer = CONFIG_SYS_VENDOR;
product = CONFIG_SYS_BOARD;
version = "Not Specified";
serial = "Not Specified";
asset-tag = "Not Specified";
chassis-location = "Not Specified";
feature-flags =
<SMBIOS_BOARD_FEAT_HOST_BOARD>;
board-type =
<SMBIOS_BOARD_TYPE_MOTHERBOARD>;
};
chassis {
manufacturer = CONFIG_SYS_VENDOR;
version = "Not Specified";
serial = "Not Specified";
asset-tag = "Not Specified";
chassis-type = <SMBIOS_ENCLOSURE_DESKTOP>;
bootup-state = <SMBIOS_STATE_SAFE>;
power-supply-state = <SMBIOS_STATE_SAFE>;
thermal-state = <SMBIOS_STATE_SAFE>;
security-status = <SMBIOS_SECURITY_NONE>;
oem-defined = <SMBIOS_ENCLOSURE_OEM_UND>;
height = <SMBIOS_ENCLOSURE_HEIGHT_UND>;
number-of-power-cords =
<SMBIOS_POWCORD_NUM_UND>;
};
processor {
version = "Not Specified";
processor-type =
<SMBIOS_PROCESSOR_TYPE_CENTRAL>;
processor-status =
<SMBIOS_PROCESSOR_STATUS_ENABLED>;
upgrade = <SMBIOS_PROCESSOR_UPGRADE_NONE>;
family = <SMBIOS_PROCESSOR_FAMILY_EXT>;
family2 = <SMBIOS_PROCESSOR_FAMILY_ARMV8>;
socket-design = "Not Specified";
serial = "Not Specified";
asset-tag = "Not Specified";
part-number = "Not Specified";
};
cache {
l1-cache {
socket-design = "Not Specified";
config = <(SMBIOS_CACHE_LEVEL_1 |
SMBIOS_CACHE_ENABLED |
SMBIOS_CACHE_OP_WB)>;
};
l2-cache {
socket-design = "Not Specified";
config = <(SMBIOS_CACHE_LEVEL_2 |
SMBIOS_CACHE_ENABLED |
SMBIOS_CACHE_OP_WB)>;
};
};
};
};
+};
2.25.1
Regards, Simon
[1] https://patchwork.kernel.org/project/qemu-devel/patch/20210926183410.256484-...

Hi Simon,
On Mon, 28 Oct 2024 at 13:05, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Tue, 22 Oct 2024 at 22:07, Raymond Mao raymond.mao@linaro.org wrote:
Add common smbios information that can be used by all armv8 platforms and set it as default for qemu-arm64. From now smbios library can load values from here for those fields doesn't exist in the sysinfo driver.
To run this with QEMU arm64, please dump the generated DTB from QEMU first, merge it with the one we build and then re-run QEMU with the merged DTB.
qemu-system-arm -machine virt -machine dumpdtb=qemu.dtb cat <(dtc -I dtb qemu.dtb) <(dtc -I dtb ./dts/dt.dtb | \ grep -v /dts-v1/) | dtc - -o merged.dtb qemu-system-arm -machine virt -nographic -bios u-boot.bin \ -dtb merged.dtb
and please talk to Peter about accepting my patch[1]
For details please take reference on dt_qemu.rst Signed-off-by: Raymond Mao <raymond.mao@linaro.org> --- Changes in v2 - Initial patch. arch/arm/dts/qemu-arm64.dts | 4 ++ arch/arm/dts/smbios_generic.dtsi | 82 ++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 arch/arm/dts/smbios_generic.dtsi diff --git a/arch/arm/dts/qemu-arm64.dts b/arch/arm/dts/qemu-arm64.dts index 096b3910728..95fcf53ed74 100644 --- a/arch/arm/dts/qemu-arm64.dts +++ b/arch/arm/dts/qemu-arm64.dts @@ -7,5 +7,9 @@ /dts-v1/; +#if defined(CONFIG_SYSINFO_SMBIOS) && !defined(QFW_SMBIOS) +#include "smbios_generic.dtsi" +#endif + / { }; diff --git a/arch/arm/dts/smbios_generic.dtsi
b/arch/arm/dts/smbios_generic.dtsi
new file mode 100644 index 00000000000..c9f07283403 --- /dev/null +++ b/arch/arm/dts/smbios_generic.dtsi @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Default SMBIOS information for Arm64 platforms
- Copyright (c) 2024 Linaro Limited
- Author: Raymond Mao raymond.mao@linaro.org
- */
+#include <config.h> +#include <smbios_def.h>
+/ {
smbios {
compatible = "u-boot,sysinfo-smbios";
smbios {
system {
manufacturer = CONFIG_SYS_VENDOR;
product = CONFIG_SYS_BOARD;
version = "Not Specified";
serial = "Not Specified";
Does it make sense to add these strings? Perhaps if the property is missing in the DT, it should be missing in the SMBIOS table? Is 'Not Specified' a special string in the SMBIO spec?
This is not defined in the spec and actually those strings can be anything. As currently this is for qemu_arm64 only and we don't have real vendor-defined values, "Not Specified" is used as a placeholder to show an example for other vendors if they want to add similar properties.
Regards, Raymond

On Mon, 28 Oct 2024 at 21:00, Raymond Mao raymond.mao@linaro.org wrote:
Hi Simon,
On Mon, 28 Oct 2024 at 13:05, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Tue, 22 Oct 2024 at 22:07, Raymond Mao raymond.mao@linaro.org wrote:
Add common smbios information that can be used by all armv8 platforms and set it as default for qemu-arm64. From now smbios library can load values from here for those fields doesn't exist in the sysinfo driver.
To run this with QEMU arm64, please dump the generated DTB from QEMU first, merge it with the one we build and then re-run QEMU with the merged DTB.
qemu-system-arm -machine virt -machine dumpdtb=qemu.dtb cat <(dtc -I dtb qemu.dtb) <(dtc -I dtb ./dts/dt.dtb | \ grep -v /dts-v1/) | dtc - -o merged.dtb qemu-system-arm -machine virt -nographic -bios u-boot.bin \ -dtb merged.dtb
and please talk to Peter about accepting my patch[1]
For details please take reference on dt_qemu.rst Signed-off-by: Raymond Mao <raymond.mao@linaro.org> --- Changes in v2 - Initial patch. arch/arm/dts/qemu-arm64.dts | 4 ++ arch/arm/dts/smbios_generic.dtsi | 82 ++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 arch/arm/dts/smbios_generic.dtsi diff --git a/arch/arm/dts/qemu-arm64.dts b/arch/arm/dts/qemu-arm64.dts index 096b3910728..95fcf53ed74 100644 --- a/arch/arm/dts/qemu-arm64.dts +++ b/arch/arm/dts/qemu-arm64.dts @@ -7,5 +7,9 @@ /dts-v1/; +#if defined(CONFIG_SYSINFO_SMBIOS) && !defined(QFW_SMBIOS) +#include "smbios_generic.dtsi" +#endif + / { }; diff --git a/arch/arm/dts/smbios_generic.dtsi b/arch/arm/dts/smbios_generic.dtsi new file mode 100644 index 00000000000..c9f07283403 --- /dev/null +++ b/arch/arm/dts/smbios_generic.dtsi @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Default SMBIOS information for Arm64 platforms + * + * Copyright (c) 2024 Linaro Limited + * Author: Raymond Mao <raymond.mao@linaro.org> + */ +#include <config.h> +#include <smbios_def.h> + +/ { + smbios { + compatible = "u-boot,sysinfo-smbios"; + + smbios { + system { + manufacturer = CONFIG_SYS_VENDOR; + product = CONFIG_SYS_BOARD; + version = "Not Specified"; + serial = "Not Specified";
Does it make sense to add these strings? Perhaps if the property is missing in the DT, it should be missing in the SMBIOS table? Is 'Not Specified' a special string in the SMBIO spec?
This is not defined in the spec and actually those strings can be anything. As currently this is for qemu_arm64 only and we don't have real vendor-defined values, "Not Specified" is used as a placeholder to show an example for other vendors if they want to add similar properties.
OK I see.
Reviewed-by: Simon Glass sjg@chromium.org

Am 29. Oktober 2024 16:45:44 MEZ schrieb Simon Glass sjg@chromium.org:
On Mon, 28 Oct 2024 at 21:00, Raymond Mao raymond.mao@linaro.org wrote:
Hi Simon,
On Mon, 28 Oct 2024 at 13:05, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Tue, 22 Oct 2024 at 22:07, Raymond Mao raymond.mao@linaro.org wrote:
Add common smbios information that can be used by all armv8 platforms and set it as default for qemu-arm64. From now smbios library can load values from here for those fields doesn't exist in the sysinfo driver.
To run this with QEMU arm64, please dump the generated DTB from QEMU first, merge it with the one we build and then re-run QEMU with the merged DTB.
qemu-system-arm -machine virt -machine dumpdtb=qemu.dtb cat <(dtc -I dtb qemu.dtb) <(dtc -I dtb ./dts/dt.dtb | \ grep -v /dts-v1/) | dtc - -o merged.dtb qemu-system-arm -machine virt -nographic -bios u-boot.bin \ -dtb merged.dtb
and please talk to Peter about accepting my patch[1]
For details please take reference on dt_qemu.rst Signed-off-by: Raymond Mao <raymond.mao@linaro.org> --- Changes in v2 - Initial patch. arch/arm/dts/qemu-arm64.dts | 4 ++ arch/arm/dts/smbios_generic.dtsi | 82 ++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 arch/arm/dts/smbios_generic.dtsi diff --git a/arch/arm/dts/qemu-arm64.dts b/arch/arm/dts/qemu-arm64.dts index 096b3910728..95fcf53ed74 100644 --- a/arch/arm/dts/qemu-arm64.dts +++ b/arch/arm/dts/qemu-arm64.dts @@ -7,5 +7,9 @@ /dts-v1/; +#if defined(CONFIG_SYSINFO_SMBIOS) && !defined(QFW_SMBIOS) +#include "smbios_generic.dtsi" +#endif + / { }; diff --git a/arch/arm/dts/smbios_generic.dtsi b/arch/arm/dts/smbios_generic.dtsi new file mode 100644 index 00000000000..c9f07283403 --- /dev/null +++ b/arch/arm/dts/smbios_generic.dtsi @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Default SMBIOS information for Arm64 platforms + * + * Copyright (c) 2024 Linaro Limited + * Author: Raymond Mao <raymond.mao@linaro.org> + */ +#include <config.h> +#include <smbios_def.h> + +/ { + smbios { + compatible = "u-boot,sysinfo-smbios"; + + smbios { + system { + manufacturer = CONFIG_SYS_VENDOR; + product = CONFIG_SYS_BOARD; + version = "Not Specified"; + serial = "Not Specified";
Does it make sense to add these strings? Perhaps if the property is missing in the DT, it should be missing in the SMBIOS table? Is 'Not Specified' a special string in the SMBIO spec?
The correct way to handle unknown values is not to provide any string at all. In the SMBIOS table a string ID number of zero indicates that the value is unknown and dmidecode will show this correctly.
This is described in the SMBIOS spec.
Please, adjust the patch accordingly.
Best regards
Heinrich
This is not defined in the spec and actually those strings can be anything. As currently this is for qemu_arm64 only and we don't have real vendor-defined values, "Not Specified" is used as a placeholder to show an example for other vendors if they want to add similar properties.
OK I see.
Reviewed-by: Simon Glass sjg@chromium.org

Am 29. Oktober 2024 16:45:44 MEZ schrieb Simon Glass sjg@chromium.org:
On Mon, 28 Oct 2024 at 21:00, Raymond Mao raymond.mao@linaro.org wrote:
Hi Simon,
On Mon, 28 Oct 2024 at 13:05, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Tue, 22 Oct 2024 at 22:07, Raymond Mao raymond.mao@linaro.org wrote:
Add common smbios information that can be used by all armv8 platforms and set it as default for qemu-arm64. From now smbios library can load values from here for those fields doesn't exist in the sysinfo driver.
To run this with QEMU arm64, please dump the generated DTB from QEMU first, merge it with the one we build and then re-run QEMU with the merged DTB.
qemu-system-arm -machine virt -machine dumpdtb=qemu.dtb cat <(dtc -I dtb qemu.dtb) <(dtc -I dtb ./dts/dt.dtb | \ grep -v /dts-v1/) | dtc - -o merged.dtb qemu-system-arm -machine virt -nographic -bios u-boot.bin \ -dtb merged.dtb
and please talk to Peter about accepting my patch[1]
For details please take reference on dt_qemu.rst Signed-off-by: Raymond Mao <raymond.mao@linaro.org> --- Changes in v2 - Initial patch. arch/arm/dts/qemu-arm64.dts | 4 ++ arch/arm/dts/smbios_generic.dtsi | 82 ++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 arch/arm/dts/smbios_generic.dtsi diff --git a/arch/arm/dts/qemu-arm64.dts b/arch/arm/dts/qemu-arm64.dts index 096b3910728..95fcf53ed74 100644 --- a/arch/arm/dts/qemu-arm64.dts +++ b/arch/arm/dts/qemu-arm64.dts @@ -7,5 +7,9 @@ /dts-v1/; +#if defined(CONFIG_SYSINFO_SMBIOS) && !defined(QFW_SMBIOS) +#include "smbios_generic.dtsi" +#endif + / { }; diff --git a/arch/arm/dts/smbios_generic.dtsi b/arch/arm/dts/smbios_generic.dtsi new file mode 100644 index 00000000000..c9f07283403 --- /dev/null +++ b/arch/arm/dts/smbios_generic.dtsi @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Default SMBIOS information for Arm64 platforms + * + * Copyright (c) 2024 Linaro Limited + * Author: Raymond Mao <raymond.mao@linaro.org> + */ +#include <config.h> +#include <smbios_def.h> + +/ { + smbios { + compatible = "u-boot,sysinfo-smbios"; + + smbios { + system { + manufacturer = CONFIG_SYS_VENDOR; + product = CONFIG_SYS_BOARD; + version = "Not Specified"; + serial = "Not Specified";
Does it make sense to add these strings? Perhaps if the property is missing in the DT, it should be missing in the SMBIOS table? Is 'Not Specified' a special string in the SMBIO spec?
The spec says:
"If a string field references no string, a null (0) is placed in that string field."
Please, remove the 'Not specified' values from the patch and do not provide any property value in the device-tree instead.
Best regards
Heinrich
This is not defined in the spec and actually those strings can be anything. As currently this is for qemu_arm64 only and we don't have real vendor-defined values, "Not Specified" is used as a placeholder to show an example for other vendors if they want to add similar properties.
OK I see.
Reviewed-by: Simon Glass sjg@chromium.org

Hi Heinrich,
On Fri, 1 Nov 2024 at 02:16, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 29. Oktober 2024 16:45:44 MEZ schrieb Simon Glass sjg@chromium.org:
On Mon, 28 Oct 2024 at 21:00, Raymond Mao raymond.mao@linaro.org wrote:
Hi Simon,
On Mon, 28 Oct 2024 at 13:05, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Tue, 22 Oct 2024 at 22:07, Raymond Mao raymond.mao@linaro.org
wrote:
Add common smbios information that can be used by all armv8 platforms and set it as default for qemu-arm64. From now smbios library can load values from here for those fields doesn't exist in the sysinfo driver.
To run this with QEMU arm64, please dump the generated DTB from QEMU first, merge it with the one we build and then re-run QEMU with the merged DTB.
qemu-system-arm -machine virt -machine dumpdtb=qemu.dtb cat <(dtc -I dtb qemu.dtb) <(dtc -I dtb ./dts/dt.dtb | \ grep -v /dts-v1/) | dtc - -o merged.dtb qemu-system-arm -machine virt -nographic -bios u-boot.bin \ -dtb merged.dtb
and please talk to Peter about accepting my patch[1]
For details please take reference on dt_qemu.rst Signed-off-by: Raymond Mao <raymond.mao@linaro.org> --- Changes in v2 - Initial patch. arch/arm/dts/qemu-arm64.dts | 4 ++ arch/arm/dts/smbios_generic.dtsi | 82
++++++++++++++++++++++++++++++++
2 files changed, 86 insertions(+) create mode 100644 arch/arm/dts/smbios_generic.dtsi
diff --git a/arch/arm/dts/qemu-arm64.dts
b/arch/arm/dts/qemu-arm64.dts
index 096b3910728..95fcf53ed74 100644 --- a/arch/arm/dts/qemu-arm64.dts +++ b/arch/arm/dts/qemu-arm64.dts @@ -7,5 +7,9 @@
/dts-v1/;
+#if defined(CONFIG_SYSINFO_SMBIOS) && !defined(QFW_SMBIOS) +#include "smbios_generic.dtsi" +#endif
/ { }; diff --git a/arch/arm/dts/smbios_generic.dtsi
b/arch/arm/dts/smbios_generic.dtsi
new file mode 100644 index 00000000000..c9f07283403 --- /dev/null +++ b/arch/arm/dts/smbios_generic.dtsi @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Default SMBIOS information for Arm64 platforms
- Copyright (c) 2024 Linaro Limited
- Author: Raymond Mao raymond.mao@linaro.org
- */
+#include <config.h> +#include <smbios_def.h>
+/ {
smbios {
compatible = "u-boot,sysinfo-smbios";
smbios {
system {
manufacturer = CONFIG_SYS_VENDOR;
product = CONFIG_SYS_BOARD;
version = "Not Specified";
serial = "Not Specified";
Does it make sense to add these strings? Perhaps if the property is
missing in the DT, it should be missing in the SMBIOS table? Is 'Not Specified' a special string in the SMBIO spec?
The spec says:
"If a string field references no string, a null (0) is placed in that string field."
Please, remove the 'Not specified' values from the patch and do not provide any property value in the device-tree instead.
OK, I will remove all 'Not specified' in the next version.
Regards, Raymond

Update the cmd according to the changes of the smbios library: 1. Refactor smbios cmd print functions to match the content defined by the specification. 2. Add new print functions for Type 0, 3, 4 and 7. 3. Update the expected pytest result to align with the smbios library changes.
Signed-off-by: Raymond Mao raymond.mao@linaro.org --- Changes in v2 - Initial patch. Move all changes related to cmd/smbios into this patch. - Combine with #9(v1) patch.
cmd/smbios.c | 342 ++++++++++++++++++++++++++++++++--- include/smbios.h | 5 + test/py/tests/test_smbios.py | 2 +- 3 files changed, 319 insertions(+), 30 deletions(-)
diff --git a/cmd/smbios.c b/cmd/smbios.c index 2122ac04e55..9839f6f6690 100644 --- a/cmd/smbios.c +++ b/cmd/smbios.c @@ -14,16 +14,109 @@
DECLARE_GLOBAL_DATA_PTR;
-static const char * const wakeup_type_strings[] = { - "Reserved", /* 0x00 */ - "Other", /* 0x01 */ - "Unknown", /* 0x02 */ - "APM Timer", /* 0x03 */ - "Modem Ring", /* 0x04 */ - "Lan Remote", /* 0x05 */ - "Power Switch", /* 0x06 */ - "PCI PME#", /* 0x07 */ - "AC Power Restored", /* 0x08 */ +static const struct str_lookup_table wakeup_type_strings[] = { + { SMBIOS_WAKEUP_TYPE_RESERVED, "Reserved" }, + { SMBIOS_WAKEUP_TYPE_OTHER, "Other" }, + { SMBIOS_WAKEUP_TYPE_UNKNOWN, "Unknown" }, + { SMBIOS_WAKEUP_TYPE_APM_TIMER, "APM Timer" }, + { SMBIOS_WAKEUP_TYPE_MODEM_RING, "Modem Ring" }, + { SMBIOS_WAKEUP_TYPE_LAN_REMOTE, "Lan Remote" }, + { SMBIOS_WAKEUP_TYPE_POWER_SWITCH, "Power Switch" }, + { SMBIOS_WAKEUP_TYPE_PCI_PME, "PCI PME#" }, + { SMBIOS_WAKEUP_TYPE_AC_POWER_RESTORED, "AC Power Restored" }, +}; + +static const struct str_lookup_table boardtype_strings[] = { + { SMBIOS_BOARD_TYPE_UNKNOWN, "Unknown" }, + { SMBIOS_BOARD_TYPE_OTHER, "Other" }, + { SMBIOS_BOARD_TYPE_SERVER_BLADE, "Server Blade" }, + { SMBIOS_BOARD_TYPE_CON_SWITCH, "Connectivity Switch" }, + { SMBIOS_BOARD_TYPE_SM_MODULE, "System Management Module" }, + { SMBIOS_BOARD_TYPE_PROCESSOR_MODULE, "Processor Module" }, + { SMBIOS_BOARD_TYPE_IO_MODULE, "I/O Module" }, + { SMBIOS_BOARD_TYPE_MEM_MODULE, "Memory Module" }, + { SMBIOS_BOARD_TYPE_DAUGHTER_BOARD, "Daughter board" }, + { SMBIOS_BOARD_TYPE_MOTHERBOARD, "Motherboard" }, + { SMBIOS_BOARD_TYPE_PROC_MEM_MODULE, "Processor/Memory Module" }, + { SMBIOS_BOARD_TYPE_PROC_IO_MODULE, "Processor/IO Module" }, + { SMBIOS_BOARD_TYPE_INTERCON, "Interconnect board" }, +}; + +static const struct str_lookup_table chassis_state_strings[] = { + { SMBIOS_STATE_OTHER, "Other" }, + { SMBIOS_STATE_UNKNOWN, "Unknown" }, + { SMBIOS_STATE_SAFE, "Safe" }, + { SMBIOS_STATE_WARNING, "Warning" }, + { SMBIOS_STATE_CRITICAL, "Critical" }, + { SMBIOS_STATE_NONRECOVERABLE, "Non-recoverable" }, +}; + +static const struct str_lookup_table chassis_security_strings[] = { + { SMBIOS_SECURITY_OTHER, "Other" }, + { SMBIOS_SECURITY_UNKNOWN, "Unknown" }, + { SMBIOS_SECURITY_NONE, "None" }, + { SMBIOS_SECURITY_EXTINT_LOCK, "External interface locked out" }, + { SMBIOS_SECURITY_EXTINT_EN, "External interface enabled" }, +}; + +static const struct str_lookup_table processor_type_strings[] = { + { SMBIOS_PROCESSOR_TYPE_OTHER, "Other" }, + { SMBIOS_PROCESSOR_TYPE_UNKNOWN, "Unknown" }, + { SMBIOS_PROCESSOR_TYPE_CENTRAL, "Central Processor" }, + { SMBIOS_PROCESSOR_TYPE_MATH, "Math Processor" }, + { SMBIOS_PROCESSOR_TYPE_DSP, "DSP Processor" }, + { SMBIOS_PROCESSOR_TYPE_VIDEO, "Video Processor" }, +}; + +static const struct str_lookup_table processor_family_strings[] = { + { SMBIOS_PROCESSOR_FAMILY_OTHER, "Other" }, + { SMBIOS_PROCESSOR_FAMILY_UNKNOWN, "Unknown" }, + { SMBIOS_PROCESSOR_FAMILY_RSVD, "Reserved" }, + { SMBIOS_PROCESSOR_FAMILY_ARMV7, "ARMv7" }, + { SMBIOS_PROCESSOR_FAMILY_ARMV8, "ARMv8" }, + { SMBIOS_PROCESSOR_FAMILY_RV32, "RISC-V RV32" }, + { SMBIOS_PROCESSOR_FAMILY_RV64, "RISC-V RV64" }, +}; + +static const struct str_lookup_table processor_upgrade_strings[] = { + { SMBIOS_PROCESSOR_UPGRADE_OTHER, "Other" }, + { SMBIOS_PROCESSOR_UPGRADE_UNKNOWN, "Unknown" }, + { SMBIOS_PROCESSOR_UPGRADE_NONE, "None" }, +}; + +static const struct str_lookup_table err_corr_type_strings[] = { + { SMBIOS_CACHE_ERRCORR_OTHER, "Other" }, + { SMBIOS_CACHE_ERRCORR_UNKNOWN, "Unknown" }, + { SMBIOS_CACHE_ERRCORR_NONE, "None" }, + { SMBIOS_CACHE_ERRCORR_PARITY, "Parity" }, + { SMBIOS_CACHE_ERRCORR_SBITECC, "Single-bit ECC" }, + { SMBIOS_CACHE_ERRCORR_MBITECC, "Multi-bit ECC" }, +}; + +static const struct str_lookup_table sys_cache_type_strings[] = { + { SMBIOS_CACHE_SYSCACHE_TYPE_OTHER, "Other" }, + { SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN, "Unknown" }, + { SMBIOS_CACHE_SYSCACHE_TYPE_INST, "Instruction" }, + { SMBIOS_CACHE_SYSCACHE_TYPE_DATA, "Data" }, + { SMBIOS_CACHE_SYSCACHE_TYPE_UNIFIED, "Unified" }, +}; + +static const struct str_lookup_table associativity_strings[] = { + { SMBIOS_CACHE_ASSOC_OTHER, "Other" }, + { SMBIOS_CACHE_ASSOC_UNKNOWN, "Unknown" }, + { SMBIOS_CACHE_ASSOC_DMAPPED, "Direct Mapped" }, + { SMBIOS_CACHE_ASSOC_2WAY, "2-way Set-Associative" }, + { SMBIOS_CACHE_ASSOC_4WAY, "4-way Set-Associative" }, + { SMBIOS_CACHE_ASSOC_FULLY, "Fully Associative" }, + { SMBIOS_CACHE_ASSOC_8WAY, "8-way Set-Associative" }, + { SMBIOS_CACHE_ASSOC_16WAY, "16-way Set-Associative" }, + { SMBIOS_CACHE_ASSOC_12WAY, "12-way Set-Associative" }, + { SMBIOS_CACHE_ASSOC_24WAY, "24-way Set-Associative" }, + { SMBIOS_CACHE_ASSOC_32WAY, "32-way Set-Associative" }, + { SMBIOS_CACHE_ASSOC_48WAY, "48-way Set-Associative" }, + { SMBIOS_CACHE_ASSOC_64WAY, "64-way Set-Associative" }, + { SMBIOS_CACHE_ASSOC_20WAY, "20-way Set-Associative" }, + };
/** @@ -79,17 +172,53 @@ static void smbios_print_generic(struct smbios_header *table) } }
-void smbios_print_str(const char *label, void *table, u8 index) +static void smbios_print_str(const char *label, void *table, u8 index) { printf("\t%s: %s\n", label, smbios_get_string(table, index)); }
-const char *smbios_wakeup_type_str(u8 wakeup_type) +static void smbios_print_lookup_str(const struct str_lookup_table *table, + u16 index, u16 array_size, + const char *prefix) +{ + int i; + const char *str = NULL; + + for (i = 0; i < array_size; i++) { + if ((table + i)->idx == index) + str = (table + i)->str; + } + + if (str) + printf("\t%s: %s\n", prefix, str); + else + printf("\t%s: [%04x]\n", prefix, index); +} + +static void smbios_print_type0(struct smbios_type0 *table) { - if (wakeup_type >= ARRAY_SIZE(wakeup_type_strings)) - /* Values over 0x08 are reserved. */ - wakeup_type = 0; - return wakeup_type_strings[wakeup_type]; + printf("BIOS Information\n"); + smbios_print_str("Vendor", table, table->vendor); + smbios_print_str("BIOS Version", table, table->bios_ver); + /* Keep table->bios_start_segment as 0 for UEFI-based systems */ + smbios_print_str("BIOS Release Date", table, table->bios_release_date); + printf("\tBIOS ROM Size: 0x%02x\n", table->bios_rom_size); + printf("\tBIOS Characteristics: 0x%016llx\n", + table->bios_characteristics); + printf("\tBIOS Characteristics Extension Byte 1: 0x%02x\n", + table->bios_characteristics_ext1); + printf("\tBIOS Characteristics Extension Byte 2: 0x%02x\n", + table->bios_characteristics_ext2); + printf("\tSystem BIOS Major Release: 0x%02x\n", + table->bios_major_release); + printf("\tSystem BIOS Minor Release: 0x%02x\n", + table->bios_minor_release); + printf("\tEmbedded Controller Firmware Major Release: 0x%02x\n", + table->ec_major_release); + printf("\tEmbedded Controller Firmware Minor Release: 0x%02x\n", + table->ec_minor_release); + printf("\tExtended BIOS ROM Size: 0x%04x\n", + table->extended_bios_rom_size); }
static void smbios_print_type1(struct smbios_type1 *table) @@ -101,8 +230,10 @@ static void smbios_print_type1(struct smbios_type1 *table) smbios_print_str("Serial Number", table, table->serial_number); if (table->hdr.length >= SMBIOS_TYPE1_LENGTH_V21) { printf("\tUUID: %pUl\n", table->uuid); - printf("\tWake-up Type: %s\n", - smbios_wakeup_type_str(table->wakeup_type)); + smbios_print_lookup_str(wakeup_type_strings, + table->wakeup_type, + ARRAY_SIZE(wakeup_type_strings), + "Wake-up Type"); } if (table->hdr.length >= SMBIOS_TYPE1_LENGTH_V24) { smbios_print_str("SKU Number", table, table->sku_number); @@ -112,25 +243,166 @@ static void smbios_print_type1(struct smbios_type1 *table)
static void smbios_print_type2(struct smbios_type2 *table) { - u16 *handle; + int i; + u8 *addr = (u8 *)table + offsetof(struct smbios_type2, eos);
- printf("Base Board Information\n"); + printf("Baseboard Information\n"); smbios_print_str("Manufacturer", table, table->manufacturer); smbios_print_str("Product Name", table, table->product_name); smbios_print_str("Version", table, table->version); smbios_print_str("Serial Number", table, table->serial_number); smbios_print_str("Asset Tag", table, table->asset_tag_number); - printf("\tFeature Flags: 0x%04x\n", table->feature_flags); + printf("\tFeature Flags: 0x%02x\n", table->feature_flags); smbios_print_str("Chassis Location", table, table->chassis_location); printf("\tChassis Handle: 0x%04x\n", table->chassis_handle); - smbios_print_str("Board Type", table, table->board_type); - printf("\tContained Object Handles: "); - handle = (void *)table->eos; - for (int i = 0; i < table->number_contained_objects; ++i) - printf("0x%04x ", handle[i]); + smbios_print_lookup_str(boardtype_strings, + table->board_type, + ARRAY_SIZE(boardtype_strings), + "Board Type"); + printf("\tNumber of Contained Object Handles: 0x%02x\n", + table->number_contained_objects); + if (!table->number_contained_objects) + return; + + printf("\tContained Object Handles:\n"); + for (i = 0; i < table->number_contained_objects; i++) { + printf("\t\tObject[%03d]:\n", i); + if (CONFIG_IS_ENABLED(HEXDUMP)) + print_hex_dump("\t\t", DUMP_PREFIX_OFFSET, 16, 1, addr, + sizeof(u16), false); + addr += sizeof(u16); + } printf("\n"); }
+static void smbios_print_type3(struct smbios_type3 *table) +{ + int i; + u8 *addr = (u8 *)table + offsetof(struct smbios_type3, sku_number); + + printf("Baseboard Information\n"); + smbios_print_str("Manufacturer", table, table->manufacturer); + printf("\tType: 0x%02x\n", table->chassis_type); + smbios_print_str("Version", table, table->version); + smbios_print_str("Serial Number", table, table->serial_number); + smbios_print_str("Asset Tag", table, table->asset_tag_number); + smbios_print_lookup_str(chassis_state_strings, + table->bootup_state, + ARRAY_SIZE(chassis_state_strings), + "Boot-up State"); + smbios_print_lookup_str(chassis_state_strings, + table->power_supply_state, + ARRAY_SIZE(chassis_state_strings), + "Power Supply State"); + smbios_print_lookup_str(chassis_state_strings, + table->thermal_state, + ARRAY_SIZE(chassis_state_strings), + "Thermal State"); + smbios_print_lookup_str(chassis_security_strings, + table->security_status, + ARRAY_SIZE(chassis_security_strings), + "Security Status"); + printf("\tOEM-defined: 0x%08x\n", table->oem_defined); + printf("\tHeight: 0x%02x\n", table->height); + printf("\tNumber of Power Cords: 0x%02x\n", + table->number_of_power_cords); + printf("\tContained Element Count: 0x%02x\n", table->element_count); + printf("\tContained Element Record Length: 0x%02x\n", + table->element_record_length); + if (table->element_count) { + printf("\tContained Elements:\n"); + for (i = 0; i < table->element_count; i++) { + printf("\t\tElement[%03d]:\n", i); + if (CONFIG_IS_ENABLED(HEXDUMP)) + print_hex_dump("\t\t", DUMP_PREFIX_OFFSET, 16, + 1, addr, + table->element_record_length, + false); + printf("\t\tContained Element Type: 0x%02x\n", *addr); + printf("\t\tContained Element Minimum: 0x%02x\n", + *(addr + 1)); + printf("\t\tContained Element Maximum: 0x%02x\n", + *(addr + 2)); + addr += table->element_record_length; + } + } + smbios_print_str("SKU Number", table, *addr); +} + +static void smbios_print_type4(struct smbios_type4 *table) +{ + printf("Processor Information:\n"); + smbios_print_str("Socket Designation", table, table->socket_design); + smbios_print_lookup_str(processor_type_strings, + table->processor_type, + ARRAY_SIZE(processor_type_strings), + "Processor Type"); + smbios_print_lookup_str(processor_family_strings, + table->processor_family, + ARRAY_SIZE(processor_family_strings), + "Processor Family"); + smbios_print_str("Processor Manufacturer", table, + table->processor_manufacturer); + printf("\tProcessor ID word 0: 0x%08x\n", table->processor_id[0]); + printf("\tProcessor ID word 1: 0x%08x\n", table->processor_id[1]); + smbios_print_str("Processor Version", table, table->processor_version); + printf("\tVoltage: 0x%02x\n", table->voltage); + printf("\tExternal Clock: 0x%04x\n", table->external_clock); + printf("\tMax Speed: 0x%04x\n", table->max_speed); + printf("\tCurrent Speed: 0x%04x\n", table->current_speed); + printf("\tStatus: 0x%02x\n", table->status); + smbios_print_lookup_str(processor_upgrade_strings, + table->processor_upgrade, + ARRAY_SIZE(processor_upgrade_strings), + "Processor Upgrade"); + printf("\tL1 Cache Handle: 0x%04x\n", table->l1_cache_handle); + printf("\tL2 Cache Handle: 0x%04x\n", table->l2_cache_handle); + printf("\tL3 Cache Handle: 0x%04x\n", table->l3_cache_handle); + smbios_print_str("Serial Number", table, table->serial_number); + smbios_print_str("Asset Tag", table, table->asset_tag); + smbios_print_str("Part Number", table, table->part_number); + printf("\tCore Count: 0x%02x\n", table->core_count); + printf("\tCore Enabled: 0x%02x\n", table->core_enabled); + printf("\tThread Count: 0x%02x\n", table->thread_count); + printf("\tProcessor Characteristics: 0x%04x\n", + table->processor_characteristics); + smbios_print_lookup_str(processor_family_strings, + table->processor_family2, + ARRAY_SIZE(processor_family_strings), + "Processor Family 2"); + printf("\tCore Count 2: 0x%04x\n", table->core_count2); + printf("\tCore Enabled 2: 0x%04x\n", table->core_enabled2); + printf("\tThread Count 2: 0x%04x\n", table->thread_count2); + printf("\tThread Enabled: 0x%04x\n", table->thread_enabled); +} + +static void smbios_print_type7(struct smbios_type7 *table) +{ + printf("Cache Information:\n"); + smbios_print_str("Socket Designation", table, + table->socket_design); + printf("\tCache Configuration: 0x%04x\n", table->config.data); + printf("\tMaximum Cache Size: 0x%04x\n", table->max_size.data); + printf("\tInstalled Size: 0x%04x\n", table->inst_size.data); + printf("\tSupported SRAM Type: 0x%04x\n", table->supp_sram_type.data); + printf("\tCurrent SRAM Type: 0x%04x\n", table->curr_sram_type.data); + printf("\tCache Speed: 0x%02x\n", table->speed); + smbios_print_lookup_str(err_corr_type_strings, + table->err_corr_type, + ARRAY_SIZE(err_corr_type_strings), + "Error Correction Type"); + smbios_print_lookup_str(sys_cache_type_strings, + table->sys_cache_type, + ARRAY_SIZE(sys_cache_type_strings), + "System Cache Type"); + smbios_print_lookup_str(associativity_strings, + table->associativity, + ARRAY_SIZE(associativity_strings), + "Associativity"); + printf("\tMaximum Cache Size 2: 0x%08x\n", table->max_size2.data); + printf("\tInstalled Cache Size 2: 0x%08x\n", table->inst_size2.data); +} + static void smbios_print_type127(struct smbios_type127 *table) { printf("End Of Table\n"); @@ -192,13 +464,25 @@ static int do_smbios(struct cmd_tbl *cmdtp, int flag, int argc, pos->handle, pos->type, pos->length, (unsigned long long)map_to_sysmem(pos)); switch (pos->type) { - case 1: + case SMBIOS_BIOS_INFORMATION: + smbios_print_type0((struct smbios_type0 *)pos); + break; + case SMBIOS_SYSTEM_INFORMATION: smbios_print_type1((struct smbios_type1 *)pos); break; - case 2: + case SMBIOS_BOARD_INFORMATION: smbios_print_type2((struct smbios_type2 *)pos); break; - case 127: + case SMBIOS_SYSTEM_ENCLOSURE: + smbios_print_type3((struct smbios_type3 *)pos); + break; + case SMBIOS_PROCESSOR_INFORMATION: + smbios_print_type4((struct smbios_type4 *)pos); + break; + case SMBIOS_CACHE_INFORMATION: + smbios_print_type7((struct smbios_type7 *)pos); + break; + case SMBIOS_END_OF_TABLE: smbios_print_type127((struct smbios_type127 *)pos); break; default: diff --git a/include/smbios.h b/include/smbios.h index 18f568f9b0d..b5fed57aba2 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -38,6 +38,11 @@ enum { #define SMBIOS_INTERMEDIATE_OFFSET 16 #define SMBIOS_STRUCT_EOS_BYTES 2
+struct str_lookup_table { + u16 idx; + const char *str; +}; + struct __packed smbios_entry { u8 anchor[4]; u8 checksum; diff --git a/test/py/tests/test_smbios.py b/test/py/tests/test_smbios.py index 82b0b689830..ffa4ea795ec 100644 --- a/test/py/tests/test_smbios.py +++ b/test/py/tests/test_smbios.py @@ -32,7 +32,7 @@ def test_cmd_smbios_sandbox(u_boot_console): """Run the smbios command on the sandbox""" output = u_boot_console.run_command('smbios') assert 'DMI type 0,' in output - assert 'String 1: U-Boot' in output + assert 'Vendor: U-Boot' in output assert 'DMI type 1,' in output assert 'Manufacturer: sandbox' in output assert 'DMI type 2,' in output

On Tue, 22 Oct 2024 at 22:07, Raymond Mao raymond.mao@linaro.org wrote:
Update the cmd according to the changes of the smbios library:
- Refactor smbios cmd print functions to match the content defined by the specification.
- Add new print functions for Type 0, 3, 4 and 7.
- Update the expected pytest result to align with the smbios library changes.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
Changes in v2
- Initial patch. Move all changes related to cmd/smbios into this patch.
- Combine with #9(v1) patch.
cmd/smbios.c | 342 ++++++++++++++++++++++++++++++++--- include/smbios.h | 5 + test/py/tests/test_smbios.py | 2 +- 3 files changed, 319 insertions(+), 30 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
OK, so it should be possible to expand the test for sandbox to check each field? Something like test/dm/acpi.c ?
Regards, Simon

Hi Simon,
On Mon, 28 Oct 2024 at 13:05, Simon Glass sjg@chromium.org wrote:
On Tue, 22 Oct 2024 at 22:07, Raymond Mao raymond.mao@linaro.org wrote:
Update the cmd according to the changes of the smbios library:
- Refactor smbios cmd print functions to match the content defined by the specification.
- Add new print functions for Type 0, 3, 4 and 7.
- Update the expected pytest result to align with the smbios library changes.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
Changes in v2
- Initial patch. Move all changes related to cmd/smbios into this patch.
- Combine with #9(v1) patch.
cmd/smbios.c | 342 ++++++++++++++++++++++++++++++++--- include/smbios.h | 5 + test/py/tests/test_smbios.py | 2 +- 3 files changed, 319 insertions(+), 30 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
OK, so it should be possible to expand the test for sandbox to check each field? Something like test/dm/acpi.c ?
Yes, I can add some more field checkers in the next version.
Regards, Raymond

Enable sysinfo smbios by default for arm64. When SYSINFO_SMBIOS is enabled, disable QFW_SMBIOS.
Signed-off-by: Raymond Mao raymond.mao@linaro.org --- Changes in v2 - None.
configs/qemu_arm64_defconfig | 2 ++ drivers/misc/Kconfig | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/configs/qemu_arm64_defconfig b/configs/qemu_arm64_defconfig index 088ba39f18e..72d1cd4f995 100644 --- a/configs/qemu_arm64_defconfig +++ b/configs/qemu_arm64_defconfig @@ -61,6 +61,8 @@ CONFIG_PCIE_ECAM_GENERIC=y CONFIG_SCSI=y CONFIG_DEBUG_UART_PL011=y CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_SYSINFO=y +CONFIG_SYSINFO_SMBIOS=y CONFIG_SYSRESET=y CONFIG_SYSRESET_CMD_POWEROFF=y CONFIG_SYSRESET_PSCI=y diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 6009d55f400..da84b35e804 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -568,7 +568,7 @@ config QFW_MMIO config QFW_SMBIOS bool default y - depends on QFW && SMBIOS && !SANDBOX + depends on QFW && SMBIOS && !SANDBOX && !SYSINFO_SMBIOS help Hidden option to read SMBIOS tables from QEMU.

On Tue, 22 Oct 2024 at 22:07, Raymond Mao raymond.mao@linaro.org wrote:
Enable sysinfo smbios by default for arm64. When SYSINFO_SMBIOS is enabled, disable QFW_SMBIOS.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
Changes in v2
- None.
configs/qemu_arm64_defconfig | 2 ++ drivers/misc/Kconfig | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org

On Tue, Oct 22, 2024 at 01:05:21PM -0700, Raymond Mao wrote:
Motivations for changes: Current SMBIOS library and command-line tool is not fully matching with the requirements:
- Missing support for other mandatory types (#7, #9, #16, #17, #19).
- Only a few platforms support SMBIOS node from the device tree.
- Values of some fields are hardcoded in the library other than fetching from the device hardware.
- Embedded data with dynamic length is not supported (E.g. Contained Object Handles in Type #2 and Contained Elements in Type #3)
Changes:
- Refactor the SMBIOS library and command-line tool to better align with the SMBIOS spec.
- Create an arch-specific driver for all aarch64-based platforms to fetch SMBIOS private data from the device hardware (processor and cache).
- Create a sysinfo driver to poppulate platform SMBIOS private data.
- Add generic SMBIOS DTS file for arm64 platforms for those common strings and values which cannot be retrieved from the system registers. Vendors can create their own SMBIOS node using this as an example. For those boards without SMBIOS nodes, this DTS file can be included to have a generic SMBIOS information of the system.
- Add support for Type #7 (Cache Information) and link its handles to Type #4.
Once this patch is acceptted, subsequent patch sets will add other missing types (#9, #16, #17, #19).
Tests: To test this with QEMU arm64, please follow the guide on dt_qemu.rst to get a merged DT to run with.
qemu-system-arm -machine virt -machine dumpdtb=qemu.dtb cat <(dtc -I dtb qemu.dtb) <(dtc -I dtb ./dts/dt.dtb | grep -v /dts-v1/) \ | dtc - -o merged.dtb qemu-system-arm -machine virt -nographic -bios u-boot.bin -dtb merged.dtb
Known issues: It hits the image size limitation on R-CAR board(rcar3_salvator-x).
u-boot.img exceeds file size limit: limit: 0x100000 bytes actual: 0x10049d bytes excess: 0x49d bytes
This board needs a clean-up to reserve spaces for the changes as SMBIOS is a fundamental feature.
Below is the breakdown of the size-growth of the related functions: function old new delta static.smbios_write_type4 252 1052 +800 static.smbios_write_type7 - 764 +764 static.smbios_write_type3 188 488 +300 smbios_get_val_si - 128 +128 static.smbios_write_type2 316 376 +60 sysinfo_get_data - 56 +56 static.smbios_write_type1 380 396 +16 smbios_write_funcs 112 128 +16 ofnode_read_u32 - 12 +12 sysinfo_rcar_ops 40 48 +8 install_smbios_table 468 472 +4
Right, so here's the problem I see right now. About 70% of all U-Boot platforms enable GENERATE_SMBIOS_TABLE and so "smbios: Refactor smbios library" causes a growth of around 1.5 kilobytes. That's a problem. There is a place where we're going to generate as full and complete a table as we can, and a place where we just want maybe the basics. We need to re-factor things first so that the platforms which aren't doing detailed tables do not grow and perhaps even shrink because we can pull existing code out.

Hi Tom,
On Wed, 23 Oct 2024 at 20:23, Tom Rini trini@konsulko.com wrote:
On Tue, Oct 22, 2024 at 01:05:21PM -0700, Raymond Mao wrote:
Motivations for changes: Current SMBIOS library and command-line tool is not fully matching with the requirements:
- Missing support for other mandatory types (#7, #9, #16, #17, #19).
- Only a few platforms support SMBIOS node from the device tree.
- Values of some fields are hardcoded in the library other than fetching from the device hardware.
- Embedded data with dynamic length is not supported (E.g. Contained Object Handles in Type #2 and Contained Elements in Type #3)
Changes:
- Refactor the SMBIOS library and command-line tool to better align with the SMBIOS spec.
- Create an arch-specific driver for all aarch64-based platforms to
fetch
SMBIOS private data from the device hardware (processor and cache). 3. Create a sysinfo driver to poppulate platform SMBIOS private data. 4. Add generic SMBIOS DTS file for arm64 platforms for those common
strings
and values which cannot be retrieved from the system registers. Vendors can create their own SMBIOS node using this as an example. For those boards without SMBIOS nodes, this DTS file can be included
to
have a generic SMBIOS information of the system. 5. Add support for Type #7 (Cache Information) and link its handles to Type #4.
Once this patch is acceptted, subsequent patch sets will add other
missing
types (#9, #16, #17, #19).
Tests: To test this with QEMU arm64, please follow the guide on dt_qemu.rst to get a merged DT to run with.
qemu-system-arm -machine virt -machine dumpdtb=qemu.dtb cat <(dtc -I dtb qemu.dtb) <(dtc -I dtb ./dts/dt.dtb | grep -v
/dts-v1/) \
| dtc - -o merged.dtb qemu-system-arm -machine virt -nographic -bios u-boot.bin -dtb merged.dtb
Known issues: It hits the image size limitation on R-CAR board(rcar3_salvator-x).
u-boot.img exceeds file size limit: limit: 0x100000 bytes actual: 0x10049d bytes excess: 0x49d bytes
This board needs a clean-up to reserve spaces for the changes as SMBIOS is a fundamental feature. Below is the breakdown of the size-growth of the related functions: function old new delta static.smbios_write_type4 252 1052 +800 static.smbios_write_type7 - 764 +764 static.smbios_write_type3 188 488 +300 smbios_get_val_si - 128 +128 static.smbios_write_type2 316 376 +60 sysinfo_get_data - 56 +56 static.smbios_write_type1 380 396 +16 smbios_write_funcs 112 128 +16 ofnode_read_u32 - 12 +12 sysinfo_rcar_ops 40 48 +8 install_smbios_table 468 472 +4
Right, so here's the problem I see right now. About 70% of all U-Boot platforms enable GENERATE_SMBIOS_TABLE and so "smbios: Refactor smbios library" causes a growth of around 1.5 kilobytes. That's a problem. There is a place where we're going to generate as full and complete a table as we can, and a place where we just want maybe the basics. We need to re-factor things first so that the platforms which aren't doing detailed tables do not grow and perhaps even shrink because we can pull existing code out.
Do you have a list of those platforms which don't need detailed tables?
I can add a new kconfig for this in the next version.
Regards, Raymond

On Thu, Oct 24, 2024 at 09:35:36AM -0400, Raymond Mao wrote:
Hi Tom,
On Wed, 23 Oct 2024 at 20:23, Tom Rini trini@konsulko.com wrote:
On Tue, Oct 22, 2024 at 01:05:21PM -0700, Raymond Mao wrote:
Motivations for changes: Current SMBIOS library and command-line tool is not fully matching with the requirements:
- Missing support for other mandatory types (#7, #9, #16, #17, #19).
- Only a few platforms support SMBIOS node from the device tree.
- Values of some fields are hardcoded in the library other than fetching from the device hardware.
- Embedded data with dynamic length is not supported (E.g. Contained Object Handles in Type #2 and Contained Elements in Type #3)
Changes:
- Refactor the SMBIOS library and command-line tool to better align with the SMBIOS spec.
- Create an arch-specific driver for all aarch64-based platforms to
fetch
SMBIOS private data from the device hardware (processor and cache). 3. Create a sysinfo driver to poppulate platform SMBIOS private data. 4. Add generic SMBIOS DTS file for arm64 platforms for those common
strings
and values which cannot be retrieved from the system registers. Vendors can create their own SMBIOS node using this as an example. For those boards without SMBIOS nodes, this DTS file can be included
to
have a generic SMBIOS information of the system. 5. Add support for Type #7 (Cache Information) and link its handles to Type #4.
Once this patch is acceptted, subsequent patch sets will add other
missing
types (#9, #16, #17, #19).
Tests: To test this with QEMU arm64, please follow the guide on dt_qemu.rst to get a merged DT to run with.
qemu-system-arm -machine virt -machine dumpdtb=qemu.dtb cat <(dtc -I dtb qemu.dtb) <(dtc -I dtb ./dts/dt.dtb | grep -v
/dts-v1/) \
| dtc - -o merged.dtb qemu-system-arm -machine virt -nographic -bios u-boot.bin -dtb merged.dtb
Known issues: It hits the image size limitation on R-CAR board(rcar3_salvator-x).
u-boot.img exceeds file size limit: limit: 0x100000 bytes actual: 0x10049d bytes excess: 0x49d bytes
This board needs a clean-up to reserve spaces for the changes as SMBIOS is a fundamental feature. Below is the breakdown of the size-growth of the related functions: function old new delta static.smbios_write_type4 252 1052 +800 static.smbios_write_type7 - 764 +764 static.smbios_write_type3 188 488 +300 smbios_get_val_si - 128 +128 static.smbios_write_type2 316 376 +60 sysinfo_get_data - 56 +56 static.smbios_write_type1 380 396 +16 smbios_write_funcs 112 128 +16 ofnode_read_u32 - 12 +12 sysinfo_rcar_ops 40 48 +8 install_smbios_table 468 472 +4
Right, so here's the problem I see right now. About 70% of all U-Boot platforms enable GENERATE_SMBIOS_TABLE and so "smbios: Refactor smbios library" causes a growth of around 1.5 kilobytes. That's a problem. There is a place where we're going to generate as full and complete a table as we can, and a place where we just want maybe the basics. We need to re-factor things first so that the platforms which aren't doing detailed tables do not grow and perhaps even shrink because we can pull existing code out.
Do you have a list of those platforms which don't need detailed tables? I can add a new kconfig for this in the next version.
No, you need to determine this, but it should be something that can be determined by existing data. The platforms which grow by only 1.5KiB don't. The ones that grow by ~4KiB, maybe? You need to see what they're actually doing today to determine that. Growing by ~8KiB? Yes.
You can see my log at: https://gist.github.com/trini/8d3d4ab5b53402059a9d178786033c18
And all of that is aside from my original worry about including a large number of static strings. I did not look in to if v2 deals with that.

Hi Tom,
On Thu, 24 Oct 2024 at 10:10, Tom Rini trini@konsulko.com wrote:
On Thu, Oct 24, 2024 at 09:35:36AM -0400, Raymond Mao wrote:
Hi Tom,
On Wed, 23 Oct 2024 at 20:23, Tom Rini trini@konsulko.com wrote:
On Tue, Oct 22, 2024 at 01:05:21PM -0700, Raymond Mao wrote:
Motivations for changes: Current SMBIOS library and command-line tool is not fully matching
with
the requirements:
- Missing support for other mandatory types (#7, #9, #16, #17, #19).
- Only a few platforms support SMBIOS node from the device tree.
- Values of some fields are hardcoded in the library other than
fetching
from the device hardware. 4. Embedded data with dynamic length is not supported (E.g. Contained Object Handles in Type #2 and Contained Elements in Type #3)
Changes:
- Refactor the SMBIOS library and command-line tool to better align
with
the SMBIOS spec. 2. Create an arch-specific driver for all aarch64-based platforms to
fetch
SMBIOS private data from the device hardware (processor and
cache).
- Create a sysinfo driver to poppulate platform SMBIOS private data.
- Add generic SMBIOS DTS file for arm64 platforms for those common
strings
and values which cannot be retrieved from the system registers. Vendors can create their own SMBIOS node using this as an example. For those boards without SMBIOS nodes, this DTS file can be
included
to
have a generic SMBIOS information of the system. 5. Add support for Type #7 (Cache Information) and link its handles
to
Type #4.
Once this patch is acceptted, subsequent patch sets will add other
missing
types (#9, #16, #17, #19).
Tests: To test this with QEMU arm64, please follow the guide on dt_qemu.rst
to
get a merged DT to run with.
qemu-system-arm -machine virt -machine dumpdtb=qemu.dtb cat <(dtc -I dtb qemu.dtb) <(dtc -I dtb ./dts/dt.dtb | grep -v
/dts-v1/) \
| dtc - -o merged.dtb qemu-system-arm -machine virt -nographic -bios u-boot.bin -dtb
merged.dtb
Known issues: It hits the image size limitation on R-CAR board(rcar3_salvator-x).
u-boot.img exceeds file size limit: limit: 0x100000 bytes actual: 0x10049d bytes excess: 0x49d bytes
This board needs a clean-up to reserve spaces for the changes as
SMBIOS
is a fundamental feature.
Below is the breakdown of the size-growth of the related functions: function old new delta static.smbios_write_type4 252 1052 +800 static.smbios_write_type7 - 764 +764 static.smbios_write_type3 188 488 +300 smbios_get_val_si - 128 +128 static.smbios_write_type2 316 376 +60 sysinfo_get_data - 56 +56 static.smbios_write_type1 380 396 +16 smbios_write_funcs 112 128 +16 ofnode_read_u32 - 12 +12 sysinfo_rcar_ops 40 48 +8 install_smbios_table 468 472 +4
Right, so here's the problem I see right now. About 70% of all U-Boot platforms enable GENERATE_SMBIOS_TABLE and so "smbios: Refactor smbios library" causes a growth of around 1.5 kilobytes. That's a problem. There is a place where we're going to generate as full and complete a table as we can, and a place where we just want maybe the basics. We need to re-factor things first so that the platforms which aren't doing detailed tables do not grow and perhaps even shrink because we can pull existing code out.
Do you have a list of those platforms which don't need detailed tables? I can add a new kconfig for this in the next version.
No, you need to determine this, but it should be something that can be determined by existing data. The platforms which grow by only 1.5KiB don't. The ones that grow by ~4KiB, maybe? You need to see what they're actually doing today to determine that. Growing by ~8KiB? Yes.
You can see my log at: https://gist.github.com/trini/8d3d4ab5b53402059a9d178786033c18
And all of that is aside from my original worry about including a large number of static strings. I did not look in to if v2 deals with that.
Yes, v2 has moved all the common strings and values to a generic dtsi
so that it can be included if any platforms are interested other than qemu_arm64. I will look into the log you provided.
Regards, Raymond

On Thu, Oct 24, 2024 at 10:19:41AM -0400, Raymond Mao wrote:
Hi Tom,
On Thu, 24 Oct 2024 at 10:10, Tom Rini trini@konsulko.com wrote:
On Thu, Oct 24, 2024 at 09:35:36AM -0400, Raymond Mao wrote:
Hi Tom,
On Wed, 23 Oct 2024 at 20:23, Tom Rini trini@konsulko.com wrote:
On Tue, Oct 22, 2024 at 01:05:21PM -0700, Raymond Mao wrote:
Motivations for changes: Current SMBIOS library and command-line tool is not fully matching
with
the requirements:
- Missing support for other mandatory types (#7, #9, #16, #17, #19).
- Only a few platforms support SMBIOS node from the device tree.
- Values of some fields are hardcoded in the library other than
fetching
from the device hardware. 4. Embedded data with dynamic length is not supported (E.g. Contained Object Handles in Type #2 and Contained Elements in Type #3)
Changes:
- Refactor the SMBIOS library and command-line tool to better align
with
the SMBIOS spec. 2. Create an arch-specific driver for all aarch64-based platforms to
fetch
SMBIOS private data from the device hardware (processor and
cache).
- Create a sysinfo driver to poppulate platform SMBIOS private data.
- Add generic SMBIOS DTS file for arm64 platforms for those common
strings
and values which cannot be retrieved from the system registers. Vendors can create their own SMBIOS node using this as an example. For those boards without SMBIOS nodes, this DTS file can be
included
to
have a generic SMBIOS information of the system. 5. Add support for Type #7 (Cache Information) and link its handles
to
Type #4.
Once this patch is acceptted, subsequent patch sets will add other
missing
types (#9, #16, #17, #19).
Tests: To test this with QEMU arm64, please follow the guide on dt_qemu.rst
to
get a merged DT to run with.
qemu-system-arm -machine virt -machine dumpdtb=qemu.dtb cat <(dtc -I dtb qemu.dtb) <(dtc -I dtb ./dts/dt.dtb | grep -v
/dts-v1/) \
| dtc - -o merged.dtb qemu-system-arm -machine virt -nographic -bios u-boot.bin -dtb
merged.dtb
Known issues: It hits the image size limitation on R-CAR board(rcar3_salvator-x).
u-boot.img exceeds file size limit: limit: 0x100000 bytes actual: 0x10049d bytes excess: 0x49d bytes
This board needs a clean-up to reserve spaces for the changes as
SMBIOS
is a fundamental feature.
Below is the breakdown of the size-growth of the related functions: function old new delta static.smbios_write_type4 252 1052 +800 static.smbios_write_type7 - 764 +764 static.smbios_write_type3 188 488 +300 smbios_get_val_si - 128 +128 static.smbios_write_type2 316 376 +60 sysinfo_get_data - 56 +56 static.smbios_write_type1 380 396 +16 smbios_write_funcs 112 128 +16 ofnode_read_u32 - 12 +12 sysinfo_rcar_ops 40 48 +8 install_smbios_table 468 472 +4
Right, so here's the problem I see right now. About 70% of all U-Boot platforms enable GENERATE_SMBIOS_TABLE and so "smbios: Refactor smbios library" causes a growth of around 1.5 kilobytes. That's a problem. There is a place where we're going to generate as full and complete a table as we can, and a place where we just want maybe the basics. We need to re-factor things first so that the platforms which aren't doing detailed tables do not grow and perhaps even shrink because we can pull existing code out.
Do you have a list of those platforms which don't need detailed tables? I can add a new kconfig for this in the next version.
No, you need to determine this, but it should be something that can be determined by existing data. The platforms which grow by only 1.5KiB don't. The ones that grow by ~4KiB, maybe? You need to see what they're actually doing today to determine that. Growing by ~8KiB? Yes.
You can see my log at: https://gist.github.com/trini/8d3d4ab5b53402059a9d178786033c18
And all of that is aside from my original worry about including a large number of static strings. I did not look in to if v2 deals with that.
Yes, v2 has moved all the common strings and values to a generic dtsi so that it can be included if any platforms are interested other than qemu_arm64. I will look into the log you provided.
Well, that's better, but not great if it's still including all of the strings. But we can circle back to that because this other issue is more important to figure out first, thanks.
participants (4)
-
Heinrich Schuchardt
-
Raymond Mao
-
Simon Glass
-
Tom Rini