
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. 3. Create a sysinfo driver to poppulate platform SMBIOS private data. 4. Put device tree SMBIOS node as a fallback solution when SMBIOS data is missing from sysinfo driver. 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).
Raymond Mao (10): sysinfo: Add sysinfo API for accessing data area sysinfo: Add sysinfo driver and data structure for SMBIOS smbios: Refactor SMBIOS library smbios: ignore the non-existence of platform sysinfo detect armv8: Add arch-specific sysinfo driver sysinfo: Add sysinfo driver for SMBIOS type 7 smbios: Add support to SMBIOS type 7 armv8: Add sysinfo driver for cache information configs: Enable sysinfo for QEMU Arm64 tests: update smbios pytest
arch/arm/cpu/armv8/Makefile | 5 + arch/arm/cpu/armv8/sysinfo.c | 391 ++++++++++++++++++++++++++ cmd/smbios.c | 350 ++++++++++++++++++++++- configs/qemu_arm64_defconfig | 2 + drivers/misc/Kconfig | 2 +- drivers/sysinfo/Makefile | 1 + drivers/sysinfo/smbios_plat.c | 442 +++++++++++++++++++++++++++++ drivers/sysinfo/smbios_plat.h | 131 +++++++++ drivers/sysinfo/sysinfo-uclass.c | 20 ++ include/smbios.h | 240 ++++++++++++++-- include/sysinfo.h | 124 ++++++++- lib/Makefile | 2 + lib/smbios.c | 461 ++++++++++++++++++++++++++----- test/py/tests/test_smbios.py | 2 +- 14 files changed, 2058 insertions(+), 115 deletions(-) create mode 100644 arch/arm/cpu/armv8/sysinfo.c create mode 100644 drivers/sysinfo/smbios_plat.c create mode 100644 drivers/sysinfo/smbios_plat.h

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 --- 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;

Add sysinfo interface and definitions to support SMBIOS type 0 to type 4.
Signed-off-by: Raymond Mao raymond.mao@linaro.org --- drivers/sysinfo/Makefile | 1 + drivers/sysinfo/smbios_plat.c | 270 ++++++++++++++++++++++++++++++++++ drivers/sysinfo/smbios_plat.h | 104 +++++++++++++ include/smbios.h | 12 ++ include/sysinfo.h | 58 +++++++- lib/Makefile | 2 + 6 files changed, 446 insertions(+), 1 deletion(-) create mode 100644 drivers/sysinfo/smbios_plat.c create mode 100644 drivers/sysinfo/smbios_plat.h
diff --git a/drivers/sysinfo/Makefile b/drivers/sysinfo/Makefile index 680dde77fe8..3e478f87c23 100644 --- a/drivers/sysinfo/Makefile +++ b/drivers/sysinfo/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_SYSINFO_GPIO) += gpio.o obj-$(CONFIG_SYSINFO_RCAR3) += rcar3.o obj-$(CONFIG_SYSINFO_SANDBOX) += sandbox.o obj-$(CONFIG_SYSINFO_SMBIOS) += smbios.o +obj-$(CONFIG_SYSINFO_SMBIOS) += smbios_plat.o \ No newline at end of file diff --git a/drivers/sysinfo/smbios_plat.c b/drivers/sysinfo/smbios_plat.c new file mode 100644 index 00000000000..adbc8cf3cf2 --- /dev/null +++ b/drivers/sysinfo/smbios_plat.c @@ -0,0 +1,270 @@ +// 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 <sysinfo.h> + +struct sysinfo_plat_priv { + struct sys_info *t1; + struct baseboard_info *t2; + struct enclosure_info *t3; + struct processor_info *t4; +}; + +/* weak function for the platforms not yet supported */ +__weak int sysinfo_get_processor_info(struct processor_info *pinfo) +{ + return -ENOSYS; +} + +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_SYSTEM_MANUFACTURER: + str = priv->t1->manufacturer; + break; + case SYSINFO_ID_SMBIOS_SYSTEM_PRODUCT: + str = priv->t1->prod_name; + break; + case SYSINFO_ID_SMBIOS_SYSTEM_VERSION: + str = priv->t1->version; + break; + case SYSINFO_ID_SMBIOS_SYSTEM_SERIAL: + str = priv->t1->sn; + break; + case SYSINFO_ID_SMBIOS_SYSTEM_SKU: + str = priv->t1->sku_num; + break; + case SYSINFO_ID_SMBIOS_SYSTEM_FAMILY: + str = priv->t1->family; + break; + case SYSINFO_ID_SMBIOS_BASEBOARD_MANUFACTURER: + str = priv->t2->manufacturer; + break; + case SYSINFO_ID_SMBIOS_BASEBOARD_PRODUCT: + str = priv->t2->prod_name; + break; + case SYSINFO_ID_SMBIOS_BASEBOARD_VERSION: + str = priv->t2->version; + break; + case SYSINFO_ID_SMBIOS_BASEBOARD_SERIAL: + str = priv->t2->sn; + break; + case SYSINFO_ID_SMBIOS_BASEBOARD_ASSET_TAG: + str = priv->t2->asset_tag; + break; + case SYSINFO_ID_SMBIOS_BASEBOARD_CHASSIS_LOCAT: + str = priv->t2->chassis_locat; + break; + case SYSINFO_ID_SMBIOS_ENCLOSURE_MANUFACTURER: + str = priv->t3->manufacturer; + break; + case SYSINFO_ID_SMBIOS_ENCLOSURE_VERSION: + str = priv->t3->version; + break; + case SYSINFO_ID_SMBIOS_ENCLOSURE_SERIAL: + str = priv->t3->sn; + break; + case SYSINFO_ID_SMBIOS_ENCLOSURE_ASSET_TAG: + str = priv->t3->asset_tag; + break; + case SYSINFO_ID_SMBIOS_ENCLOSURE_SKU: + str = priv->t3->sku_num; + break; + case SYSINFO_ID_SMBIOS_PROCESSOR_SOCKET: + str = priv->t4->socket_design; + break; + case SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT: + str = priv->t4->manufacturer; + break; + case SYSINFO_ID_SMBIOS_PROCESSOR_VERSION: + str = priv->t4->version; + break; + case SYSINFO_ID_SMBIOS_PROCESSOR_SN: + str = priv->t4->sn; + break; + case SYSINFO_ID_SMBIOS_PROCESSOR_ASSET_TAG: + str = priv->t4->asset_tag; + break; + case SYSINFO_ID_SMBIOS_PROCESSOR_PN: + str = priv->t4->pn; + 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); + + switch (id) { + case SYSINFO_ID_SMBIOS_SYSTEM_WAKEUP: + *val = priv->t1->wakeup_type; + break; + case SYSINFO_ID_SMBIOS_BASEBOARD_FEATURE: + *val = priv->t2->feature.data; + break; + case SYSINFO_ID_SMBIOS_BASEBOARD_TYPE: + *val = priv->t2->type; + break; + case SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_NUM: + *val = priv->t2->objs_num; + break; + case SYSINFO_ID_SMBIOS_ENCLOSURE_TYPE: + *val = priv->t3->chassis_type; + break; + case SYSINFO_ID_SMBIOS_ENCLOSURE_BOOTUP: + *val = priv->t3->bootup_state; + break; + case SYSINFO_ID_SMBIOS_ENCLOSURE_POW: + *val = priv->t3->power_supply_state; + break; + case SYSINFO_ID_SMBIOS_ENCLOSURE_THERMAL: + *val = priv->t3->thermal_state; + break; + case SYSINFO_ID_SMBIOS_ENCLOSURE_SECURITY: + *val = priv->t3->security_status; + break; + case SYSINFO_ID_SMBIOS_ENCLOSURE_OEM: + *val = priv->t3->oem_defined; + break; + case SYSINFO_ID_SMBIOS_ENCLOSURE_HEIGHT: + *val = priv->t3->height; + break; + case SYSINFO_ID_SMBIOS_ENCLOSURE_POWCORE_NUM: + *val = priv->t3->number_of_power_cords; + break; + case SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_CNT: + *val = priv->t3->element_count; + break; + case SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_LEN: + *val = priv->t3->element_record_length; + break; + case SYSINFO_ID_SMBIOS_PROCESSOR_TYPE: + *val = priv->t4->type; + break; + case SYSINFO_ID_SMBIOS_PROCESSOR_VOLTAGE: + *val = priv->t4->voltage; + break; + case SYSINFO_ID_SMBIOS_PROCESSOR_EXT_CLOCK: + *val = priv->t4->ext_clock; + break; + case SYSINFO_ID_SMBIOS_PROCESSOR_MAX_SPEED: + *val = priv->t4->max_speed; + break; + case SYSINFO_ID_SMBIOS_PROCESSOR_CUR_SPEED: + *val = priv->t4->curr_speed; + break; + case SYSINFO_ID_SMBIOS_PROCESSOR_STATUS: + *val = priv->t4->status; + break; + case SYSINFO_ID_SMBIOS_PROCESSOR_UPGRADE: + *val = priv->t4->upgrade; + break; + 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_THREAD_CNT: + *val = priv->t4->thread_count; + break; + case SYSINFO_ID_SMBIOS_PROCESSOR_CHARA: + *val = priv->t4->characteristics; + break; + case SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY2: + *val = priv->t4->family2; + break; + case SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT2: + *val = priv->t4->core_count2; + break; + case SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN2: + *val = priv->t4->core_enabled2; + break; + case SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT2: + *val = priv->t4->thread_count2; + break; + case SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_EN: + *val = priv->t4->thread_enabled; + break; + default: + break; + } + + 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_ENCLOSURE_ELEMENTS: + *buf = priv->t3->elements; + *size = priv->t3->elements_size; + break; + case SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_HANDLE: + *buf = priv->t2->objs; + *size = priv->t2->objs_size; + break; + case SYSINFO_ID_SMBIOS_PROCESSOR_ID: + *buf = (uchar *)priv->t4->id; + *size = sizeof(priv->t4->id); + break; + default: + break; + } + return 0; +} + +static int sysinfo_plat_probe(struct udevice *dev) +{ + struct sysinfo_plat_priv *priv = dev_get_priv(dev); + struct sysinfo_plat *plat = dev_get_plat(dev); + + priv->t1 = &plat->sys; + priv->t2 = &plat->board; + priv->t3 = &plat->chassis; + + if (!sysinfo_get_processor_info(plat->processor)) + priv->t4 = plat->processor; + + return 0; +} + +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_plat) = { + .name = "sysinfo_smbios_plat", + .id = UCLASS_SYSINFO, + .ops = &sysinfo_smbios_ops, + .priv_auto = sizeof(struct sysinfo_plat_priv), + .probe = sysinfo_plat_probe, +}; diff --git a/drivers/sysinfo/smbios_plat.h b/drivers/sysinfo/smbios_plat.h new file mode 100644 index 00000000000..3576f492ecb --- /dev/null +++ b/drivers/sysinfo/smbios_plat.h @@ -0,0 +1,104 @@ +/* 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> + +/* + * TODO: + * sysinfo_plat and all sub data structure should be moved to <asm/sysinfo.h> + * if we have this defined for each arch. + */ +struct __packed sys_info { + char *manufacturer; + char *prod_name; + char *version; + char *sn; + u8 wakeup_type; + char *sku_num; + char *family; +}; + +struct __packed baseboard_info { + char *manufacturer; + char *prod_name; + char *version; + char *sn; + char *asset_tag; + union baseboard_feat feature; + char *chassis_locat; + u8 type; + u8 objs_num; + void *objs; + size_t objs_size; +}; + +struct __packed enclosure_info { + char *manufacturer; + char *version; + char *sn; + char *asset_tag; + u8 chassis_type; + u8 bootup_state; + u8 power_supply_state; + u8 thermal_state; + u8 security_status; + u32 oem_defined; + u8 height; + u8 number_of_power_cords; + u8 element_count; + u8 element_record_length; + void *elements; + size_t elements_size; + char *sku_num; +}; + +struct __packed processor_info { + char *socket_design; + u8 type; + u8 family; + char *manufacturer; + u32 id[2]; + char *version; + u8 voltage; + u16 ext_clock; + u16 max_speed; + u16 curr_speed; + u8 status; + u8 upgrade; + char *sn; + char *asset_tag; + char *pn; + u8 core_count; + u8 core_enabled; + u8 thread_count; + u16 characteristics; + u16 family2; + u16 core_count2; + u16 core_enabled2; + u16 thread_count2; + u16 thread_enabled; +}; + +struct sysinfo_plat { + struct sys_info sys; + struct baseboard_info board; + struct enclosure_info chassis; + struct processor_info *processor; + /* add other sysinfo structure here */ +}; + +#if CONFIG_IS_ENABLED(SYSINFO_SMBIOS) +int sysinfo_get_processor_info(struct processor_info *pinfo); +#else +static inline int sysinfo_get_processor_info(struct processor_info *pinfo) +{ + return -ENOSYS; +} +#endif + +#endif /* __SMBIOS_PLAT_H */ diff --git a/include/smbios.h b/include/smbios.h index 00119d7a60c..60e28a89af8 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -154,6 +154,18 @@ struct __packed smbios_type1 { #define SMBIOS_BOARD_FEATURE_HOSTING (1 << 0) #define SMBIOS_BOARD_MOTHERBOARD 10
+union baseboard_feat { + struct { + u8 hosting_board:1; + u8 need_daughter_board:1; + u8 removable:1; + u8 replaceable:1; + u8 hot_swappable:1; + u8 rsvd:3; + } fields; + u8 data; +}; + struct __packed smbios_type2 { u8 type; u8 length; diff --git a/include/sysinfo.h b/include/sysinfo.h index 17b2b9c7111..6c9de7744c1 100644 --- a/include/sysinfo.h +++ b/include/sysinfo.h @@ -42,18 +42,74 @@ 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_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,
/* For show_board_info() */ SYSINFO_ID_BOARD_MODEL, diff --git a/lib/Makefile b/lib/Makefile index 81b503ab526..1829647e83d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -42,6 +42,8 @@ obj-$(CONFIG_FIT) += fdtdec_common.o obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o obj-$(CONFIG_GZIP_COMPRESSED) += gzip.o obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o +ccflags-$(CONFIG_SYSINFO_SMBIOS) += \ + -I$(srctree)/drivers/sysinfo obj-$(CONFIG_SMBIOS_PARSER) += smbios-parser.o obj-$(CONFIG_IMAGE_SPARSE) += image-sparse.o obj-y += initcall.o

On 8/16/24 17:46, Raymond Mao wrote:
Add sysinfo interface and definitions to support SMBIOS type 0 to type 4.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
drivers/sysinfo/Makefile | 1 + drivers/sysinfo/smbios_plat.c | 270 ++++++++++++++++++++++++++++++++++ drivers/sysinfo/smbios_plat.h | 104 +++++++++++++ include/smbios.h | 12 ++ include/sysinfo.h | 58 +++++++- lib/Makefile | 2 + 6 files changed, 446 insertions(+), 1 deletion(-) create mode 100644 drivers/sysinfo/smbios_plat.c create mode 100644 drivers/sysinfo/smbios_plat.h
diff --git a/drivers/sysinfo/Makefile b/drivers/sysinfo/Makefile index 680dde77fe8..3e478f87c23 100644 --- a/drivers/sysinfo/Makefile +++ b/drivers/sysinfo/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_SYSINFO_GPIO) += gpio.o obj-$(CONFIG_SYSINFO_RCAR3) += rcar3.o obj-$(CONFIG_SYSINFO_SANDBOX) += sandbox.o obj-$(CONFIG_SYSINFO_SMBIOS) += smbios.o +obj-$(CONFIG_SYSINFO_SMBIOS) += smbios_plat.o \ No newline at end of file
doesn't look correct.
diff --git a/drivers/sysinfo/smbios_plat.c b/drivers/sysinfo/smbios_plat.c new file mode 100644 index 00000000000..adbc8cf3cf2 --- /dev/null +++ b/drivers/sysinfo/smbios_plat.c @@ -0,0 +1,270 @@ +// 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 <sysinfo.h>
+struct sysinfo_plat_priv {
- struct sys_info *t1;
- struct baseboard_info *t2;
- struct enclosure_info *t3;
- struct processor_info *t4;
+};
+/* weak function for the platforms not yet supported */ +__weak int sysinfo_get_processor_info(struct processor_info *pinfo) +{
- return -ENOSYS;
+}
+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_SYSTEM_MANUFACTURER:
str = priv->t1->manufacturer;
break;
- case SYSINFO_ID_SMBIOS_SYSTEM_PRODUCT:
str = priv->t1->prod_name;
break;
- case SYSINFO_ID_SMBIOS_SYSTEM_VERSION:
str = priv->t1->version;
break;
- case SYSINFO_ID_SMBIOS_SYSTEM_SERIAL:
str = priv->t1->sn;
break;
- case SYSINFO_ID_SMBIOS_SYSTEM_SKU:
str = priv->t1->sku_num;
break;
- case SYSINFO_ID_SMBIOS_SYSTEM_FAMILY:
str = priv->t1->family;
break;
- case SYSINFO_ID_SMBIOS_BASEBOARD_MANUFACTURER:
str = priv->t2->manufacturer;
break;
- case SYSINFO_ID_SMBIOS_BASEBOARD_PRODUCT:
str = priv->t2->prod_name;
break;
- case SYSINFO_ID_SMBIOS_BASEBOARD_VERSION:
str = priv->t2->version;
break;
- case SYSINFO_ID_SMBIOS_BASEBOARD_SERIAL:
str = priv->t2->sn;
break;
- case SYSINFO_ID_SMBIOS_BASEBOARD_ASSET_TAG:
str = priv->t2->asset_tag;
break;
- case SYSINFO_ID_SMBIOS_BASEBOARD_CHASSIS_LOCAT:
str = priv->t2->chassis_locat;
break;
- case SYSINFO_ID_SMBIOS_ENCLOSURE_MANUFACTURER:
str = priv->t3->manufacturer;
break;
- case SYSINFO_ID_SMBIOS_ENCLOSURE_VERSION:
str = priv->t3->version;
break;
- case SYSINFO_ID_SMBIOS_ENCLOSURE_SERIAL:
str = priv->t3->sn;
break;
- case SYSINFO_ID_SMBIOS_ENCLOSURE_ASSET_TAG:
str = priv->t3->asset_tag;
break;
- case SYSINFO_ID_SMBIOS_ENCLOSURE_SKU:
str = priv->t3->sku_num;
break;
- case SYSINFO_ID_SMBIOS_PROCESSOR_SOCKET:
str = priv->t4->socket_design;
break;
- case SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT:
str = priv->t4->manufacturer;
break;
- case SYSINFO_ID_SMBIOS_PROCESSOR_VERSION:
str = priv->t4->version;
break;
- case SYSINFO_ID_SMBIOS_PROCESSOR_SN:
str = priv->t4->sn;
break;
- case SYSINFO_ID_SMBIOS_PROCESSOR_ASSET_TAG:
str = priv->t4->asset_tag;
break;
- case SYSINFO_ID_SMBIOS_PROCESSOR_PN:
str = priv->t4->pn;
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);
- switch (id) {
- case SYSINFO_ID_SMBIOS_SYSTEM_WAKEUP:
*val = priv->t1->wakeup_type;
break;
- case SYSINFO_ID_SMBIOS_BASEBOARD_FEATURE:
*val = priv->t2->feature.data;
break;
- case SYSINFO_ID_SMBIOS_BASEBOARD_TYPE:
*val = priv->t2->type;
break;
- case SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_NUM:
*val = priv->t2->objs_num;
break;
- case SYSINFO_ID_SMBIOS_ENCLOSURE_TYPE:
*val = priv->t3->chassis_type;
break;
- case SYSINFO_ID_SMBIOS_ENCLOSURE_BOOTUP:
*val = priv->t3->bootup_state;
break;
- case SYSINFO_ID_SMBIOS_ENCLOSURE_POW:
*val = priv->t3->power_supply_state;
break;
- case SYSINFO_ID_SMBIOS_ENCLOSURE_THERMAL:
*val = priv->t3->thermal_state;
break;
- case SYSINFO_ID_SMBIOS_ENCLOSURE_SECURITY:
*val = priv->t3->security_status;
break;
- case SYSINFO_ID_SMBIOS_ENCLOSURE_OEM:
*val = priv->t3->oem_defined;
break;
- case SYSINFO_ID_SMBIOS_ENCLOSURE_HEIGHT:
*val = priv->t3->height;
break;
- case SYSINFO_ID_SMBIOS_ENCLOSURE_POWCORE_NUM:
*val = priv->t3->number_of_power_cords;
break;
- case SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_CNT:
*val = priv->t3->element_count;
break;
- case SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_LEN:
*val = priv->t3->element_record_length;
break;
- case SYSINFO_ID_SMBIOS_PROCESSOR_TYPE:
*val = priv->t4->type;
break;
- case SYSINFO_ID_SMBIOS_PROCESSOR_VOLTAGE:
*val = priv->t4->voltage;
break;
- case SYSINFO_ID_SMBIOS_PROCESSOR_EXT_CLOCK:
*val = priv->t4->ext_clock;
break;
- case SYSINFO_ID_SMBIOS_PROCESSOR_MAX_SPEED:
*val = priv->t4->max_speed;
break;
- case SYSINFO_ID_SMBIOS_PROCESSOR_CUR_SPEED:
*val = priv->t4->curr_speed;
break;
- case SYSINFO_ID_SMBIOS_PROCESSOR_STATUS:
*val = priv->t4->status;
break;
- case SYSINFO_ID_SMBIOS_PROCESSOR_UPGRADE:
*val = priv->t4->upgrade;
break;
- 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_THREAD_CNT:
*val = priv->t4->thread_count;
break;
- case SYSINFO_ID_SMBIOS_PROCESSOR_CHARA:
*val = priv->t4->characteristics;
break;
- case SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY2:
*val = priv->t4->family2;
break;
- case SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT2:
*val = priv->t4->core_count2;
break;
- case SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN2:
*val = priv->t4->core_enabled2;
break;
- case SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT2:
*val = priv->t4->thread_count2;
break;
- case SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_EN:
*val = priv->t4->thread_enabled;
break;
- default:
break;
- }
- 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_ENCLOSURE_ELEMENTS:
*buf = priv->t3->elements;
*size = priv->t3->elements_size;
break;
- case SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_HANDLE:
*buf = priv->t2->objs;
*size = priv->t2->objs_size;
break;
- case SYSINFO_ID_SMBIOS_PROCESSOR_ID:
*buf = (uchar *)priv->t4->id;
*size = sizeof(priv->t4->id);
break;
- default:
break;
- }
- return 0;
+}
+static int sysinfo_plat_probe(struct udevice *dev) +{
- struct sysinfo_plat_priv *priv = dev_get_priv(dev);
- struct sysinfo_plat *plat = dev_get_plat(dev);
- priv->t1 = &plat->sys;
- priv->t2 = &plat->board;
- priv->t3 = &plat->chassis;
- if (!sysinfo_get_processor_info(plat->processor))
priv->t4 = plat->processor;
- return 0;
+}
+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_plat) = {
- .name = "sysinfo_smbios_plat",
- .id = UCLASS_SYSINFO,
- .ops = &sysinfo_smbios_ops,
- .priv_auto = sizeof(struct sysinfo_plat_priv),
- .probe = sysinfo_plat_probe,
+}; diff --git a/drivers/sysinfo/smbios_plat.h b/drivers/sysinfo/smbios_plat.h new file mode 100644 index 00000000000..3576f492ecb --- /dev/null +++ b/drivers/sysinfo/smbios_plat.h @@ -0,0 +1,104 @@ +/* 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>
+/*
- TODO:
- sysinfo_plat and all sub data structure should be moved to <asm/sysinfo.h>
- if we have this defined for each arch.
But why?
- */
+struct __packed sys_info {
- char *manufacturer;
- char *prod_name;
- char *version;
- char *sn;
- u8 wakeup_type;
- char *sku_num;
- char *family;
+};
+struct __packed baseboard_info {
- char *manufacturer;
- char *prod_name;
- char *version;
- char *sn;
- char *asset_tag;
- union baseboard_feat feature;
- char *chassis_locat;
- u8 type;
- u8 objs_num;
- void *objs;
- size_t objs_size;
+};
+struct __packed enclosure_info {
- char *manufacturer;
- char *version;
- char *sn;
- char *asset_tag;
- u8 chassis_type;
- u8 bootup_state;
- u8 power_supply_state;
- u8 thermal_state;
- u8 security_status;
- u32 oem_defined;
- u8 height;
- u8 number_of_power_cords;
- u8 element_count;
- u8 element_record_length;
- void *elements;
- size_t elements_size;
- char *sku_num;
+};
+struct __packed processor_info {
- char *socket_design;
- u8 type;
- u8 family;
packed is nice but I think you should use pahole and look at them to see where you have gaps. Because I am quite sure you have gaps there.
char * is 64bit then two u8 and below is another pointer which has 64bit.
Or 32bit arch it is the same.
- char *manufacturer;
- u32 id[2];
- char *version;
- u8 voltage;
- u16 ext_clock;
- u16 max_speed;
- u16 curr_speed;
- u8 status;
- u8 upgrade;
- char *sn;
- char *asset_tag;
- char *pn;
- u8 core_count;
- u8 core_enabled;
- u8 thread_count;
- u16 characteristics;
- u16 family2;
- u16 core_count2;
- u16 core_enabled2;
- u16 thread_count2;
- u16 thread_enabled;
+};
+struct sysinfo_plat {
- struct sys_info sys;
- struct baseboard_info board;
- struct enclosure_info chassis;
- struct processor_info *processor;
- /* add other sysinfo structure here */
+};
+#if CONFIG_IS_ENABLED(SYSINFO_SMBIOS) +int sysinfo_get_processor_info(struct processor_info *pinfo); +#else +static inline int sysinfo_get_processor_info(struct processor_info *pinfo) +{
- return -ENOSYS;
+} +#endif
+#endif /* __SMBIOS_PLAT_H */ diff --git a/include/smbios.h b/include/smbios.h index 00119d7a60c..60e28a89af8 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -154,6 +154,18 @@ struct __packed smbios_type1 { #define SMBIOS_BOARD_FEATURE_HOSTING (1 << 0) #define SMBIOS_BOARD_MOTHERBOARD 10
+union baseboard_feat {
- struct {
u8 hosting_board:1;
u8 need_daughter_board:1;
u8 removable:1;
u8 replaceable:1;
u8 hot_swappable:1;
u8 rsvd:3;
- } fields;
- u8 data;
+};
- struct __packed smbios_type2 { u8 type; u8 length;
diff --git a/include/sysinfo.h b/include/sysinfo.h index 17b2b9c7111..6c9de7744c1 100644 --- a/include/sysinfo.h +++ b/include/sysinfo.h @@ -42,18 +42,74 @@ 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_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,
/* For show_board_info() */ SYSINFO_ID_BOARD_MODEL,
diff --git a/lib/Makefile b/lib/Makefile index 81b503ab526..1829647e83d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -42,6 +42,8 @@ obj-$(CONFIG_FIT) += fdtdec_common.o obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o obj-$(CONFIG_GZIP_COMPRESSED) += gzip.o obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o +ccflags-$(CONFIG_SYSINFO_SMBIOS) += \
- -I$(srctree)/drivers/sysinfo
I can't see reason for this. Why do you think make sense to keep header in drivers/sysinfo when you can move it to include/ directly.
obj-$(CONFIG_SMBIOS_PARSER) += smbios-parser.o obj-$(CONFIG_IMAGE_SPARSE) += image-sparse.o obj-y += initcall.o
M

On 8/16/24 17:46, Raymond Mao wrote:
Add sysinfo interface and definitions to support SMBIOS type 0 to type 4.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
drivers/sysinfo/Makefile | 1 + drivers/sysinfo/smbios_plat.c | 270 ++++++++++++++++++++++++++++++++++ drivers/sysinfo/smbios_plat.h | 104 +++++++++++++ include/smbios.h | 12 ++ include/sysinfo.h | 58 +++++++- lib/Makefile | 2 + 6 files changed, 446 insertions(+), 1 deletion(-) create mode 100644 drivers/sysinfo/smbios_plat.c create mode 100644 drivers/sysinfo/smbios_plat.h
diff --git a/drivers/sysinfo/Makefile b/drivers/sysinfo/Makefile index 680dde77fe8..3e478f87c23 100644 --- a/drivers/sysinfo/Makefile +++ b/drivers/sysinfo/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_SYSINFO_GPIO) += gpio.o obj-$(CONFIG_SYSINFO_RCAR3) += rcar3.o obj-$(CONFIG_SYSINFO_SANDBOX) += sandbox.o obj-$(CONFIG_SYSINFO_SMBIOS) += smbios.o +obj-$(CONFIG_SYSINFO_SMBIOS) += smbios_plat.o
One more thing. Does it make sense to have it under the same Kconfig entry? I think separate symbol would make more sense and can be enabled but default but there should be an option to disable it and replaced by own implementation or use existing one.
Thanks, Michal

Hi Raymond,
On Fri, 16 Aug 2024 at 09:47, Raymond Mao raymond.mao@linaro.org wrote:
Add sysinfo interface and definitions to support SMBIOS type 0 to type 4.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
drivers/sysinfo/Makefile | 1 + drivers/sysinfo/smbios_plat.c | 270 ++++++++++++++++++++++++++++++++++ drivers/sysinfo/smbios_plat.h | 104 +++++++++++++ include/smbios.h | 12 ++ include/sysinfo.h | 58 +++++++- lib/Makefile | 2 + 6 files changed, 446 insertions(+), 1 deletion(-) create mode 100644 drivers/sysinfo/smbios_plat.c create mode 100644 drivers/sysinfo/smbios_plat.h
diff --git a/drivers/sysinfo/Makefile b/drivers/sysinfo/Makefile index 680dde77fe8..3e478f87c23 100644 --- a/drivers/sysinfo/Makefile +++ b/drivers/sysinfo/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_SYSINFO_GPIO) += gpio.o obj-$(CONFIG_SYSINFO_RCAR3) += rcar3.o obj-$(CONFIG_SYSINFO_SANDBOX) += sandbox.o obj-$(CONFIG_SYSINFO_SMBIOS) += smbios.o +obj-$(CONFIG_SYSINFO_SMBIOS) += smbios_plat.o \ No newline at end of file diff --git a/drivers/sysinfo/smbios_plat.c b/drivers/sysinfo/smbios_plat.c new file mode 100644 index 00000000000..adbc8cf3cf2 --- /dev/null +++ b/drivers/sysinfo/smbios_plat.c @@ -0,0 +1,270 @@ +// 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 <sysinfo.h>
+struct sysinfo_plat_priv {
struct sys_info *t1;
struct baseboard_info *t2;
struct enclosure_info *t3;
struct processor_info *t4;
+};
+/* weak function for the platforms not yet supported */ +__weak int sysinfo_get_processor_info(struct processor_info *pinfo) +{
return -ENOSYS;
+}
+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_SYSTEM_MANUFACTURER:
str = priv->t1->manufacturer;
break;
case SYSINFO_ID_SMBIOS_SYSTEM_PRODUCT:
str = priv->t1->prod_name;
break;
case SYSINFO_ID_SMBIOS_SYSTEM_VERSION:
str = priv->t1->version;
break;
case SYSINFO_ID_SMBIOS_SYSTEM_SERIAL:
str = priv->t1->sn;
break;
case SYSINFO_ID_SMBIOS_SYSTEM_SKU:
str = priv->t1->sku_num;
break;
case SYSINFO_ID_SMBIOS_SYSTEM_FAMILY:
str = priv->t1->family;
break;
case SYSINFO_ID_SMBIOS_BASEBOARD_MANUFACTURER:
str = priv->t2->manufacturer;
break;
case SYSINFO_ID_SMBIOS_BASEBOARD_PRODUCT:
str = priv->t2->prod_name;
break;
case SYSINFO_ID_SMBIOS_BASEBOARD_VERSION:
str = priv->t2->version;
break;
case SYSINFO_ID_SMBIOS_BASEBOARD_SERIAL:
str = priv->t2->sn;
break;
case SYSINFO_ID_SMBIOS_BASEBOARD_ASSET_TAG:
str = priv->t2->asset_tag;
break;
case SYSINFO_ID_SMBIOS_BASEBOARD_CHASSIS_LOCAT:
str = priv->t2->chassis_locat;
break;
case SYSINFO_ID_SMBIOS_ENCLOSURE_MANUFACTURER:
str = priv->t3->manufacturer;
break;
case SYSINFO_ID_SMBIOS_ENCLOSURE_VERSION:
str = priv->t3->version;
break;
case SYSINFO_ID_SMBIOS_ENCLOSURE_SERIAL:
str = priv->t3->sn;
break;
case SYSINFO_ID_SMBIOS_ENCLOSURE_ASSET_TAG:
str = priv->t3->asset_tag;
break;
case SYSINFO_ID_SMBIOS_ENCLOSURE_SKU:
str = priv->t3->sku_num;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_SOCKET:
str = priv->t4->socket_design;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT:
str = priv->t4->manufacturer;
This function is another example of where the devicetree would be a much sensible solution. Otherwise every vendor has to create string tables in the code. We have two vendors using the same SoC and they have to have different drivers...it is just going to be a mess...
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_VERSION:
str = priv->t4->version;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_SN:
str = priv->t4->sn;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_ASSET_TAG:
str = priv->t4->asset_tag;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_PN:
str = priv->t4->pn;
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);
switch (id) {
case SYSINFO_ID_SMBIOS_SYSTEM_WAKEUP:
*val = priv->t1->wakeup_type;
break;
case SYSINFO_ID_SMBIOS_BASEBOARD_FEATURE:
*val = priv->t2->feature.data;
break;
case SYSINFO_ID_SMBIOS_BASEBOARD_TYPE:
*val = priv->t2->type;
break;
case SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_NUM:
*val = priv->t2->objs_num;
break;
case SYSINFO_ID_SMBIOS_ENCLOSURE_TYPE:
*val = priv->t3->chassis_type;
break;
case SYSINFO_ID_SMBIOS_ENCLOSURE_BOOTUP:
*val = priv->t3->bootup_state;
break;
case SYSINFO_ID_SMBIOS_ENCLOSURE_POW:
*val = priv->t3->power_supply_state;
break;
case SYSINFO_ID_SMBIOS_ENCLOSURE_THERMAL:
*val = priv->t3->thermal_state;
break;
case SYSINFO_ID_SMBIOS_ENCLOSURE_SECURITY:
*val = priv->t3->security_status;
break;
case SYSINFO_ID_SMBIOS_ENCLOSURE_OEM:
*val = priv->t3->oem_defined;
break;
case SYSINFO_ID_SMBIOS_ENCLOSURE_HEIGHT:
*val = priv->t3->height;
break;
case SYSINFO_ID_SMBIOS_ENCLOSURE_POWCORE_NUM:
*val = priv->t3->number_of_power_cords;
break;
case SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_CNT:
*val = priv->t3->element_count;
break;
case SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_LEN:
*val = priv->t3->element_record_length;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_TYPE:
*val = priv->t4->type;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_VOLTAGE:
*val = priv->t4->voltage;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_EXT_CLOCK:
*val = priv->t4->ext_clock;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_MAX_SPEED:
*val = priv->t4->max_speed;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_CUR_SPEED:
*val = priv->t4->curr_speed;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_STATUS:
*val = priv->t4->status;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_UPGRADE:
*val = priv->t4->upgrade;
break;
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_THREAD_CNT:
*val = priv->t4->thread_count;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_CHARA:
*val = priv->t4->characteristics;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY2:
*val = priv->t4->family2;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT2:
*val = priv->t4->core_count2;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN2:
*val = priv->t4->core_enabled2;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT2:
*val = priv->t4->thread_count2;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_EN:
*val = priv->t4->thread_enabled;
break;
default:
break;
}
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_ENCLOSURE_ELEMENTS:
*buf = priv->t3->elements;
*size = priv->t3->elements_size;
break;
case SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_HANDLE:
*buf = priv->t2->objs;
*size = priv->t2->objs_size;
break;
case SYSINFO_ID_SMBIOS_PROCESSOR_ID:
*buf = (uchar *)priv->t4->id;
*size = sizeof(priv->t4->id);
break;
default:
break;
}
return 0;
+}
+static int sysinfo_plat_probe(struct udevice *dev) +{
struct sysinfo_plat_priv *priv = dev_get_priv(dev);
struct sysinfo_plat *plat = dev_get_plat(dev);
priv->t1 = &plat->sys;
priv->t2 = &plat->board;
priv->t3 = &plat->chassis;
if (!sysinfo_get_processor_info(plat->processor))
priv->t4 = plat->processor;
return 0;
+}
+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_plat) = {
.name = "sysinfo_smbios_plat",
.id = UCLASS_SYSINFO,
.ops = &sysinfo_smbios_ops,
.priv_auto = sizeof(struct sysinfo_plat_priv),
.probe = sysinfo_plat_probe,
+}; diff --git a/drivers/sysinfo/smbios_plat.h b/drivers/sysinfo/smbios_plat.h new file mode 100644 index 00000000000..3576f492ecb --- /dev/null +++ b/drivers/sysinfo/smbios_plat.h @@ -0,0 +1,104 @@ +/* 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>
+/*
- TODO:
- sysinfo_plat and all sub data structure should be moved to <asm/sysinfo.h>
- if we have this defined for each arch.
- */
+struct __packed sys_info {
char *manufacturer;
char *prod_name;
char *version;
char *sn;
u8 wakeup_type;
char *sku_num;
char *family;
+};
+struct __packed baseboard_info {
char *manufacturer;
char *prod_name;
char *version;
char *sn;
char *asset_tag;
union baseboard_feat feature;
char *chassis_locat;
u8 type;
u8 objs_num;
void *objs;
size_t objs_size;
+};
+struct __packed enclosure_info {
char *manufacturer;
char *version;
char *sn;
char *asset_tag;
u8 chassis_type;
u8 bootup_state;
u8 power_supply_state;
u8 thermal_state;
u8 security_status;
u32 oem_defined;
u8 height;
u8 number_of_power_cords;
u8 element_count;
u8 element_record_length;
void *elements;
size_t elements_size;
char *sku_num;
+};
+struct __packed processor_info {
char *socket_design;
u8 type;
u8 family;
char *manufacturer;
u32 id[2];
char *version;
u8 voltage;
u16 ext_clock;
u16 max_speed;
u16 curr_speed;
u8 status;
u8 upgrade;
char *sn;
char *asset_tag;
char *pn;
u8 core_count;
u8 core_enabled;
u8 thread_count;
u16 characteristics;
u16 family2;
u16 core_count2;
u16 core_enabled2;
u16 thread_count2;
u16 thread_enabled;
+};
+struct sysinfo_plat {
struct sys_info sys;
struct baseboard_info board;
struct enclosure_info chassis;
struct processor_info *processor;
/* add other sysinfo structure here */
+};
+#if CONFIG_IS_ENABLED(SYSINFO_SMBIOS) +int sysinfo_get_processor_info(struct processor_info *pinfo); +#else +static inline int sysinfo_get_processor_info(struct processor_info *pinfo) +{
return -ENOSYS;
+} +#endif
+#endif /* __SMBIOS_PLAT_H */ diff --git a/include/smbios.h b/include/smbios.h index 00119d7a60c..60e28a89af8 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -154,6 +154,18 @@ struct __packed smbios_type1 { #define SMBIOS_BOARD_FEATURE_HOSTING (1 << 0) #define SMBIOS_BOARD_MOTHERBOARD 10
+union baseboard_feat {
struct {
u8 hosting_board:1;
u8 need_daughter_board:1;
u8 removable:1;
u8 replaceable:1;
u8 hot_swappable:1;
u8 rsvd:3;
} fields;
u8 data;
+};
struct __packed smbios_type2 { u8 type; u8 length; diff --git a/include/sysinfo.h b/include/sysinfo.h index 17b2b9c7111..6c9de7744c1 100644 --- a/include/sysinfo.h +++ b/include/sysinfo.h @@ -42,18 +42,74 @@ 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_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,
Just looking at the above suggests that this approach is not scalable.
/* For show_board_info() */ SYSINFO_ID_BOARD_MODEL,
diff --git a/lib/Makefile b/lib/Makefile index 81b503ab526..1829647e83d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -42,6 +42,8 @@ obj-$(CONFIG_FIT) += fdtdec_common.o obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o obj-$(CONFIG_GZIP_COMPRESSED) += gzip.o obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o +ccflags-$(CONFIG_SYSINFO_SMBIOS) += \
-I$(srctree)/drivers/sysinfo
obj-$(CONFIG_SMBIOS_PARSER) += smbios-parser.o obj-$(CONFIG_IMAGE_SPARSE) += image-sparse.o obj-y += initcall.o -- 2.25.1
Regards, SImon

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 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 like contained object handles, elements or processor id. 5. Refactor SMBIOS cmd print functions to match the command output with the specification 6. Add new print functions for Type 0, 3 and 4. 7. Miscellaneous fixes in SMBIOS.
Signed-off-by: Raymond Mao raymond.mao@linaro.org --- cmd/smbios.c | 268 +++++++++++++++++++++++++++++++++-- include/smbios.h | 116 +++++++++++---- lib/smbios.c | 358 ++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 632 insertions(+), 110 deletions(-)
diff --git a/cmd/smbios.c b/cmd/smbios.c index d3bd8b12a67..8e2bf46a09c 100644 --- a/cmd/smbios.c +++ b/cmd/smbios.c @@ -26,6 +26,71 @@ static const char * const wakeup_type_strings[] = { "AC Power Restored", /* 0x08 */ };
+static const char * const boardtype_strings[] = { + "Reserved", /* 0x00 */ + "Unknown", /* 0x01 */ + "Other", /* 0x02 */ + "Server Blade", /* 0x03 */ + "Connectivity Switch", /* 0x04 */ + "System Management Module", /* 0x05 */ + "Processor Module", /* 0x06 */ + "I/O Module", /* 0x07 */ + "Memory Module", /* 0x08 */ + "Daughter board", /* 0x09 */ + "Motherboard", /* 0x0a */ + "Processor/Memory Module", /* 0x0b */ + "Processor/IO Module", /* 0x0c */ + "Interconnect board", /* 0x0d */ +}; + +static const char * const chassis_state_strings[] = { + "Reserved", /* 0x00 */ + "Other", /* 0x01 */ + "Unknown", /* 0x02 */ + "Safe", /* 0x03 */ + "Warning", /* 0x04 */ + "Critical", /* 0x05 */ + "Non-recoverable", /* 0x06 */ +}; + +static const char * const chassis_security_strings[] = { + "Reserved", /* 0x00 */ + "Other", /* 0x01 */ + "Unknown", /* 0x02 */ + "None", /* 0x03 */ + "External interface locked out",/* 0x04 */ + "External interface enabled", /* 0x05 */ +}; + +static const char * const processor_type_strings[] = { + "Reserved", /* 0x00 */ + "Other", /* 0x01 */ + "Unknown", /* 0x02 */ + "Central Processor", /* 0x03 */ + "Math Processor", /* 0x04 */ + "DSP Processor", /* 0x05 */ + "Video Processor", /* 0x06 */ +}; + +static const char * const processor_family_strings[] = { + [0] = "Other", + [1] = "Unknown", + [2 ... 253] = "Other", /* skip these definitions from now */ + [254] = "Refer to 'Processor Family 2'", + [255] = "Reserved", + [256] = "ARMv7", + [257] = "ARMv8", +}; + +static const char * const processor_upgrade_strings[] = { + [0] = "Reserved", + [1] = "Other", + [2] = "Unknown", + [3 ... 5] = "Other", /* skip these definitions from now */ + [6] = "None", + [7 ... 80] = "Other", /* skip these definitions from now */ +}; + /** * smbios_get_string() - get SMBIOS string from table * @@ -92,6 +157,32 @@ const char *smbios_wakeup_type_str(u8 wakeup_type) return wakeup_type_strings[wakeup_type]; }
+static void smbios_print_type0(struct smbios_type0 *table) +{ + 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) { printf("System Information\n"); @@ -99,38 +190,180 @@ 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); } }
+const char *smbios_baseboard_type_str(u8 borad_type) +{ + if (borad_type >= ARRAY_SIZE(boardtype_strings)) + borad_type = 0; + return boardtype_strings[borad_type]; +} + 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]); + printf("\tBoard Type: %s\n", + smbios_baseboard_type_str(table->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"); }
+const char *smbios_chassis_state_str(u8 state) +{ + if (state >= ARRAY_SIZE(chassis_state_strings)) + state = 0; + return chassis_state_strings[state]; +} + +const char *smbios_chassis_security_str(u8 status) +{ + if (status >= ARRAY_SIZE(chassis_security_strings)) + status = 0; + return chassis_security_strings[status]; +} + +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); + + printf("\tBoot-up State: %s\n", + smbios_chassis_state_str(table->bootup_state)); + printf("\tPower Supply State: %s\n", + smbios_chassis_state_str(table->power_supply_state)); + printf("\tThermal State: %s\n", + smbios_chassis_state_str(table->thermal_state)); + printf("\tSecurity Status: %s\n", + smbios_chassis_security_str(table->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); +} + +const char *smbios_processor_type_str(u8 type) +{ + if (type >= ARRAY_SIZE(processor_type_strings)) + type = 0; + return processor_type_strings[type]; +} + +const char *smbios_processor_family_str(u16 family) +{ + if (family >= ARRAY_SIZE(processor_family_strings)) + family = 0; + + return processor_family_strings[family]; +} + +const char *smbios_processor_upgrade_str(u16 upgrade) +{ + if (upgrade >= ARRAY_SIZE(processor_upgrade_strings)) + upgrade = 0; + + return processor_upgrade_strings[upgrade]; +} + +static void smbios_print_type4(struct smbios_type4 *table) +{ + printf("Processor Information:\n"); + smbios_print_str("Socket Designation", table, table->socket_design); + printf("\tProcessor Type: %s\n", + smbios_processor_type_str(table->processor_type)); + printf("\tProcessor Family: %s\n", + smbios_processor_family_str(table->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); + printf("\tProcessor Upgrade: %s\n", + smbios_processor_upgrade_str(table->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); + printf("\tProcessor Family 2: %s\n", + smbios_processor_family_str(table->processor_family2)); + 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_type127(struct smbios_type127 *table) { printf("End Of Table\n"); @@ -192,13 +425,22 @@ 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_END_OF_TABLE: smbios_print_type127((struct smbios_type127 *)pos); break; default: diff --git a/include/smbios.h b/include/smbios.h index 60e28a89af8..f2269642268 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -80,19 +80,24 @@ struct __packed smbios3_entry { u64 struct_table_address; };
+struct __packed smbios_header { + u8 type; + u8 length; + u16 handle; +}; + /* 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) +#define BIOS_CHARACTERISTICS_PCI_SUPPORTED BIT(7) +#define BIOS_CHARACTERISTICS_UPGRADEABLE BIT(11) +#define BIOS_CHARACTERISTICS_SELECTABLE_BOOT BIT(16) + +#define BIOS_CHARACTERISTICS_EXT1_ACPI BIT(0) +#define BIOS_CHARACTERISTICS_EXT2_UEFI BIT(3) +#define BIOS_CHARACTERISTICS_EXT2_TARGET BIT(2)
struct __packed smbios_type0 { - u8 type; - u8 length; - u16 handle; + struct smbios_header hdr; u8 vendor; u8 bios_ver; u16 bios_start_segment; @@ -136,10 +141,12 @@ enum smbios_wakeup_type { 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,8 +158,19 @@ struct __packed smbios_type1 { char eos[SMBIOS_STRUCT_EOS_BYTES]; };
-#define SMBIOS_BOARD_FEATURE_HOSTING (1 << 0) +#define SMBIOS_BOARD_UNKNOWN 1 +#define SMBIOS_BOARD_OTHER 2 +#define SMBIOS_BOARD_SERVER_BLADE 3 +#define SMBIOS_BOARD_CON_SWITCH 4 +#define SMBIOS_BOARD_SM_MODULE 5 +#define SMBIOS_BOARD_PROCESSOR_MODULE 6 +#define SMBIOS_BOARD_IO_MODULE 7 +#define SMBIOS_BOARD_MEM_MODULE 8 +#define SMBIOS_BOARD_DAUGHTER_BOARD 9 #define SMBIOS_BOARD_MOTHERBOARD 10 +#define SMBIOS_BOARD_PROC_MEM_MODULE 11 +#define SMBIOS_BOARD_PROC_IO_MODULE 12 +#define SMBIOS_BOARD_INTERCON 13
union baseboard_feat { struct { @@ -167,9 +185,7 @@ union baseboard_feat { };
struct __packed smbios_type2 { - u8 type; - u8 length; - u16 handle; + struct smbios_header hdr; u8 manufacturer; u8 product_name; u8 version; @@ -180,17 +196,29 @@ 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]; };
#define SMBIOS_ENCLOSURE_DESKTOP 3 #define SMBIOS_STATE_SAFE 3 #define SMBIOS_SECURITY_NONE 3 +#define SMBIOS_ENCLOSURE_OEM_UND 0 +#define SMBIOS_ENCLOSURE_HEIGHT_UND 0 +#define SMBIOS_POWCORD_NUM_UND 0 +#define SMBIOS_ELEMENT_TYPE_SELECT BIT(7)
-struct __packed smbios_type3 { +struct __packed elem_hdr { u8 type; - u8 length; - u16 handle; + u8 minimum; /* 0 - 254 */ + u8 maximum; /* 1 - 255 */ +}; + +struct __packed smbios_type3 { + struct smbios_header hdr; u8 manufacturer; u8 chassis_type; u8 version; @@ -205,21 +233,52 @@ 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]; };
+#define SMBIOS_PROCESSOR_TYPE_OTHER 1 +#define SMBIOS_PROCESSOR_TYPE_UNKNOWN 2 #define SMBIOS_PROCESSOR_TYPE_CENTRAL 3 -#define SMBIOS_PROCESSOR_STATUS_ENABLED 1 +#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_NONE 6
#define SMBIOS_PROCESSOR_FAMILY_OTHER 1 #define SMBIOS_PROCESSOR_FAMILY_UNKNOWN 2 +#define SMBIOS_PROCESSOR_FAMILY_ARMV7 256 +#define SMBIOS_PROCESSOR_FAMILY_ARMV8 257 + +#define SMBIOS_PROCESSOR_FAMILY_EXT 0xfe + +/* Processor Characteristics */ +#define SMBIOS_PROCESSOR_RSVD BIT(0) +#define SMBIOS_PROCESSOR_UND BIT(1) +#define SMBIOS_PROCESSOR_64BIT BIT(2) +#define SMBIOS_PROCESSOR_MULTICORE BIT(3) +#define SMBIOS_PROCESSOR_HWTHREAD BIT(4) +#define SMBIOS_PROCESSOR_EXEC_PROT BIT(5) +#define SMBIOS_PROCESSOR_ENH_VIRT BIT(6) +#define SMBIOS_PROCESSOR_POW_CON BIT(7) +#define SMBIOS_PROCESSOR_128BIT BIT(8) +#define SMBIOS_PROCESSOR_ARM64_SOCID BIT(9)
struct __packed smbios_type4 { - u8 type; - u8 length; - u16 handle; - u8 socket_designation; + struct smbios_header hdr; + u8 socket_design; u8 processor_type; u8 processor_family; u8 processor_manufacturer; @@ -245,9 +304,12 @@ struct __packed smbios_type4 { u16 core_count2; u16 core_enabled2; u16 thread_count2; + u16 thread_enabled; char eos[SMBIOS_STRUCT_EOS_BYTES]; };
+#define SMBIOS_CACHE_HANDLE_NONE 0xffff + struct __packed smbios_type32 { u8 type; u8 length; @@ -264,12 +326,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/lib/smbios.c b/lib/smbios.c index 7c24ea129eb..8e481365165 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -8,6 +8,8 @@ #define LOG_CATEGORY LOGC_BOARD
#include <dm.h> +#include <dm/device-internal.h> +#include <dm/lists.h> #include <env.h> #include <linux/stringify.h> #include <linux/string.h> @@ -206,6 +208,26 @@ void get_str_from_dt(const struct map_sysinfo *nprop, char *str, size_t size) } }
+/** + * smbios_get_val_si() - Get value from sysinfo + * + * @ctx: context of SMBIOS + * @sysinfo_id: unique identifier for the value to be read + * Return: 0 if not found, else value from sysinfo + */ +static int smbios_get_val_si(struct smbios_ctx *ctx, int sysinfo_id) +{ + int val; + + if (!sysinfo_id || !ctx->dev) + return 0; + + if (!sysinfo_get_int(ctx->dev, sysinfo_id, &val)) + return val; + + return 0; +} + /** * smbios_add_prop_si() - Add a property from the devicetree or sysinfo * @@ -225,8 +247,7 @@ 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); + log_debug("smbios: %s, sysinfo id: %d\n", prop, sysinfo_id);
if (sysinfo_id && ctx->dev) { char val[SMBIOS_STR_MAX]; @@ -235,6 +256,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 }; @@ -247,6 +271,8 @@ static int smbios_add_prop_si(struct smbios_ctx *ctx, const char *prop, } else { const struct map_sysinfo *nprop;
+ log_debug("no smbios node, try the entire DT\n"); + nprop = convert_sysinfo_to_dt(ctx->subnode_name, prop); get_str_from_dt(nprop, str_dt, sizeof(str_dt)); str = (const char *)str_dt; @@ -330,15 +356,18 @@ 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"); + 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 +376,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; @@ -374,7 +405,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,16 +416,18 @@ 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", - 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); @@ -403,19 +436,21 @@ 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, - 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, 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", 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,33 +461,80 @@ 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); + size_t obj_hdl_size = 0; + u8 *obj_hdl = NULL; + u8 *obj_addr, *eos_addr; + + if (!sysinfo_get_data(ctx->dev, SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_HANDLE, + &obj_hdl, &obj_hdl_size)) + len += obj_hdl_size; /* Add the dynamic part */
t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type2)); + memset(t, 0, len); + + /* Verify the contained object handles */ + t->number_contained_objects = + smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_NUM); + + if ((t->number_contained_objects * sizeof(u16) != obj_hdl_size) || + (!obj_hdl && (t->number_contained_objects || obj_hdl_size)) || + (obj_hdl && (!t->number_contained_objects || !obj_hdl_size))) { + /* + * Error with returning 0-length when any of below rules does + * not match: + * 1. Contained Object Handles length must be equal to (Object + * Handle Length * Object Number). + * 2. If no Contained Object Handles exist, Object Number must + * be 0, and versa vice. + */ + unmap_sysmem(t); + return 0; + } + fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, handle); + + obj_addr = (u8 *)t + offsetof(struct smbios_type2, eos); + /* eos is at the end of the structure */ + eos_addr = (u8 *)t + len - sizeof(t->eos); 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->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, 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, SYSINFO_ID_SMBIOS_BASEBOARD_TYPE); + + /* Get the objs from driver */ + if (obj_hdl) + memcpy(obj_addr, obj_hdl, obj_hdl_size);
- 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_FEATURE_HOSTING; - t->board_type = SMBIOS_BOARD_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,20 +545,94 @@ 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); + u8 *elem = NULL; + u8 *elem_addr, *eos_addr, *sku_num_addr; + size_t elem_size = 0; + + if (!sysinfo_get_data(ctx->dev, SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENTS, + &elem, &elem_size)) + len += elem_size; /* Add the dynamic part */
t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type3)); + memset(t, 0, len); + + /* Verify the contained elements */ + t->element_count = + smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_CNT); + + t->element_record_length = + smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_LEN); + + if ((elem_size != t->element_record_length * t->element_count) || + (!elem && (t->element_count || t->element_record_length || + elem_size)) || + (elem && (t->element_record_length < sizeof(struct elem_hdr) || + !elem_size))) { + /* + * Error with returning 0-length when any of below rules does + * not match: + * 1. Contained Elements length must be equal to (Element + * Record Length * Element Count). + * 2. If no Contained Elements exist, Element Count and Element + * Record Length must be 0. + * 3. If Contained Elements exist, Element Record Length must + * be at least the size of the Element Record Header. + */ + unmap_sysmem(t); + return 0; + } + 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; - - len = t->length + smbios_string_table_len(ctx); + + 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, + 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, + SYSINFO_ID_SMBIOS_ENCLOSURE_BOOTUP); + t->power_supply_state = + smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_ENCLOSURE_POW); + t->thermal_state = + smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_ENCLOSURE_THERMAL); + t->security_status = + smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_ENCLOSURE_SECURITY); + t->oem_defined = smbios_get_val_si(ctx, + SYSINFO_ID_SMBIOS_ENCLOSURE_OEM); + t->height = smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_ENCLOSURE_HEIGHT); + t->number_of_power_cords = + smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_ENCLOSURE_POWCORE_NUM); + + /* Get the elements from driver */ + if (elem) + memcpy(elem_addr, elem, elem_size); + + *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; unmap_sysmem(t);
@@ -489,6 +645,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]; @@ -511,31 +669,97 @@ static void smbios_write_type4_dm(struct smbios_type4 *t, } #endif
- t->processor_family = 0xfe; + if (processor_family == SMBIOS_PROCESSOR_FAMILY_UNKNOWN) + processor_family = + smbios_get_val_si(ctx, + SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY2); + + t->processor_family = SMBIOS_PROCESSOR_FAMILY_EXT; t->processor_family2 = processor_family; - t->processor_manufacturer = smbios_add_prop(ctx, NULL, vendor); - t->processor_version = smbios_add_prop(ctx, NULL, name); + + t->processor_manufacturer = + smbios_add_prop_si(ctx, NULL, + SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT, + vendor); + t->processor_version = + smbios_add_prop_si(ctx, NULL, + SYSINFO_ID_SMBIOS_PROCESSOR_VERSION, + name); + + if (t->processor_id[0] || t->processor_id[1]) + return; + + if (sysinfo_get_data(ctx->dev, SYSINFO_ID_SMBIOS_PROCESSOR_ID, + &id_data, &id_size) || + id_size != sizeof(t->processor_id)) + return; + if (id_data) + memcpy((u8 *)t->processor_id, id_data, id_size); + }
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; + t->socket_design = + smbios_add_prop_si(ctx, NULL, + SYSINFO_ID_SMBIOS_PROCESSOR_SOCKET, + NULL); + t->processor_type = + smbios_get_val_si(ctx, 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;
- len = t->length + smbios_string_table_len(ctx); + t->voltage = + smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_VOLTAGE); + t->external_clock = + smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_EXT_CLOCK); + t->max_speed = + smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_MAX_SPEED); + t->current_speed = + smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_CUR_SPEED); + t->status = + smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_STATUS); + t->processor_upgrade = + smbios_get_val_si(ctx, 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; + + t->serial_number = smbios_add_prop_si(ctx, NULL, + SYSINFO_ID_SMBIOS_PROCESSOR_SN, + NULL); + t->asset_tag = smbios_add_prop_si(ctx, NULL, + SYSINFO_ID_SMBIOS_PROCESSOR_ASSET_TAG, + NULL); + t->part_number = smbios_add_prop_si(ctx, NULL, + SYSINFO_ID_SMBIOS_PROCESSOR_PN, + NULL); + t->core_count = + smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT); + t->core_enabled = + smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN); + t->thread_count = + smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT); + t->processor_characteristics = + smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_CHARA); + t->core_count2 = + smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT2); + t->core_enabled2 = + smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN2); + t->thread_count2 = + smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT2); + t->thread_enabled = + smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_EN); + + len = t->hdr.length + smbios_string_table_len(ctx); *current += len; unmap_sysmem(t);
@@ -546,10 +770,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 +787,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; @@ -598,7 +822,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;

On 8/16/24 17:46, Raymond Mao 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 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 like contained object handles, elements or processor id.
- Refactor SMBIOS cmd print functions to match the command output with the specification
- Add new print functions for Type 0, 3 and 4.
- Miscellaneous fixes in SMBIOS.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
cmd/smbios.c | 268 +++++++++++++++++++++++++++++++++-- include/smbios.h | 116 +++++++++++---- lib/smbios.c | 358 ++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 632 insertions(+), 110 deletions(-)
diff --git a/cmd/smbios.c b/cmd/smbios.c index d3bd8b12a67..8e2bf46a09c 100644 --- a/cmd/smbios.c +++ b/cmd/smbios.c @@ -26,6 +26,71 @@ static const char * const wakeup_type_strings[] = { "AC Power Restored", /* 0x08 */ };
+static const char * const boardtype_strings[] = {
- "Reserved", /* 0x00 */
- "Unknown", /* 0x01 */
- "Other", /* 0x02 */
- "Server Blade", /* 0x03 */
- "Connectivity Switch", /* 0x04 */
- "System Management Module", /* 0x05 */
- "Processor Module", /* 0x06 */
- "I/O Module", /* 0x07 */
- "Memory Module", /* 0x08 */
- "Daughter board", /* 0x09 */
- "Motherboard", /* 0x0a */
- "Processor/Memory Module", /* 0x0b */
- "Processor/IO Module", /* 0x0c */
- "Interconnect board", /* 0x0d */
+};
+static const char * const chassis_state_strings[] = {
- "Reserved", /* 0x00 */
- "Other", /* 0x01 */
- "Unknown", /* 0x02 */
- "Safe", /* 0x03 */
- "Warning", /* 0x04 */
- "Critical", /* 0x05 */
- "Non-recoverable", /* 0x06 */
+};
+static const char * const chassis_security_strings[] = {
- "Reserved", /* 0x00 */
- "Other", /* 0x01 */
- "Unknown", /* 0x02 */
- "None", /* 0x03 */
- "External interface locked out",/* 0x04 */
- "External interface enabled", /* 0x05 */
+};
+static const char * const processor_type_strings[] = {
- "Reserved", /* 0x00 */
- "Other", /* 0x01 */
- "Unknown", /* 0x02 */
- "Central Processor", /* 0x03 */
- "Math Processor", /* 0x04 */
- "DSP Processor", /* 0x05 */
- "Video Processor", /* 0x06 */
+};
+static const char * const processor_family_strings[] = {
- [0] = "Other",
- [1] = "Unknown",
- [2 ... 253] = "Other", /* skip these definitions from now */
- [254] = "Refer to 'Processor Family 2'",
- [255] = "Reserved",
- [256] = "ARMv7",
- [257] = "ARMv8",
+};
+static const char * const processor_upgrade_strings[] = {
- [0] = "Reserved",
- [1] = "Other",
- [2] = "Unknown",
- [3 ... 5] = "Other", /* skip these definitions from now */
- [6] = "None",
- [7 ... 80] = "Other", /* skip these definitions from now */
+};
- /**
- smbios_get_string() - get SMBIOS string from table
@@ -92,6 +157,32 @@ const char *smbios_wakeup_type_str(u8 wakeup_type) return wakeup_type_strings[wakeup_type]; }
+static void smbios_print_type0(struct smbios_type0 *table) +{
- 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) { printf("System Information\n");
@@ -99,38 +190,180 @@ 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); } }
+const char *smbios_baseboard_type_str(u8 borad_type)
typo board_type
+{
- if (borad_type >= ARRAY_SIZE(boardtype_strings))
borad_type = 0;
newline but is 0 proper here? It means Reserved. Shouldn't be Unknown?
- return boardtype_strings[borad_type];
+}
- 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]);
- printf("\tBoard Type: %s\n",
smbios_baseboard_type_str(table->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"); }
+const char *smbios_chassis_state_str(u8 state) +{
- if (state >= ARRAY_SIZE(chassis_state_strings))
state = 0;
newline and same as above.
- return chassis_state_strings[state];
+}
+const char *smbios_chassis_security_str(u8 status) +{
- if (status >= ARRAY_SIZE(chassis_security_strings))
status = 0;
ditto.
M

On 16.08.24 17:46, Raymond Mao 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 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 like contained object handles, elements or processor id.
- Refactor SMBIOS cmd print functions to match the command output with the specification
- Add new print functions for Type 0, 3 and 4.
- Miscellaneous fixes in SMBIOS.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
cmd/smbios.c | 268 +++++++++++++++++++++++++++++++++-- include/smbios.h | 116 +++++++++++---- lib/smbios.c | 358 ++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 632 insertions(+), 110 deletions(-)
diff --git a/cmd/smbios.c b/cmd/smbios.c index d3bd8b12a67..8e2bf46a09c 100644 --- a/cmd/smbios.c +++ b/cmd/smbios.c @@ -26,6 +26,71 @@ static const char * const wakeup_type_strings[] = { "AC Power Restored", /* 0x08 */ };
+static const char * const boardtype_strings[] = {
- "Reserved", /* 0x00 */
0x00 is not in the spec. For all values that are not in the spec just print the hexadecimal number.
- "Unknown", /* 0x01 */
- "Other", /* 0x02 */
- "Server Blade", /* 0x03 */
- "Connectivity Switch", /* 0x04 */
- "System Management Module", /* 0x05 */
- "Processor Module", /* 0x06 */
- "I/O Module", /* 0x07 */
- "Memory Module", /* 0x08 */
- "Daughter board", /* 0x09 */
- "Motherboard", /* 0x0a */
- "Processor/Memory Module", /* 0x0b */
- "Processor/IO Module", /* 0x0c */
- "Interconnect board", /* 0x0d */
+};
+static const char * const chassis_state_strings[] = {
- "Reserved", /* 0x00 */
ditto
- "Other", /* 0x01 */
- "Unknown", /* 0x02 */
- "Safe", /* 0x03 */
- "Warning", /* 0x04 */
- "Critical", /* 0x05 */
- "Non-recoverable", /* 0x06 */
+};
+static const char * const chassis_security_strings[] = {
- "Reserved", /* 0x00 */
ditto
- "Other", /* 0x01 */
- "Unknown", /* 0x02 */
- "None", /* 0x03 */
- "External interface locked out",/* 0x04 */
- "External interface enabled", /* 0x05 */
+};
+static const char * const processor_type_strings[] = {
- "Reserved", /* 0x00 */
ditto
- "Other", /* 0x01 */
- "Unknown", /* 0x02 */
- "Central Processor", /* 0x03 */
- "Math Processor", /* 0x04 */
- "DSP Processor", /* 0x05 */
- "Video Processor", /* 0x06 */
+};
+static const char * const processor_family_strings[] = {
- [0] = "Other",
- [1] = "Unknown",
- [2 ... 253] = "Other", /* skip these definitions from now */
"Other" should only be used for 0x01. In all other cases print the hexadecimal number.
As we have hundreds of unused strings we should use a structure which contains only used values to reduce the structure size, e.g.
struct processor_family_str { u16 index; const char *str; };
const struct processor_family_str processor_family_strings;
- [254] = "Refer to 'Processor Family 2'",
This string should never be printed. Instead use the 'Processor Family 2' field to identify the family.
- [255] = "Reserved",
- [256] = "ARMv7",
- [257] = "ARMv8",
Please, add:
0x200 512 RISC-V RV32 0x201 513 RISC-V RV64
and the LoongArch values that we support.
Best regards
Heinrich
+};
+static const char * const processor_upgrade_strings[] = {
- [0] = "Reserved",
- [1] = "Other",
- [2] = "Unknown",
- [3 ... 5] = "Other", /* skip these definitions from now */
- [6] = "None",
- [7 ... 80] = "Other", /* skip these definitions from now */
+};
- /**
- smbios_get_string() - get SMBIOS string from table
@@ -92,6 +157,32 @@ const char *smbios_wakeup_type_str(u8 wakeup_type) return wakeup_type_strings[wakeup_type]; }
+static void smbios_print_type0(struct smbios_type0 *table) +{
- 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) { printf("System Information\n");
@@ -99,38 +190,180 @@ 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); } }
+const char *smbios_baseboard_type_str(u8 borad_type) +{
- if (borad_type >= ARRAY_SIZE(boardtype_strings))
borad_type = 0;
- return boardtype_strings[borad_type];
+}
- 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]);
- printf("\tBoard Type: %s\n",
smbios_baseboard_type_str(table->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"); }
+const char *smbios_chassis_state_str(u8 state) +{
- if (state >= ARRAY_SIZE(chassis_state_strings))
state = 0;
- return chassis_state_strings[state];
+}
+const char *smbios_chassis_security_str(u8 status) +{
- if (status >= ARRAY_SIZE(chassis_security_strings))
status = 0;
- return chassis_security_strings[status];
+}
+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);
- printf("\tBoot-up State: %s\n",
smbios_chassis_state_str(table->bootup_state));
- printf("\tPower Supply State: %s\n",
smbios_chassis_state_str(table->power_supply_state));
- printf("\tThermal State: %s\n",
smbios_chassis_state_str(table->thermal_state));
- printf("\tSecurity Status: %s\n",
smbios_chassis_security_str(table->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);
+}
+const char *smbios_processor_type_str(u8 type) +{
- if (type >= ARRAY_SIZE(processor_type_strings))
type = 0;
- return processor_type_strings[type];
+}
+const char *smbios_processor_family_str(u16 family) +{
- if (family >= ARRAY_SIZE(processor_family_strings))
family = 0;
- return processor_family_strings[family];
+}
+const char *smbios_processor_upgrade_str(u16 upgrade) +{
- if (upgrade >= ARRAY_SIZE(processor_upgrade_strings))
upgrade = 0;
- return processor_upgrade_strings[upgrade];
+}
+static void smbios_print_type4(struct smbios_type4 *table) +{
- printf("Processor Information:\n");
- smbios_print_str("Socket Designation", table, table->socket_design);
- printf("\tProcessor Type: %s\n",
smbios_processor_type_str(table->processor_type));
u16 family = table->processor_family; if (family == 0xfe) family = table->processor_family2;
For values above 0xfe we must evaluate the table->processor_family2 field.
Best regards
Heinrich
- printf("\tProcessor Family: %s\n",
smbios_processor_family_str(table->processor_family));
smbios_processor_family_str(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);
- printf("\tProcessor Upgrade: %s\n",
smbios_processor_upgrade_str(table->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);
- printf("\tProcessor Family 2: %s\n",
smbios_processor_family_str(table->processor_family2));
- 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_type127(struct smbios_type127 *table) { printf("End Of Table\n");
@@ -192,13 +425,22 @@ 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;
default:case SMBIOS_END_OF_TABLE: smbios_print_type127((struct smbios_type127 *)pos); break;
diff --git a/include/smbios.h b/include/smbios.h index 60e28a89af8..f2269642268 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -80,19 +80,24 @@ struct __packed smbios3_entry { u64 struct_table_address; };
+struct __packed smbios_header {
- u8 type;
- u8 length;
- u16 handle;
+};
- /* 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) +#define BIOS_CHARACTERISTICS_PCI_SUPPORTED BIT(7) +#define BIOS_CHARACTERISTICS_UPGRADEABLE BIT(11) +#define BIOS_CHARACTERISTICS_SELECTABLE_BOOT BIT(16)
+#define BIOS_CHARACTERISTICS_EXT1_ACPI BIT(0) +#define BIOS_CHARACTERISTICS_EXT2_UEFI BIT(3) +#define BIOS_CHARACTERISTICS_EXT2_TARGET BIT(2)
struct __packed smbios_type0 {
- u8 type;
- u8 length;
- u16 handle;
- struct smbios_header hdr; u8 vendor; u8 bios_ver; u16 bios_start_segment;
@@ -136,10 +141,12 @@ enum smbios_wakeup_type { 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,8 +158,19 @@ struct __packed smbios_type1 { char eos[SMBIOS_STRUCT_EOS_BYTES]; };
-#define SMBIOS_BOARD_FEATURE_HOSTING (1 << 0) +#define SMBIOS_BOARD_UNKNOWN 1 +#define SMBIOS_BOARD_OTHER 2 +#define SMBIOS_BOARD_SERVER_BLADE 3 +#define SMBIOS_BOARD_CON_SWITCH 4 +#define SMBIOS_BOARD_SM_MODULE 5 +#define SMBIOS_BOARD_PROCESSOR_MODULE 6 +#define SMBIOS_BOARD_IO_MODULE 7 +#define SMBIOS_BOARD_MEM_MODULE 8 +#define SMBIOS_BOARD_DAUGHTER_BOARD 9 #define SMBIOS_BOARD_MOTHERBOARD 10 +#define SMBIOS_BOARD_PROC_MEM_MODULE 11 +#define SMBIOS_BOARD_PROC_IO_MODULE 12 +#define SMBIOS_BOARD_INTERCON 13
union baseboard_feat { struct { @@ -167,9 +185,7 @@ union baseboard_feat { };
struct __packed smbios_type2 {
- u8 type;
- u8 length;
- u16 handle;
- struct smbios_header hdr; u8 manufacturer; u8 product_name; u8 version;
@@ -180,17 +196,29 @@ 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]; };
#define SMBIOS_ENCLOSURE_DESKTOP 3 #define SMBIOS_STATE_SAFE 3 #define SMBIOS_SECURITY_NONE 3
+#define SMBIOS_ENCLOSURE_OEM_UND 0 +#define SMBIOS_ENCLOSURE_HEIGHT_UND 0 +#define SMBIOS_POWCORD_NUM_UND 0 +#define SMBIOS_ELEMENT_TYPE_SELECT BIT(7)
-struct __packed smbios_type3 { +struct __packed elem_hdr { u8 type;
- u8 length;
- u16 handle;
- u8 minimum; /* 0 - 254 */
- u8 maximum; /* 1 - 255 */
+};
+struct __packed smbios_type3 {
- struct smbios_header hdr; u8 manufacturer; u8 chassis_type; u8 version;
@@ -205,21 +233,52 @@ 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]; };
+#define SMBIOS_PROCESSOR_TYPE_OTHER 1 +#define SMBIOS_PROCESSOR_TYPE_UNKNOWN 2 #define SMBIOS_PROCESSOR_TYPE_CENTRAL 3 -#define SMBIOS_PROCESSOR_STATUS_ENABLED 1 +#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_NONE 6
#define SMBIOS_PROCESSOR_FAMILY_OTHER 1 #define SMBIOS_PROCESSOR_FAMILY_UNKNOWN 2
+#define SMBIOS_PROCESSOR_FAMILY_ARMV7 256 +#define SMBIOS_PROCESSOR_FAMILY_ARMV8 257
+#define SMBIOS_PROCESSOR_FAMILY_EXT 0xfe
+/* Processor Characteristics */ +#define SMBIOS_PROCESSOR_RSVD BIT(0) +#define SMBIOS_PROCESSOR_UND BIT(1) +#define SMBIOS_PROCESSOR_64BIT BIT(2) +#define SMBIOS_PROCESSOR_MULTICORE BIT(3) +#define SMBIOS_PROCESSOR_HWTHREAD BIT(4) +#define SMBIOS_PROCESSOR_EXEC_PROT BIT(5) +#define SMBIOS_PROCESSOR_ENH_VIRT BIT(6) +#define SMBIOS_PROCESSOR_POW_CON BIT(7) +#define SMBIOS_PROCESSOR_128BIT BIT(8) +#define SMBIOS_PROCESSOR_ARM64_SOCID BIT(9)
struct __packed smbios_type4 {
- u8 type;
- u8 length;
- u16 handle;
- u8 socket_designation;
- struct smbios_header hdr;
- u8 socket_design; u8 processor_type; u8 processor_family; u8 processor_manufacturer;
@@ -245,9 +304,12 @@ struct __packed smbios_type4 { u16 core_count2; u16 core_enabled2; u16 thread_count2;
- u16 thread_enabled; char eos[SMBIOS_STRUCT_EOS_BYTES]; };
+#define SMBIOS_CACHE_HANDLE_NONE 0xffff
- struct __packed smbios_type32 { u8 type; u8 length;
@@ -264,12 +326,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/lib/smbios.c b/lib/smbios.c index 7c24ea129eb..8e481365165 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -8,6 +8,8 @@ #define LOG_CATEGORY LOGC_BOARD
#include <dm.h> +#include <dm/device-internal.h> +#include <dm/lists.h> #include <env.h> #include <linux/stringify.h> #include <linux/string.h> @@ -206,6 +208,26 @@ void get_str_from_dt(const struct map_sysinfo *nprop, char *str, size_t size) } }
+/**
- smbios_get_val_si() - Get value from sysinfo
- @ctx: context of SMBIOS
- @sysinfo_id: unique identifier for the value to be read
- Return: 0 if not found, else value from sysinfo
- */
+static int smbios_get_val_si(struct smbios_ctx *ctx, int sysinfo_id) +{
- int val;
- if (!sysinfo_id || !ctx->dev)
return 0;
- if (!sysinfo_get_int(ctx->dev, sysinfo_id, &val))
return val;
- return 0;
+}
- /**
- smbios_add_prop_si() - Add a property from the devicetree or sysinfo
@@ -225,8 +247,7 @@ 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);
log_debug("smbios: %s, sysinfo id: %d\n", prop, sysinfo_id);
if (sysinfo_id && ctx->dev) { char val[SMBIOS_STR_MAX];
@@ -235,6 +256,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 };
@@ -247,6 +271,8 @@ static int smbios_add_prop_si(struct smbios_ctx *ctx, const char *prop, } else { const struct map_sysinfo *nprop;
log_debug("no smbios node, try the entire DT\n");
nprop = convert_sysinfo_to_dt(ctx->subnode_name, prop); get_str_from_dt(nprop, str_dt, sizeof(str_dt)); str = (const char *)str_dt;
@@ -330,15 +356,18 @@ 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");
- 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,
if (t->bios_ver) gd->smbios_version = ctx->last_str; log_debug("smbios_version = %p: '%s'\n", gd->smbios_version,PLAIN_VERSION);
@@ -347,7 +376,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,
#ifdef CONFIG_ROM_SIZE if (CONFIG_ROM_SIZE < SZ_16M) { t->bios_rom_size = (CONFIG_ROM_SIZE / 65536) - 1;U_BOOT_DMI_DATE);
@@ -374,7 +405,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,16 +416,18 @@ 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",
SYSINFO_ID_SMBIOS_SYSTEM_MANUFACTURER,
NULL);
- t->manufacturer =
smbios_add_prop_si(ctx, "manufacturer",
SYSINFO_ID_SMBIOS_SYSTEM_MANUFACTURER,
t->product_name = smbios_add_prop_si(ctx, "product", SYSINFO_ID_SMBIOS_SYSTEM_PRODUCT, NULL);NULL);
@@ -403,19 +436,21 @@ 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));
} else {strlcpy((char *)t->uuid, serial_str, sizeof(t->uuid));
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 =
t->sku_number = smbios_add_prop_si(ctx, "sku", SYSINFO_ID_SMBIOS_SYSTEM_SKU, NULL); t->family = smbios_add_prop_si(ctx, "family", SYSINFO_ID_SMBIOS_SYSTEM_FAMILY, NULL);smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_SYSTEM_WAKEUP);
- len = t->length + smbios_string_table_len(ctx);
- len = t->hdr.length + smbios_string_table_len(ctx); *current += len; unmap_sysmem(t);
@@ -426,33 +461,80 @@ 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);
size_t obj_hdl_size = 0;
u8 *obj_hdl = NULL;
u8 *obj_addr, *eos_addr;
if (!sysinfo_get_data(ctx->dev, SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_HANDLE,
&obj_hdl, &obj_hdl_size))
len += obj_hdl_size; /* Add the dynamic part */
t = map_sysmem(*current, len);
- memset(t, 0, sizeof(struct smbios_type2));
- memset(t, 0, len);
- /* Verify the contained object handles */
- t->number_contained_objects =
smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_BASEBOARD_OBJS_NUM);
- if ((t->number_contained_objects * sizeof(u16) != obj_hdl_size) ||
(!obj_hdl && (t->number_contained_objects || obj_hdl_size)) ||
(obj_hdl && (!t->number_contained_objects || !obj_hdl_size))) {
/*
* Error with returning 0-length when any of below rules does
* not match:
* 1. Contained Object Handles length must be equal to (Object
* Handle Length * Object Number).
* 2. If no Contained Object Handles exist, Object Number must
* be 0, and versa vice.
*/
unmap_sysmem(t);
return 0;
- }
- fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, handle);
- obj_addr = (u8 *)t + offsetof(struct smbios_type2, eos);
- /* eos is at the end of the structure */
- eos_addr = (u8 *)t + len - sizeof(t->eos); 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->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, 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, SYSINFO_ID_SMBIOS_BASEBOARD_TYPE);
- /* Get the objs from driver */
- if (obj_hdl)
memcpy(obj_addr, obj_hdl, obj_hdl_size);
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_FEATURE_HOSTING;
t->board_type = SMBIOS_BOARD_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,20 +545,94 @@ 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);
u8 *elem = NULL;
u8 *elem_addr, *eos_addr, *sku_num_addr;
size_t elem_size = 0;
if (!sysinfo_get_data(ctx->dev, SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENTS,
&elem, &elem_size))
len += elem_size; /* Add the dynamic part */
t = map_sysmem(*current, len);
- memset(t, 0, sizeof(struct smbios_type3));
- memset(t, 0, len);
- /* Verify the contained elements */
- t->element_count =
smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_CNT);
- t->element_record_length =
smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_ENCLOSURE_ELEMENT_LEN);
- if ((elem_size != t->element_record_length * t->element_count) ||
(!elem && (t->element_count || t->element_record_length ||
elem_size)) ||
(elem && (t->element_record_length < sizeof(struct elem_hdr) ||
!elem_size))) {
/*
* Error with returning 0-length when any of below rules does
* not match:
* 1. Contained Elements length must be equal to (Element
* Record Length * Element Count).
* 2. If no Contained Elements exist, Element Count and Element
* Record Length must be 0.
* 3. If Contained Elements exist, Element Record Length must
* be at least the size of the Element Record Header.
*/
unmap_sysmem(t);
return 0;
- }
- 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;
- len = t->length + smbios_string_table_len(ctx);
- 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,
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,
SYSINFO_ID_SMBIOS_ENCLOSURE_BOOTUP);
- t->power_supply_state =
smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_ENCLOSURE_POW);
- t->thermal_state =
smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_ENCLOSURE_THERMAL);
- t->security_status =
smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_ENCLOSURE_SECURITY);
- t->oem_defined = smbios_get_val_si(ctx,
SYSINFO_ID_SMBIOS_ENCLOSURE_OEM);
- t->height = smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_ENCLOSURE_HEIGHT);
- t->number_of_power_cords =
smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_ENCLOSURE_POWCORE_NUM);
- /* Get the elements from driver */
- if (elem)
memcpy(elem_addr, elem, elem_size);
- *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; unmap_sysmem(t);
@@ -489,6 +645,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];
@@ -511,31 +669,97 @@ static void smbios_write_type4_dm(struct smbios_type4 *t, } #endif
- t->processor_family = 0xfe;
- if (processor_family == SMBIOS_PROCESSOR_FAMILY_UNKNOWN)
processor_family =
smbios_get_val_si(ctx,
SYSINFO_ID_SMBIOS_PROCESSOR_FAMILY2);
- t->processor_family = SMBIOS_PROCESSOR_FAMILY_EXT; t->processor_family2 = processor_family;
- t->processor_manufacturer = smbios_add_prop(ctx, NULL, vendor);
- t->processor_version = smbios_add_prop(ctx, NULL, name);
t->processor_manufacturer =
smbios_add_prop_si(ctx, NULL,
SYSINFO_ID_SMBIOS_PROCESSOR_MANUFACT,
vendor);
t->processor_version =
smbios_add_prop_si(ctx, NULL,
SYSINFO_ID_SMBIOS_PROCESSOR_VERSION,
name);
if (t->processor_id[0] || t->processor_id[1])
return;
if (sysinfo_get_data(ctx->dev, SYSINFO_ID_SMBIOS_PROCESSOR_ID,
&id_data, &id_size) ||
id_size != sizeof(t->processor_id))
return;
if (id_data)
memcpy((u8 *)t->processor_id, id_data, id_size);
}
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;
- t->socket_design =
smbios_add_prop_si(ctx, NULL,
SYSINFO_ID_SMBIOS_PROCESSOR_SOCKET,
NULL);
- t->processor_type =
smbios_write_type4_dm(t, ctx);smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_TYPE);
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;
len = t->length + smbios_string_table_len(ctx);
- t->voltage =
smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_VOLTAGE);
- t->external_clock =
smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_EXT_CLOCK);
- t->max_speed =
smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_MAX_SPEED);
- t->current_speed =
smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_CUR_SPEED);
- t->status =
smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_STATUS);
- t->processor_upgrade =
smbios_get_val_si(ctx, 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;
- t->serial_number = smbios_add_prop_si(ctx, NULL,
SYSINFO_ID_SMBIOS_PROCESSOR_SN,
NULL);
- t->asset_tag = smbios_add_prop_si(ctx, NULL,
SYSINFO_ID_SMBIOS_PROCESSOR_ASSET_TAG,
NULL);
- t->part_number = smbios_add_prop_si(ctx, NULL,
SYSINFO_ID_SMBIOS_PROCESSOR_PN,
NULL);
- t->core_count =
smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT);
- t->core_enabled =
smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN);
- t->thread_count =
smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT);
- t->processor_characteristics =
smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_CHARA);
- t->core_count2 =
smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_CORE_CNT2);
- t->core_enabled2 =
smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_CORE_EN2);
- t->thread_count2 =
smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_CNT2);
- t->thread_enabled =
smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_EN);
- len = t->hdr.length + smbios_string_table_len(ctx); *current += len; unmap_sysmem(t);
@@ -546,10 +770,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 +787,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;
@@ -598,7 +822,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;

During writing SMBIOS table, implementation of sysinfo detect function for a specific platform is not mandatory. Thus we should not return an error when platform sysinfo detect function does not exist.
Signed-off-by: Raymond Mao raymond.mao@linaro.org --- lib/smbios.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/lib/smbios.c b/lib/smbios.c index 8e481365165..2f1759d419e 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -825,10 +825,9 @@ ulong write_smbios_table(ulong addr) if (CONFIG_IS_ENABLED(SYSINFO)) { uclass_first_device(UCLASS_SYSINFO, &ctx.dev); if (ctx.dev) { - int ret; + int ret = sysinfo_detect(ctx.dev);
parent_node = dev_read_subnode(ctx.dev, "smbios"); - ret = sysinfo_detect(ctx.dev);
/* * ignore the error since many boards don't implement

On 8/16/24 17:46, Raymond Mao wrote:
During writing SMBIOS table, implementation of sysinfo detect function for a specific platform is not mandatory. Thus we should not return an error when platform sysinfo detect function does not exist.
first of all you should avoid we and use imperative mood.
Second what you are writing here is not matching what your change does.
Simon did a patch not to make it mandatory.
M
Signed-off-by: Raymond Mao raymond.mao@linaro.org
lib/smbios.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/lib/smbios.c b/lib/smbios.c index 8e481365165..2f1759d419e 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -825,10 +825,9 @@ ulong write_smbios_table(ulong addr) if (CONFIG_IS_ENABLED(SYSINFO)) { uclass_first_device(UCLASS_SYSINFO, &ctx.dev); if (ctx.dev) {
int ret;
int ret = sysinfo_detect(ctx.dev); parent_node = dev_read_subnode(ctx.dev, "smbios");
ret = sysinfo_detect(ctx.dev); /* * ignore the error since many boards don't implement

Add common sysinfo driver for armv8 platforms containing all necessary SMBIOS information (Type 1 to 4).
Signed-off-by: Raymond Mao raymond.mao@linaro.org --- arch/arm/cpu/armv8/Makefile | 5 + arch/arm/cpu/armv8/sysinfo.c | 203 +++++++++++++++++++++++++++++++++++ 2 files changed, 208 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..374f20d455d 100644 --- a/arch/arm/cpu/armv8/Makefile +++ b/arch/arm/cpu/armv8/Makefile @@ -45,3 +45,8 @@ 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 + +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_SYSINFO_SMBIOS) += sysinfo.o +ccflags-$(CONFIG_SYSINFO_SMBIOS) += -I$(srctree)/drivers/sysinfo +endif \ No newline at end of file diff --git a/arch/arm/cpu/armv8/sysinfo.c b/arch/arm/cpu/armv8/sysinfo.c new file mode 100644 index 00000000000..a8e17d654be --- /dev/null +++ b/arch/arm/cpu/armv8/sysinfo.c @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2024 Linaro Limited + * Author: Raymond Mao raymond.mao@linaro.org + */ +#include <dm.h> +#if CONFIG_IS_ENABLED(SYSINFO_SMBIOS) +#include <smbios_plat.h> +#endif +#include <stdio.h> +#include <sysinfo.h> + +#define ELEMENT_RECORD_DATA_LEN 8 +#define ELEMENT_RECORD_NUM 2 + +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 { + 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, +}; + +struct __packed enclosure_element_record { + struct elem_hdr hdr; + u8 data[ELEMENT_RECORD_DATA_LEN]; +}; + +struct processor_info processor_info_armv8; + +/* Default data for the enclosure contained elements */ +struct enclosure_element_record contained_elements[ELEMENT_RECORD_NUM] = { + { + .hdr.type = SMBIOS_BOARD_MOTHERBOARD, + .hdr.minimum = 0, + .hdr.maximum = 0xff, + .data = {0}, + }, + { + .hdr.type = SMBIOS_BOARD_MOTHERBOARD, + .hdr.minimum = 0, + .hdr.maximum = 0xff, + .data = {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)); + + log_debug("MIDR: 0x%016llx\n", midr.data); + log_debug("MPIDR: 0x%016llx\n", mpidr); + log_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; + } + log_debug("CPU part number: 0x%x\n", midr.fields.partnum); + log_debug("CPU revision: 0x%x\n", midr.fields.revision); + log_debug("CPU architecture: 0x%x\n", midr.fields.architecture); + log_debug("CPU variant: 0x%x\n", midr.fields.variant); + + pinfo->version = "Not Specified"; + + /* Extract number of cores */ + core_count = (mpidr >> 0) & 0xFF; + pinfo->core_count = core_count + 1; + log_debug("CPU Core Count: %d\n", pinfo->core_count); + + /* Other default processor information */ + pinfo->type = SMBIOS_PROCESSOR_TYPE_CENTRAL; + pinfo->status = SMBIOS_PROCESSOR_STATUS_ENABLED; + pinfo->upgrade = SMBIOS_PROCESSOR_UPGRADE_NONE; + pinfo->family2 = SMBIOS_PROCESSOR_FAMILY_ARMV8; + pinfo->socket_design = "Not Specified"; + pinfo->sn = "Not Specified"; + pinfo->asset_tag = "Not Specified"; + pinfo->pn = "Not Specified"; + 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; + + return 0; +} + +struct sysinfo_plat sysinfo_smbios_armv8 = { + /* System Information */ + .sys.manufacturer = "arm", + .sys.prod_name = "arm", + .sys.version = "armv8", + .sys.sn = "Not Specified", + .sys.wakeup_type = SMBIOS_WAKEUP_TYPE_UNKNOWN, + .sys.sku_num = "Not Specified", + .sys.family = "arm", + + /* Baseboard (or Module) Information */ + .board.manufacturer = "arm", + .board.prod_name = "arm", + .board.version = "armv8", + .board.sn = "Not Specified", + .board.asset_tag = "Not Specified", + .board.feature.fields.hosting_board = 1, /* host board */ + .board.chassis_locat = "Not Specified", + .board.type = SMBIOS_BOARD_MOTHERBOARD, + + /* System Enclosure or Chassis Information */ + .chassis.manufacturer = "arm", + .chassis.version = "armv8", + .chassis.sn = "Not Specified", + .chassis.asset_tag = "Not Specified", + .chassis.chassis_type = SMBIOS_ENCLOSURE_DESKTOP, + .chassis.bootup_state = SMBIOS_STATE_SAFE, + .chassis.power_supply_state = SMBIOS_STATE_SAFE, + .chassis.thermal_state = SMBIOS_STATE_SAFE, + .chassis.security_status = SMBIOS_SECURITY_NONE, + .chassis.oem_defined = SMBIOS_ENCLOSURE_OEM_UND, + .chassis.height = SMBIOS_ENCLOSURE_HEIGHT_UND, + .chassis.number_of_power_cords = SMBIOS_POWCORD_NUM_UND, + .chassis.element_count = ARRAY_SIZE(contained_elements), + .chassis.element_record_length = sizeof(contained_elements[0]), + .chassis.elements = &contained_elements[0], + .chassis.elements_size = sizeof(contained_elements), + .chassis.sku_num = "Not Specified", + + /* Processor Information */ + .processor = &processor_info_armv8, +}; + +U_BOOT_DRVINFO(sysinfo_smbios_plat) = { + .name = "sysinfo_smbios_plat", + .plat = &sysinfo_smbios_armv8, +};

Hi Raymond,
On 16/08/2024 17:46, Raymond Mao wrote:
Add common sysinfo driver for armv8 platforms containing all necessary SMBIOS information (Type 1 to 4).
Signed-off-by: Raymond Mao raymond.mao@linaro.org
arch/arm/cpu/armv8/Makefile | 5 + arch/arm/cpu/armv8/sysinfo.c | 203 +++++++++++++++++++++++++++++++++++ 2 files changed, 208 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..374f20d455d 100644 --- a/arch/arm/cpu/armv8/Makefile +++ b/arch/arm/cpu/armv8/Makefile @@ -45,3 +45,8 @@ 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
+ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_SYSINFO_SMBIOS) += sysinfo.o +ccflags-$(CONFIG_SYSINFO_SMBIOS) += -I$(srctree)/drivers/sysinfo +endif \ No newline at end of file diff --git a/arch/arm/cpu/armv8/sysinfo.c b/arch/arm/cpu/armv8/sysinfo.c new file mode 100644 index 00000000000..a8e17d654be --- /dev/null +++ b/arch/arm/cpu/armv8/sysinfo.c @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (c) 2024 Linaro Limited
- Author: Raymond Mao raymond.mao@linaro.org
- */
+#include <dm.h> +#if CONFIG_IS_ENABLED(SYSINFO_SMBIOS) +#include <smbios_plat.h> +#endif +#include <stdio.h> +#include <sysinfo.h>
+#define ELEMENT_RECORD_DATA_LEN 8 +#define ELEMENT_RECORD_NUM 2
+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 {
- 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,
+};
+struct __packed enclosure_element_record {
- struct elem_hdr hdr;
- u8 data[ELEMENT_RECORD_DATA_LEN];
+};
+struct processor_info processor_info_armv8;
+/* Default data for the enclosure contained elements */ +struct enclosure_element_record contained_elements[ELEMENT_RECORD_NUM] = {
- {
.hdr.type = SMBIOS_BOARD_MOTHERBOARD,
.hdr.minimum = 0,
.hdr.maximum = 0xff,
.data = {0},
- },
- {
.hdr.type = SMBIOS_BOARD_MOTHERBOARD,
.hdr.minimum = 0,
.hdr.maximum = 0xff,
.data = {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));
- log_debug("MIDR: 0x%016llx\n", midr.data);
Maybe an unreasonable request, but I think it would make more sense to use debug() here rather than log_debug() so as not to contribute to the logspam unless someone actually wants to log this file.
Or another option, maybe you could combined these prints into a single line?
Kind regards, Caleb
- log_debug("MPIDR: 0x%016llx\n", mpidr);
- log_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;
- }
- log_debug("CPU part number: 0x%x\n", midr.fields.partnum);
- log_debug("CPU revision: 0x%x\n", midr.fields.revision);
- log_debug("CPU architecture: 0x%x\n", midr.fields.architecture);
- log_debug("CPU variant: 0x%x\n", midr.fields.variant);
- pinfo->version = "Not Specified";
- /* Extract number of cores */
- core_count = (mpidr >> 0) & 0xFF;
- pinfo->core_count = core_count + 1;
- log_debug("CPU Core Count: %d\n", pinfo->core_count);
- /* Other default processor information */
- pinfo->type = SMBIOS_PROCESSOR_TYPE_CENTRAL;
- pinfo->status = SMBIOS_PROCESSOR_STATUS_ENABLED;
- pinfo->upgrade = SMBIOS_PROCESSOR_UPGRADE_NONE;
- pinfo->family2 = SMBIOS_PROCESSOR_FAMILY_ARMV8;
- pinfo->socket_design = "Not Specified";
- pinfo->sn = "Not Specified";
- pinfo->asset_tag = "Not Specified";
- pinfo->pn = "Not Specified";
- 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;
- return 0;
+}
+struct sysinfo_plat sysinfo_smbios_armv8 = {
- /* System Information */
- .sys.manufacturer = "arm",
- .sys.prod_name = "arm",
- .sys.version = "armv8",
- .sys.sn = "Not Specified",
- .sys.wakeup_type = SMBIOS_WAKEUP_TYPE_UNKNOWN,
- .sys.sku_num = "Not Specified",
- .sys.family = "arm",
- /* Baseboard (or Module) Information */
- .board.manufacturer = "arm",
- .board.prod_name = "arm",
- .board.version = "armv8",
- .board.sn = "Not Specified",
- .board.asset_tag = "Not Specified",
- .board.feature.fields.hosting_board = 1, /* host board */
- .board.chassis_locat = "Not Specified",
- .board.type = SMBIOS_BOARD_MOTHERBOARD,
- /* System Enclosure or Chassis Information */
- .chassis.manufacturer = "arm",
- .chassis.version = "armv8",
- .chassis.sn = "Not Specified",
- .chassis.asset_tag = "Not Specified",
- .chassis.chassis_type = SMBIOS_ENCLOSURE_DESKTOP,
- .chassis.bootup_state = SMBIOS_STATE_SAFE,
- .chassis.power_supply_state = SMBIOS_STATE_SAFE,
- .chassis.thermal_state = SMBIOS_STATE_SAFE,
- .chassis.security_status = SMBIOS_SECURITY_NONE,
- .chassis.oem_defined = SMBIOS_ENCLOSURE_OEM_UND,
- .chassis.height = SMBIOS_ENCLOSURE_HEIGHT_UND,
- .chassis.number_of_power_cords = SMBIOS_POWCORD_NUM_UND,
- .chassis.element_count = ARRAY_SIZE(contained_elements),
- .chassis.element_record_length = sizeof(contained_elements[0]),
- .chassis.elements = &contained_elements[0],
- .chassis.elements_size = sizeof(contained_elements),
- .chassis.sku_num = "Not Specified",
- /* Processor Information */
- .processor = &processor_info_armv8,
+};
+U_BOOT_DRVINFO(sysinfo_smbios_plat) = {
- .name = "sysinfo_smbios_plat",
- .plat = &sysinfo_smbios_armv8,
+};

On 8/16/24 17:46, Raymond Mao wrote:
Add common sysinfo driver for armv8 platforms containing all necessary SMBIOS information (Type 1 to 4).
Signed-off-by: Raymond Mao raymond.mao@linaro.org
arch/arm/cpu/armv8/Makefile | 5 + arch/arm/cpu/armv8/sysinfo.c | 203 +++++++++++++++++++++++++++++++++++ 2 files changed, 208 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..374f20d455d 100644 --- a/arch/arm/cpu/armv8/Makefile +++ b/arch/arm/cpu/armv8/Makefile @@ -45,3 +45,8 @@ 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
+ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_SYSINFO_SMBIOS) += sysinfo.o +ccflags-$(CONFIG_SYSINFO_SMBIOS) += -I$(srctree)/drivers/sysinfo
I think this should be moved to generic location to avoid line above.
+endif \ No newline at end of file
obviously wrong.
diff --git a/arch/arm/cpu/armv8/sysinfo.c b/arch/arm/cpu/armv8/sysinfo.c new file mode 100644 index 00000000000..a8e17d654be --- /dev/null +++ b/arch/arm/cpu/armv8/sysinfo.c @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (c) 2024 Linaro Limited
- Author: Raymond Mao raymond.mao@linaro.org
- */
+#include <dm.h> +#if CONFIG_IS_ENABLED(SYSINFO_SMBIOS) +#include <smbios_plat.h> +#endif
This also look weird.
M

Add sysinfo interface and data structures for cache information required by SMBIOS type 7.
Signed-off-by: Raymond Mao raymond.mao@linaro.org --- drivers/sysinfo/smbios_plat.c | 172 ++++++++++++++++++++++++++++++++++ drivers/sysinfo/smbios_plat.h | 27 ++++++ include/smbios.h | 112 ++++++++++++++++++++++ include/sysinfo.h | 36 +++++++ 4 files changed, 347 insertions(+)
diff --git a/drivers/sysinfo/smbios_plat.c b/drivers/sysinfo/smbios_plat.c index adbc8cf3cf2..e225b42d672 100644 --- a/drivers/sysinfo/smbios_plat.c +++ b/drivers/sysinfo/smbios_plat.c @@ -12,14 +12,60 @@ struct sysinfo_plat_priv { struct baseboard_info *t2; struct enclosure_info *t3; struct processor_info *t4; + struct smbios_type7 t7[SYSINFO_CACHE_LVL_MAX]; + char *cache_socket_design[SYSINFO_CACHE_LVL_MAX]; + u16 cache_handles[SYSINFO_CACHE_LVL_MAX]; + u8 cache_level; + /* + * TODO: add other types here: + * Type 9 - System Slots + * Type 16 - Physical Memory Array + * Type 17 - Memory Device + * Type 19 - Memory Array Mapped Address + */ };
+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.fields.locate = SMBIOS_CACHE_LOCATE_UNKNOWN; + ci->config.fields.opmode = 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; @@ -30,6 +76,22 @@ static int sysinfo_plat_get_str(struct udevice *dev, int id, { struct sysinfo_plat_priv *priv = dev_get_priv(dev); const char *str = NULL; + 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_SOCKET: + str = priv->cache_socket_design[i]; + break; + default: + break; + } + } + goto handle_str; + }
switch (id) { case SYSINFO_ID_SMBIOS_SYSTEM_MANUFACTURER: @@ -105,6 +167,7 @@ static int sysinfo_plat_get_str(struct udevice *dev, int id, break; }
+handle_str: if (!str) return -ENOSYS;
@@ -116,6 +179,52 @@ static int sysinfo_plat_get_str(struct udevice *dev, int id, 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_CONFIG: + *val = priv->t7[i].config.data; + break; + case SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE: + *val = priv->t7[i].max_size.data; + break; + case SYSINFO_ID_SMBIOS_CACHE_INST_SIZE: + *val = priv->t7[i].inst_size.data; + break; + case SYSINFO_ID_SMBIOS_CACHE_SUPSRAM_TYPE: + *val = priv->t7[i].supp_sram_type.data; + break; + case SYSINFO_ID_SMBIOS_CACHE_CURSRAM_TYPE: + *val = priv->t7[i].curr_sram_type.data; + break; + case SYSINFO_ID_SMBIOS_CACHE_SPEED: + *val = priv->t7[i].speed; + break; + case SYSINFO_ID_SMBIOS_CACHE_ERRCOR_TYPE: + *val = priv->t7[i].err_corr_type; + break; + case SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE: + *val = priv->t7[i].sys_cache_type; + break; + case SYSINFO_ID_SMBIOS_CACHE_ASSOC: + *val = priv->t7[i].associativity; + break; + case SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2: + *val = priv->t7[i].max_size2.data; + break; + case SYSINFO_ID_SMBIOS_CACHE_INST_SIZE2: + *val = priv->t7[i].inst_size2.data; + break; + default: + break; + } + } + return 0; + }
switch (id) { case SYSINFO_ID_SMBIOS_SYSTEM_WAKEUP: @@ -208,6 +317,11 @@ static int sysinfo_plat_get_int(struct udevice *dev, int id, int *val) case SYSINFO_ID_SMBIOS_PROCESSOR_THREAD_EN: *val = priv->t4->thread_enabled; break; + case SYSINFO_ID_SMBIOS_CACHE_LEVEL: + if (!priv->cache_level) /* No cache detected */ + return -ENOSYS; + *val = priv->cache_level - 1; + break; default: break; } @@ -233,6 +347,10 @@ static int sysinfo_plat_get_data(struct udevice *dev, int id, uchar **buf, *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: break; } @@ -243,6 +361,7 @@ static int sysinfo_plat_probe(struct udevice *dev) { struct sysinfo_plat_priv *priv = dev_get_priv(dev); struct sysinfo_plat *plat = dev_get_plat(dev); + u8 level;
priv->t1 = &plat->sys; priv->t2 = &plat->board; @@ -251,6 +370,59 @@ static int sysinfo_plat_probe(struct udevice *dev) 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 + */ + priv->t7[level].config.data = pcache->config.data; + priv->t7[level].supp_sram_type.data = + pcache->supp_sram_type.data; + priv->t7[level].curr_sram_type.data = + pcache->curr_sram_type.data; + priv->t7[level].speed = pcache->speed; + priv->t7[level].err_corr_type = pcache->err_corr_type; + 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; + } + priv->cache_socket_design[level] = pcache->socket_design; + smbios_cache_info_dump(&priv->t7[level]); + } + if (!level) /* no cache detected */ + return -ENOSYS; + + priv->cache_level = level; + return 0; }
diff --git a/drivers/sysinfo/smbios_plat.h b/drivers/sysinfo/smbios_plat.h index 3576f492ecb..8439feb9fc5 100644 --- a/drivers/sysinfo/smbios_plat.h +++ b/drivers/sysinfo/smbios_plat.h @@ -13,6 +13,20 @@ * sysinfo_plat and all sub data structure should be moved to <asm/sysinfo.h> * if we have this defined for each arch. */ +struct __packed cache_info { + char *socket_design; + union cache_config config; + u32 line_size; + u32 associativity; + u32 max_size; + u32 inst_size; + u8 cache_type; + union cache_sram_type supp_sram_type; + union cache_sram_type curr_sram_type; + u8 speed; + u8 err_corr_type; +}; + struct __packed sys_info { char *manufacturer; char *prod_name; @@ -89,12 +103,25 @@ struct sysinfo_plat { struct baseboard_info board; struct enclosure_info chassis; struct processor_info *processor; + struct cache_info *cache; /* add other sysinfo structure here */ };
#if CONFIG_IS_ENABLED(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; diff --git a/include/smbios.h b/include/smbios.h index f2269642268..267a672cefe 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -308,8 +308,120 @@ struct __packed smbios_type4 { char eos[SMBIOS_STRUCT_EOS_BYTES]; };
+/* Cache Information */ + +#define SMBIOS_CACHE_SIZE_EXT_KB (2047 * 1024) /* 2047 MiB */ #define SMBIOS_CACHE_HANDLE_NONE 0xffff
+#define SMBIOS_CACHE_SYSCACHE_TYPE_OTHER 1 +#define SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN 2 +#define SMBIOS_CACHE_SYSCACHE_TYPE_INSTRUCTION 3 +#define SMBIOS_CACHE_SYSCACHE_TYPE_DATA 4 +#define SMBIOS_CACHE_SYSCACHE_TYPE_UNIFIED 5 + +#define SMBIOS_CACHE_SPEED_UNKNOWN 0 + +#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 + +#define SMBIOS_CACHE_UNSOCKETED 0 +#define SMBIOS_CACHE_SOCKETED 1 + +#define SMBIOS_CACHE_LOCATE_INTERNAL 0 +#define SMBIOS_CACHE_LOCATE_EXTERNAL 1 +#define SMBIOS_CACHE_LOCATE_RESERVED 2 +#define SMBIOS_CACHE_LOCATE_UNKNOWN 3 + +#define SMBIOS_CACHE_DISABLED 0 +#define SMBIOS_CACHE_ENABLED 1 + +#define SMBIOS_CACHE_OP_WT 0 /* Write Through */ +#define SMBIOS_CACHE_OP_WB 1 /* Write Back */ +#define SMBIOS_CACHE_OP_VAR 2 /* Varies with Memory Address */ +#define SMBIOS_CACHE_OP_UND 3 /* Unknown*/ + +#define SMBIOS_CACHE_GRANU_1K 0 +#define SMBIOS_CACHE_GRANU_64K 1 + +#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 + +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/sysinfo.h b/include/sysinfo.h index 6c9de7744c1..708bfc17ea6 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, @@ -111,6 +113,40 @@ enum sysinfo_id { 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, SYSINFO_ID_BOARD_MANUFACTURER,

Add SMBIOS type 7 (cache information) write functions. Link cache handles from type 7 to type 4. Add SMBIOS command print functions for type 7.
Signed-off-by: Raymond Mao raymond.mao@linaro.org --- cmd/smbios.c | 82 +++++++++++++++++++++++++++++++++++++++ lib/smbios.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 185 insertions(+), 3 deletions(-)
diff --git a/cmd/smbios.c b/cmd/smbios.c index 8e2bf46a09c..38651740451 100644 --- a/cmd/smbios.c +++ b/cmd/smbios.c @@ -91,6 +91,43 @@ static const char * const processor_upgrade_strings[] = { [7 ... 80] = "Other", /* skip these definitions from now */ };
+static const char * const err_corr_type_strings[] = { + "Reserved", /* 0x00 */ + "Other", /* 0x01 */ + "Unknown", /* 0x02 */ + "None", /* 0x03 */ + "Parity", /* 0x04 */ + "Single-bit ECC", /* 0x05 */ + "Multi-bit ECC", /* 0x06 */ +}; + +static const char * const sys_cache_type_strings[] = { + "Reserved", /* 0x00 */ + "Other", /* 0x01 */ + "Unknown", /* 0x02 */ + "Instruction", /* 0x03 */ + "Data", /* 0x04 */ + "Unified", /* 0x05 */ +}; + +static const char * const associativity_strings[] = { + "Reserved", /* 0x00 */ + "Other", /* 0x01 */ + "Unknown", /* 0x02 */ + "Direct Mapped", /* 0x03 */ + "2-way Set-Associative", /* 0x04 */ + "4-way Set-Associative", /* 0x05 */ + "Fully Associative", /* 0x06 */ + "8-way Set-Associative", /* 0x07 */ + "16-way Set-Associative", /* 0x08 */ + "12-way Set-Associative", /* 0x09 */ + "24-way Set-Associative", /* 0x0a */ + "32-way Set-Associative", /* 0x0b */ + "48-way Set-Associative", /* 0x0c */ + "64-way Set-Associative", /* 0x0d */ + "20-way Set-Associative", /* 0x0e */ +}; + /** * smbios_get_string() - get SMBIOS string from table * @@ -364,6 +401,48 @@ static void smbios_print_type4(struct smbios_type4 *table) printf("\tThread Enabled: 0x%04x\n", table->thread_enabled); }
+const char *smbios_cache_err_corr_type_str(u8 err_corr_type) +{ + if (err_corr_type >= ARRAY_SIZE(err_corr_type_strings)) + err_corr_type = 0; + return err_corr_type_strings[err_corr_type]; +} + +const char *smbios_cache_sys_cache_type_str(u8 sys_cache_type) +{ + if (sys_cache_type >= ARRAY_SIZE(sys_cache_type_strings)) + sys_cache_type = 0; + return sys_cache_type_strings[sys_cache_type]; +} + +const char *smbios_cache_associativity_str(u8 associativity) +{ + if (associativity >= ARRAY_SIZE(associativity_strings)) + associativity = 0; + return associativity_strings[associativity]; +} + +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); + printf("\tError Correction Type: %s\n", + smbios_cache_err_corr_type_str(table->err_corr_type)); + printf("\tSystem Cache Type: %s\n", + smbios_cache_sys_cache_type_str(table->sys_cache_type)); + printf("\tAssociativity: %s\n", + smbios_cache_associativity_str(table->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"); @@ -440,6 +519,9 @@ static int do_smbios(struct cmd_tbl *cmdtp, int flag, int argc, 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; diff --git a/lib/smbios.c b/lib/smbios.c index 2f1759d419e..f5514661abe 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -703,6 +703,8 @@ 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); @@ -729,9 +731,25 @@ static int smbios_write_type4(ulong *current, int handle, t->processor_upgrade = smbios_get_val_si(ctx, 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; + + t->l1_cache_handle = *handle ? *handle : + SMBIOS_CACHE_HANDLE_NONE; + handle++; + t->l2_cache_handle = *handle ? *handle : + SMBIOS_CACHE_HANDLE_NONE; + handle++; + t->l3_cache_handle = *handle ? *handle : + SMBIOS_CACHE_HANDLE_NONE; + } else { + t->l1_cache_handle = SMBIOS_CACHE_HANDLE_NONE; + t->l2_cache_handle = SMBIOS_CACHE_HANDLE_NONE; + t->l3_cache_handle = SMBIOS_CACHE_HANDLE_NONE; + }
t->serial_number = smbios_add_prop_si(ctx, NULL, SYSINFO_ID_SMBIOS_PROCESSOR_SN, @@ -766,6 +784,86 @@ 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", + SYSINFO_ID_SMBIOS_CACHE_SOCKET + level, + NULL); + t->config.data = + smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_CACHE_CONFIG + level); + t->max_size.data = + smbios_get_val_si(ctx, + SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE + level); + t->inst_size.data = + smbios_get_val_si(ctx, + SYSINFO_ID_SMBIOS_CACHE_INST_SIZE + level); + t->supp_sram_type.data = + smbios_get_val_si(ctx, + SYSINFO_ID_SMBIOS_CACHE_SUPSRAM_TYPE + level); + t->curr_sram_type.data = + smbios_get_val_si(ctx, + SYSINFO_ID_SMBIOS_CACHE_CURSRAM_TYPE + level); + t->speed = smbios_get_val_si(ctx, + SYSINFO_ID_SMBIOS_CACHE_SPEED + level); + t->err_corr_type = + smbios_get_val_si(ctx, + SYSINFO_ID_SMBIOS_CACHE_ERRCOR_TYPE + level); + t->sys_cache_type = + smbios_get_val_si(ctx, + SYSINFO_ID_SMBIOS_CACHE_SCACHE_TYPE + level); + t->associativity = + smbios_get_val_si(ctx, + SYSINFO_ID_SMBIOS_CACHE_ASSOC + level); + t->max_size2.data = + smbios_get_val_si(ctx, + SYSINFO_ID_SMBIOS_CACHE_MAX_SIZE2 + level); + t->inst_size2.data = + smbios_get_val_si(ctx, + 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; + + /* Get the number of level */ + level = smbios_get_val_si(ctx, SYSINFO_ID_SMBIOS_CACHE_LEVEL); + if (level >= SYSINFO_CACHE_LVL_MAX) /* Error, return 0-length */ + return 0; + + for (i = 0; i <= level; i++) + len += smbios_write_type7_1level(current, handle++, ctx, i); + + return len; +} + static int smbios_write_type32(ulong *current, int handle, struct smbios_ctx *ctx) { @@ -805,6 +903,8 @@ 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", }, + /* Type 7 must ahead of type 4 to get cache handles. */ + { smbios_write_type7, }, { smbios_write_type4, }, { smbios_write_type32, }, { smbios_write_type127 },

Add cache information sysinfo driver containing necessary information required by SMBIOS type 7 for all armv8 platforms.
Signed-off-by: Raymond Mao raymond.mao@linaro.org --- arch/arm/cpu/armv8/sysinfo.c | 188 +++++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+)
diff --git a/arch/arm/cpu/armv8/sysinfo.c b/arch/arm/cpu/armv8/sysinfo.c index a8e17d654be..73e071212ae 100644 --- a/arch/arm/cpu/armv8/sysinfo.c +++ b/arch/arm/cpu/armv8/sysinfo.c @@ -13,6 +13,30 @@ #define ELEMENT_RECORD_DATA_LEN 8 #define ELEMENT_RECORD_NUM 2
+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; @@ -25,6 +49,28 @@ union midr_el1 { 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, @@ -47,6 +93,7 @@ struct __packed enclosure_element_record { u8 data[ELEMENT_RECORD_DATA_LEN]; };
+struct cache_info cache_info_armv8[SYSINFO_CACHE_LVL_MAX]; struct processor_info processor_info_armv8;
/* Default data for the enclosure contained elements */ @@ -65,6 +112,144 @@ struct enclosure_element_record contained_elements[ELEMENT_RECORD_NUM] = { }, };
+/* + * 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)); + log_debug("CLIDR_EL1: 0x%llx\n", clidr_el1); + + cache_type = (clidr_el1 >> (3 * level)) & 0x7; + log_debug("cache_type:%d\n", cache_type); + + 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_INSTRUCTION; + 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)); + log_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; + + log_debug("L%d Cache:\n", level + 1); + log_debug("Number of bytes in cache line:%u\n", cinfo->line_size); + log_debug("Associativity of cache:%u\n", cinfo->associativity); + log_debug("Number of sets in cache:%u\n", num_sets); + log_debug("Cache size in KB:%u\n", cinfo->max_size); + + cinfo->inst_size = cinfo->max_size; + + /* + * Below fields are set with default values for Arm arch, + * More information are hardware platform specific. + */ + cinfo->socket_design = "Not Specified"; + cinfo->config.fields.level = level; + /* Generally, "Not-Socketed" is for integrated caches */ + cinfo->config.fields.bsocketed = SMBIOS_CACHE_UNSOCKETED; + /* For modern SoCs, L1/L2 cache are usually internal */ + cinfo->config.fields.locate = SMBIOS_CACHE_LOCATE_INTERNAL; + cinfo->config.fields.benabled = SMBIOS_CACHE_ENABLED; + /* Generally, L1 and L2 caches are write-back */ + cinfo->config.fields.opmode = SMBIOS_CACHE_OP_WB; + + /* + * 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; @@ -195,6 +380,9 @@ struct sysinfo_plat sysinfo_smbios_armv8 = {
/* Processor Information */ .processor = &processor_info_armv8, + + /* Cache Information */ + .cache = &cache_info_armv8[0], };
U_BOOT_DRVINFO(sysinfo_smbios_plat) = {

Enable sysinfo smbios by default for Arm64. When SYSINFO_SMBIOS is enabled, disable QFW_SMBIOS.
Signed-off-by: Raymond Mao raymond.mao@linaro.org --- 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 7e166f43908..dac656f5c88 100644 --- a/configs/qemu_arm64_defconfig +++ b/configs/qemu_arm64_defconfig @@ -60,6 +60,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.

Update the expected test result to align with the smbios library changes.
Signed-off-by: Raymond Mao raymond.mao@linaro.org --- test/py/tests/test_smbios.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
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 Fri, Aug 16, 2024 at 08:46:53AM -0700, Raymond Mao wrote:
Update the expected test result to align with the smbios library changes.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
test/py/tests/test_smbios.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
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
This needs to be done with the change, not by itself.

Hi Tom,
On Mon, 19 Aug 2024 at 18:19, Tom Rini trini@konsulko.com wrote:
On Fri, Aug 16, 2024 at 08:46:53AM -0700, Raymond Mao wrote:
Update the expected test result to align with the smbios library changes.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
test/py/tests/test_smbios.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
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
This needs to be done with the change, not by itself.
Sorry but I didn't get what you mean... but shall I exclude this one from
the series?
Regards, Raymond

On Mon, Oct 21, 2024 at 11:23:05AM -0400, Raymond Mao wrote:
Hi Tom,
On Mon, 19 Aug 2024 at 18:19, Tom Rini trini@konsulko.com wrote:
On Fri, Aug 16, 2024 at 08:46:53AM -0700, Raymond Mao wrote:
Update the expected test result to align with the smbios library changes.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
test/py/tests/test_smbios.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
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
This needs to be done with the change, not by itself.
Sorry but I didn't get what you mean... but shall I exclude this one from the series?
What I mean is that the series should be bisect'able within the pytest framework too and not just build time. So the commit that breaks the test is where the test should be fixed.

Hi Raymond,
On Fri, 16 Aug 2024 at 09:47, Raymond Mao raymond.mao@linaro.org 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.
- Create a sysinfo driver to poppulate platform SMBIOS private data.
- Put device tree SMBIOS node as a fallback solution when SMBIOS data is missing from sysinfo driver.
- 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).
Raymond Mao (10): sysinfo: Add sysinfo API for accessing data area sysinfo: Add sysinfo driver and data structure for SMBIOS smbios: Refactor SMBIOS library smbios: ignore the non-existence of platform sysinfo detect armv8: Add arch-specific sysinfo driver sysinfo: Add sysinfo driver for SMBIOS type 7 smbios: Add support to SMBIOS type 7 armv8: Add sysinfo driver for cache information configs: Enable sysinfo for QEMU Arm64 tests: update smbios pytest
arch/arm/cpu/armv8/Makefile | 5 + arch/arm/cpu/armv8/sysinfo.c | 391 ++++++++++++++++++++++++++ cmd/smbios.c | 350 ++++++++++++++++++++++- configs/qemu_arm64_defconfig | 2 + drivers/misc/Kconfig | 2 +- drivers/sysinfo/Makefile | 1 + drivers/sysinfo/smbios_plat.c | 442 +++++++++++++++++++++++++++++ drivers/sysinfo/smbios_plat.h | 131 +++++++++ drivers/sysinfo/sysinfo-uclass.c | 20 ++ include/smbios.h | 240 ++++++++++++++-- include/sysinfo.h | 124 ++++++++- lib/Makefile | 2 + lib/smbios.c | 461 ++++++++++++++++++++++++++----- test/py/tests/test_smbios.py | 2 +- 14 files changed, 2058 insertions(+), 115 deletions(-) create mode 100644 arch/arm/cpu/armv8/sysinfo.c create mode 100644 drivers/sysinfo/smbios_plat.c create mode 100644 drivers/sysinfo/smbios_plat.h
-- 2.25.1
As a general comment, this is adding a load of code which is used by a lot of platforms. As more and more aarch64 platforms are created, this data grows. Why not use the devicetree for this hardware information? That is what it is for.
Some of the information detected makes sense, such as cache setup, but some of it seems like an approximation, or is missing, but suggests it is authoritative.
Regards, Simon

Hi Simon,
As a general comment, this is adding a load of code which is used by a lot of platforms. As more and more aarch64 platforms are created, this data grows. Why not use the devicetree for this hardware information? That is what it is for.
This data does not belong in devicetree, the various system registers exist to describe this information... Putting it in DT would be duplicating it.
Using DT for this would additionally require having bindings accepted upstream and for all SoCs to add them. To what end?
That being said, it would maybe be good to know what the size diff is with this series before getting into the weeds.
Some of the information detected makes sense, such as cache setup, but some of it seems like an approximation, or is missing, but suggests it is authoritative.
Could you give some examples?
Kind regards,
Regards, Simon

Hi Caleb,
On Mon, 19 Aug 2024 at 17:03, Caleb Connolly caleb.connolly@linaro.org wrote:
Hi Simon,
As a general comment, this is adding a load of code which is used by a lot of platforms. As more and more aarch64 platforms are created, this data grows. Why not use the devicetree for this hardware information? That is what it is for.
This data does not belong in devicetree, the various system registers exist to describe this information... Putting it in DT would be duplicating it.
I am not wanting to duplicate info which can be read from system registers.
Using DT for this would additionally require having bindings accepted upstream and for all SoCs to add them. To what end?
To get the correct information in there. How are boards supposed to add SMBIOS info? Do we end up creating a whole infra in U-Boot just for the driver to read it out? It just doesn't make any sense to me...
Let's put hardware info in the DT where it belongs.
That being said, it would maybe be good to know what the size diff is with this series before getting into the weeds.
Some of the information detected makes sense, such as cache setup, but some of it seems like an approximation, or is missing, but suggests it is authoritative.
Could you give some examples?
Here is an excerpt from the patch, you can see various things which are incorrect or too general.
.sys.manufacturer = "arm", + .sys.prod_name = "arm", + .sys.version = "armv8", + .sys.sn = "Not Specified", + .sys.wakeup_type = SMBIOS_WAKEUP_TYPE_UNKNOWN, + .sys.sku_num = "Not Specified", + .sys.family = "arm", + + /* Baseboard (or Module) Information */ + .board.manufacturer = "arm", + .board.prod_name = "arm", + .board.version = "armv8", + .board.sn = "Not Specified", + .board.asset_tag = "Not Specified", + .board.feature.fields.hosting_board = 1, /* host board */ + .board.chassis_locat = "Not Specified", + .board.type = SMBIOS_BOARD_MOTHERBOARD, + + /* System Enclosure or Chassis Information */ + .chassis.manufacturer = "arm", + .chassis.version = "armv8", + .chassis.sn = "Not Specified", + .chassis.asset_tag = "Not Specified", + .chassis.chassis_type = SMBIOS_ENCLOSURE_DESKTOP, + .chassis.bootup_state = SMBIOS_STATE_SAFE, + .chassis.power_supply_state = SMBIOS_STATE_SAFE, + .chassis.thermal_state = SMBIOS_STATE_SAFE, + .chassis.security_status = SMBIOS_SECURITY_NONE, + .chassis.oem_defined = SMBIOS_ENCLOSURE_OEM_UND, + .chassis.height = SMBIOS_ENCLOSURE_HEIGHT_UND, + .chassis.number_of_power_cords = SMBIOS_POWCORD_NUM_UND, + .chassis.element_count = ARRAY_SIZE(contained_elements), + .chassis.element_record_length = sizeof(contained_elements[0]), + .chassis.elements = &contained_elements[0], + .chassis.elements_size = sizeof(contained_elements), + .chassis.sku_num = "Not Specified",
Regards, Simon

On Mon, Aug 26, 2024 at 11:58:54AM -0600, Simon Glass wrote:
Hi Caleb,
On Mon, 19 Aug 2024 at 17:03, Caleb Connolly caleb.connolly@linaro.org wrote:
Hi Simon,
As a general comment, this is adding a load of code which is used by a lot of platforms. As more and more aarch64 platforms are created, this data grows. Why not use the devicetree for this hardware information? That is what it is for.
This data does not belong in devicetree, the various system registers exist to describe this information... Putting it in DT would be duplicating it.
I am not wanting to duplicate info which can be read from system registers.
Using DT for this would additionally require having bindings accepted upstream and for all SoCs to add them. To what end?
To get the correct information in there. How are boards supposed to add SMBIOS info? Do we end up creating a whole infra in U-Boot just for the driver to read it out? It just doesn't make any sense to me...
Let's put hardware info in the DT where it belongs.
I'm a little confused here because of some older threads on this overall topic. Part of the issue here is that in user space, "everyone" has SMBIOS-based tooling today, and wants to have that work, rather than inventing new tooling or modify existing tooling. And you were concerned I thought that we had tied SMBIOS too much to EFI being present when indeed it should be possible to pass the location along to the OS without EFI, but at the time Linux at least only supported that notion on MIPS I think?

On 8/26/24 20:23, Tom Rini wrote:
On Mon, Aug 26, 2024 at 11:58:54AM -0600, Simon Glass wrote:
Hi Caleb,
On Mon, 19 Aug 2024 at 17:03, Caleb Connolly caleb.connolly@linaro.org wrote:
Hi Simon,
As a general comment, this is adding a load of code which is used by a lot of platforms. As more and more aarch64 platforms are created, this data grows. Why not use the devicetree for this hardware information? That is what it is for.
This data does not belong in devicetree, the various system registers exist to describe this information... Putting it in DT would be duplicating it.
I am not wanting to duplicate info which can be read from system registers.
Using DT for this would additionally require having bindings accepted upstream and for all SoCs to add them. To what end?
To get the correct information in there. How are boards supposed to add SMBIOS info? Do we end up creating a whole infra in U-Boot just for the driver to read it out? It just doesn't make any sense to me...
Let's put hardware info in the DT where it belongs.
I'm a little confused here because of some older threads on this overall topic. Part of the issue here is that in user space, "everyone" has SMBIOS-based tooling today, and wants to have that work, rather than inventing new tooling or modify existing tooling. And you were concerned I thought that we had tied SMBIOS too much to EFI being present when indeed it should be possible to pass the location along to the OS without EFI, but at the time Linux at least only supported that notion on MIPS I think?
Looking at the Linux kernel code, only x86 can discover an SMBIOS table without EFI. We should not ride that dead horse.
Best regards
Heinrich

Hi Tom,
On Mon, 26 Aug 2024 at 12:23, Tom Rini trini@konsulko.com wrote:
On Mon, Aug 26, 2024 at 11:58:54AM -0600, Simon Glass wrote:
Hi Caleb,
On Mon, 19 Aug 2024 at 17:03, Caleb Connolly caleb.connolly@linaro.org wrote:
Hi Simon,
As a general comment, this is adding a load of code which is used by a lot of platforms. As more and more aarch64 platforms are created, this data grows. Why not use the devicetree for this hardware information? That is what it is for.
This data does not belong in devicetree, the various system registers exist to describe this information... Putting it in DT would be duplicating it.
I am not wanting to duplicate info which can be read from system registers.
Using DT for this would additionally require having bindings accepted upstream and for all SoCs to add them. To what end?
To get the correct information in there. How are boards supposed to add SMBIOS info? Do we end up creating a whole infra in U-Boot just for the driver to read it out? It just doesn't make any sense to me...
Let's put hardware info in the DT where it belongs.
I'm a little confused here because of some older threads on this overall topic. Part of the issue here is that in user space, "everyone" has SMBIOS-based tooling today, and wants to have that work, rather than inventing new tooling or modify existing tooling. And you were concerned I thought that we had tied SMBIOS too much to EFI being present when indeed it should be possible to pass the location along to the OS without EFI, but at the time Linux at least only supported that notion on MIPS I think?
That is a whole other concern I have, that we are perpetuating this legacy format which is a real pain to work with, when we already have devicetree. Let's leave that issue aside as I have not detected any interest in solving that problem, or even any agreement that it is a problem.
But for this particular series, I am just wanting to get the correct info in there. Having the CPU-detection code provide an opinion about what type of chassis is in use (just to take an example, the patch pieces I highlighted have been dropped from the email I am replying to) just seems a bit daft to me. Only the board vendor would know that info.
Regards, Simon

On Mon, Aug 26, 2024 at 01:12:16PM -0600, Simon Glass wrote:
Hi Tom,
On Mon, 26 Aug 2024 at 12:23, Tom Rini trini@konsulko.com wrote:
On Mon, Aug 26, 2024 at 11:58:54AM -0600, Simon Glass wrote:
Hi Caleb,
On Mon, 19 Aug 2024 at 17:03, Caleb Connolly caleb.connolly@linaro.org wrote:
Hi Simon,
As a general comment, this is adding a load of code which is used by a lot of platforms. As more and more aarch64 platforms are created, this data grows. Why not use the devicetree for this hardware information? That is what it is for.
This data does not belong in devicetree, the various system registers exist to describe this information... Putting it in DT would be duplicating it.
I am not wanting to duplicate info which can be read from system registers.
Using DT for this would additionally require having bindings accepted upstream and for all SoCs to add them. To what end?
To get the correct information in there. How are boards supposed to add SMBIOS info? Do we end up creating a whole infra in U-Boot just for the driver to read it out? It just doesn't make any sense to me...
Let's put hardware info in the DT where it belongs.
I'm a little confused here because of some older threads on this overall topic. Part of the issue here is that in user space, "everyone" has SMBIOS-based tooling today, and wants to have that work, rather than inventing new tooling or modify existing tooling. And you were concerned I thought that we had tied SMBIOS too much to EFI being present when indeed it should be possible to pass the location along to the OS without EFI, but at the time Linux at least only supported that notion on MIPS I think?
That is a whole other concern I have, that we are perpetuating this legacy format which is a real pain to work with, when we already have devicetree. Let's leave that issue aside as I have not detected any interest in solving that problem, or even any agreement that it is a problem.
OK, yes, lets set that aside.
But for this particular series, I am just wanting to get the correct info in there. Having the CPU-detection code provide an opinion about what type of chassis is in use (just to take an example, the patch pieces I highlighted have been dropped from the email I am replying to) just seems a bit daft to me. Only the board vendor would know that info.
Yes, I agree the detection should be reworked a good bit as some information will be board design specific while others SoC specific. And we should avoid adding many unused at run time strings to all platforms that enable this too (looking at all the CPU vendor related stuff).

On 8/26/24 21:59, Tom Rini wrote:
On Mon, Aug 26, 2024 at 01:12:16PM -0600, Simon Glass wrote:
Hi Tom,
On Mon, 26 Aug 2024 at 12:23, Tom Rini trini@konsulko.com wrote:
On Mon, Aug 26, 2024 at 11:58:54AM -0600, Simon Glass wrote:
Hi Caleb,
On Mon, 19 Aug 2024 at 17:03, Caleb Connolly caleb.connolly@linaro.org wrote:
Hi Simon,
As a general comment, this is adding a load of code which is used by a lot of platforms. As more and more aarch64 platforms are created, this data grows. Why not use the devicetree for this hardware information? That is what it is for.
This data does not belong in devicetree, the various system registers exist to describe this information... Putting it in DT would be duplicating it.
I am not wanting to duplicate info which can be read from system registers.
Using DT for this would additionally require having bindings accepted upstream and for all SoCs to add them. To what end?
To get the correct information in there. How are boards supposed to add SMBIOS info? Do we end up creating a whole infra in U-Boot just for the driver to read it out? It just doesn't make any sense to me...
Let's put hardware info in the DT where it belongs.
I'm a little confused here because of some older threads on this overall topic. Part of the issue here is that in user space, "everyone" has SMBIOS-based tooling today, and wants to have that work, rather than inventing new tooling or modify existing tooling. And you were concerned I thought that we had tied SMBIOS too much to EFI being present when indeed it should be possible to pass the location along to the OS without EFI, but at the time Linux at least only supported that notion on MIPS I think?
That is a whole other concern I have, that we are perpetuating this legacy format which is a real pain to work with, when we already have devicetree. Let's leave that issue aside as I have not detected any interest in solving that problem, or even any agreement that it is a problem.
OK, yes, lets set that aside.
But for this particular series, I am just wanting to get the correct info in there. Having the CPU-detection code provide an opinion about what type of chassis is in use (just to take an example, the patch pieces I highlighted have been dropped from the email I am replying to) just seems a bit daft to me. Only the board vendor would know that info.
Yes, I agree the detection should be reworked a good bit as some information will be board design specific while others SoC specific. And we should avoid adding many unused at run time strings to all platforms that enable this too (looking at all the CPU vendor related stuff).
I doubt on productive machines there will be much use of U-Boot's smbios command use. It is more a developer tool.
For reading all the details we currently have lib/efi_loader/smbiosdump.efi which can dump the SMBIOS table to a file that dmidecode can read.
Maybe instead of adding more and more decoding logic into the U-Boot smbios command we should add an smbios sub-command to dump to a file. This would be less of a hassle than running an EFI program for the same purpose.
Best regards
Heinrich

On Sun, Sep 15, 2024 at 07:57:19PM +0200, Heinrich Schuchardt wrote:
On 8/26/24 21:59, Tom Rini wrote:
On Mon, Aug 26, 2024 at 01:12:16PM -0600, Simon Glass wrote:
Hi Tom,
On Mon, 26 Aug 2024 at 12:23, Tom Rini trini@konsulko.com wrote:
On Mon, Aug 26, 2024 at 11:58:54AM -0600, Simon Glass wrote:
Hi Caleb,
On Mon, 19 Aug 2024 at 17:03, Caleb Connolly caleb.connolly@linaro.org wrote:
Hi Simon,
> As a general comment, this is adding a load of code which is used by a > lot of platforms. As more and more aarch64 platforms are created, this > data grows. Why not use the devicetree for this hardware information? > That is what it is for.
This data does not belong in devicetree, the various system registers exist to describe this information... Putting it in DT would be duplicating it.
I am not wanting to duplicate info which can be read from system registers.
Using DT for this would additionally require having bindings accepted upstream and for all SoCs to add them. To what end?
To get the correct information in there. How are boards supposed to add SMBIOS info? Do we end up creating a whole infra in U-Boot just for the driver to read it out? It just doesn't make any sense to me...
Let's put hardware info in the DT where it belongs.
I'm a little confused here because of some older threads on this overall topic. Part of the issue here is that in user space, "everyone" has SMBIOS-based tooling today, and wants to have that work, rather than inventing new tooling or modify existing tooling. And you were concerned I thought that we had tied SMBIOS too much to EFI being present when indeed it should be possible to pass the location along to the OS without EFI, but at the time Linux at least only supported that notion on MIPS I think?
That is a whole other concern I have, that we are perpetuating this legacy format which is a real pain to work with, when we already have devicetree. Let's leave that issue aside as I have not detected any interest in solving that problem, or even any agreement that it is a problem.
OK, yes, lets set that aside.
But for this particular series, I am just wanting to get the correct info in there. Having the CPU-detection code provide an opinion about what type of chassis is in use (just to take an example, the patch pieces I highlighted have been dropped from the email I am replying to) just seems a bit daft to me. Only the board vendor would know that info.
Yes, I agree the detection should be reworked a good bit as some information will be board design specific while others SoC specific. And we should avoid adding many unused at run time strings to all platforms that enable this too (looking at all the CPU vendor related stuff).
I doubt on productive machines there will be much use of U-Boot's smbios command use. It is more a developer tool.
For reading all the details we currently have lib/efi_loader/smbiosdump.efi which can dump the SMBIOS table to a file that dmidecode can read.
Maybe instead of adding more and more decoding logic into the U-Boot smbios command we should add an smbios sub-command to dump to a file. This would be less of a hassle than running an EFI program for the same purpose.
Sounds like a good idea to me.

Hi,
On Sun, 15 Sept 2024 at 20:28, Tom Rini trini@konsulko.com wrote:
On Sun, Sep 15, 2024 at 07:57:19PM +0200, Heinrich Schuchardt wrote:
On 8/26/24 21:59, Tom Rini wrote:
On Mon, Aug 26, 2024 at 01:12:16PM -0600, Simon Glass wrote:
Hi Tom,
On Mon, 26 Aug 2024 at 12:23, Tom Rini trini@konsulko.com wrote:
On Mon, Aug 26, 2024 at 11:58:54AM -0600, Simon Glass wrote:
Hi Caleb,
On Mon, 19 Aug 2024 at 17:03, Caleb Connolly caleb.connolly@linaro.org wrote: > > Hi Simon, > > > As a general comment, this is adding a load of code which is used by a > > lot of platforms. As more and more aarch64 platforms are created, this > > data grows. Why not use the devicetree for this hardware information? > > That is what it is for. > > This data does not belong in devicetree, the various system registers > exist to describe this information... Putting it in DT would be > duplicating it.
I am not wanting to duplicate info which can be read from system registers.
> > Using DT for this would additionally require having bindings accepted > upstream and for all SoCs to add them. To what end?
To get the correct information in there. How are boards supposed to add SMBIOS info? Do we end up creating a whole infra in U-Boot just for the driver to read it out? It just doesn't make any sense to me...
Let's put hardware info in the DT where it belongs.
I'm a little confused here because of some older threads on this overall topic. Part of the issue here is that in user space, "everyone" has SMBIOS-based tooling today, and wants to have that work, rather than inventing new tooling or modify existing tooling. And you were concerned I thought that we had tied SMBIOS too much to EFI being present when indeed it should be possible to pass the location along to the OS without EFI, but at the time Linux at least only supported that notion on MIPS I think?
That is a whole other concern I have, that we are perpetuating this legacy format which is a real pain to work with, when we already have devicetree. Let's leave that issue aside as I have not detected any interest in solving that problem, or even any agreement that it is a problem.
OK, yes, lets set that aside.
But for this particular series, I am just wanting to get the correct info in there. Having the CPU-detection code provide an opinion about what type of chassis is in use (just to take an example, the patch pieces I highlighted have been dropped from the email I am replying to) just seems a bit daft to me. Only the board vendor would know that info.
Yes, I agree the detection should be reworked a good bit as some information will be board design specific while others SoC specific. And we should avoid adding many unused at run time strings to all platforms that enable this too (looking at all the CPU vendor related stuff).
I doubt on productive machines there will be much use of U-Boot's smbios command use. It is more a developer tool.
Many commands fall into that category.
For reading all the details we currently have lib/efi_loader/smbiosdump.efi which can dump the SMBIOS table to a file that dmidecode can read.
Maybe instead of adding more and more decoding logic into the U-Boot smbios command we should add an smbios sub-command to dump to a file. This would be less of a hassle than running an EFI program for the same purpose.
Sounds like a good idea to me.
I would like to see this series land in U-Boot as I believe it is very helpful for seeing what the table looks like. Dumping to a file which then needs to be decoded is not as convenient. We may also find it easier to add tests for SMBIOS.
Regards, Simon

On Thu, Sep 19, 2024 at 04:13:02PM +0200, Simon Glass wrote:
Hi,
On Sun, 15 Sept 2024 at 20:28, Tom Rini trini@konsulko.com wrote:
On Sun, Sep 15, 2024 at 07:57:19PM +0200, Heinrich Schuchardt wrote:
On 8/26/24 21:59, Tom Rini wrote:
On Mon, Aug 26, 2024 at 01:12:16PM -0600, Simon Glass wrote:
Hi Tom,
On Mon, 26 Aug 2024 at 12:23, Tom Rini trini@konsulko.com wrote:
On Mon, Aug 26, 2024 at 11:58:54AM -0600, Simon Glass wrote: > Hi Caleb, > > On Mon, 19 Aug 2024 at 17:03, Caleb Connolly caleb.connolly@linaro.org wrote: > > > > Hi Simon, > > > > > As a general comment, this is adding a load of code which is used by a > > > lot of platforms. As more and more aarch64 platforms are created, this > > > data grows. Why not use the devicetree for this hardware information? > > > That is what it is for. > > > > This data does not belong in devicetree, the various system registers > > exist to describe this information... Putting it in DT would be > > duplicating it. > > I am not wanting to duplicate info which can be read from system registers. > > > > > Using DT for this would additionally require having bindings accepted > > upstream and for all SoCs to add them. To what end? > > To get the correct information in there. How are boards supposed to > add SMBIOS info? Do we end up creating a whole infra in U-Boot just > for the driver to read it out? It just doesn't make any sense to me... > > Let's put hardware info in the DT where it belongs.
I'm a little confused here because of some older threads on this overall topic. Part of the issue here is that in user space, "everyone" has SMBIOS-based tooling today, and wants to have that work, rather than inventing new tooling or modify existing tooling. And you were concerned I thought that we had tied SMBIOS too much to EFI being present when indeed it should be possible to pass the location along to the OS without EFI, but at the time Linux at least only supported that notion on MIPS I think?
That is a whole other concern I have, that we are perpetuating this legacy format which is a real pain to work with, when we already have devicetree. Let's leave that issue aside as I have not detected any interest in solving that problem, or even any agreement that it is a problem.
OK, yes, lets set that aside.
But for this particular series, I am just wanting to get the correct info in there. Having the CPU-detection code provide an opinion about what type of chassis is in use (just to take an example, the patch pieces I highlighted have been dropped from the email I am replying to) just seems a bit daft to me. Only the board vendor would know that info.
Yes, I agree the detection should be reworked a good bit as some information will be board design specific while others SoC specific. And we should avoid adding many unused at run time strings to all platforms that enable this too (looking at all the CPU vendor related stuff).
I doubt on productive machines there will be much use of U-Boot's smbios command use. It is more a developer tool.
Many commands fall into that category.
Yes, there is a trade-off to be made.
For reading all the details we currently have lib/efi_loader/smbiosdump.efi which can dump the SMBIOS table to a file that dmidecode can read.
Maybe instead of adding more and more decoding logic into the U-Boot smbios command we should add an smbios sub-command to dump to a file. This would be less of a hassle than running an EFI program for the same purpose.
Sounds like a good idea to me.
I would like to see this series land in U-Boot as I believe it is very helpful for seeing what the table looks like. Dumping to a file which then needs to be decoded is not as convenient. We may also find it easier to add tests for SMBIOS.
And I don't look forward to the seemingly inevitable parsing bug means CVE assigned. If the command is broadly enabled then "everyone" gets to worry about it, and if it's narrowly enabled have we really gotten better than the options of dump to file, parse elsewhere or load a parser and run it?

Hi Tom and Heinrich,
On Thu, 19 Sept 2024 at 13:48, Tom Rini trini@konsulko.com wrote:
On Thu, Sep 19, 2024 at 04:13:02PM +0200, Simon Glass wrote:
Hi,
On Sun, 15 Sept 2024 at 20:28, Tom Rini trini@konsulko.com wrote:
On Sun, Sep 15, 2024 at 07:57:19PM +0200, Heinrich Schuchardt wrote:
On 8/26/24 21:59, Tom Rini wrote:
On Mon, Aug 26, 2024 at 01:12:16PM -0600, Simon Glass wrote:
Hi Tom,
On Mon, 26 Aug 2024 at 12:23, Tom Rini trini@konsulko.com
wrote:
> > On Mon, Aug 26, 2024 at 11:58:54AM -0600, Simon Glass wrote: > > Hi Caleb, > > > > On Mon, 19 Aug 2024 at 17:03, Caleb Connolly <
caleb.connolly@linaro.org> wrote:
> > > > > > Hi Simon, > > > > > > > As a general comment, this is adding a load of code
which is used by a
> > > > lot of platforms. As more and more aarch64 platforms are
created, this
> > > > data grows. Why not use the devicetree for this hardware
information?
> > > > That is what it is for. > > > > > > This data does not belong in devicetree, the various
system registers
> > > exist to describe this information... Putting it in DT
would be
> > > duplicating it. > > > > I am not wanting to duplicate info which can be read from
system registers.
> > > > > > > > Using DT for this would additionally require having
bindings accepted
> > > upstream and for all SoCs to add them. To what end? > > > > To get the correct information in there. How are boards
supposed to
> > add SMBIOS info? Do we end up creating a whole infra in
U-Boot just
> > for the driver to read it out? It just doesn't make any
sense to me...
> > > > Let's put hardware info in the DT where it belongs. > > I'm a little confused here because of some older threads on
this overall
> topic. Part of the issue here is that in user space,
"everyone" has
> SMBIOS-based tooling today, and wants to have that work,
rather than
> inventing new tooling or modify existing tooling. And you were
concerned
> I thought that we had tied SMBIOS too much to EFI being
present when
> indeed it should be possible to pass the location along to the
OS
> without EFI, but at the time Linux at least only supported
that notion
> on MIPS I think?
That is a whole other concern I have, that we are perpetuating
this
legacy format which is a real pain to work with, when we already
have
devicetree. Let's leave that issue aside as I have not detected
any
interest in solving that problem, or even any agreement that it
is a
problem.
OK, yes, lets set that aside.
But for this particular series, I am just wanting to get the
correct
info in there. Having the CPU-detection code provide an opinion
about
what type of chassis is in use (just to take an example, the
patch
pieces I highlighted have been dropped from the email I am
replying
to) just seems a bit daft to me. Only the board vendor would
know that
info.
Yes, I agree the detection should be reworked a good bit as some information will be board design specific while others SoC
specific. And
we should avoid adding many unused at run time strings to all
platforms
that enable this too (looking at all the CPU vendor related stuff).
I doubt on productive machines there will be much use of U-Boot's
smbios
command use. It is more a developer tool.
Many commands fall into that category.
Yes, there is a trade-off to be made.
For reading all the details we currently have lib/efi_loader/smbiosdump.efi which can dump the SMBIOS table to a
file
that dmidecode can read.
Maybe instead of adding more and more decoding logic into the U-Boot smbios command we should add an smbios sub-command to dump to a file. This would be less of a hassle than running an EFI program for the
same
purpose.
Sounds like a good idea to me.
I would like to see this series land in U-Boot as I believe it is very helpful for seeing what the table looks like. Dumping to a file which then needs to be decoded is not as convenient. We may also find it easier to add tests for SMBIOS.
And I don't look forward to the seemingly inevitable parsing bug means CVE assigned. If the command is broadly enabled then "everyone" gets to worry about it, and if it's narrowly enabled have we really gotten better than the options of dump to file, parse elsewhere or load a parser and run it?
Currently the code for parsing the SMBIOS tables really helps debugging
before an external parser is ready for use. I think we can keep it until a dump tool is in the project, at that time we can just simply disable the CMD_SMBIOS config for the concern of code size.
Regards, Raymond

Hi Simon,
On Sat, 17 Aug 2024 at 11:58, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Fri, 16 Aug 2024 at 09:47, Raymond Mao raymond.mao@linaro.org 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. 3. Create a sysinfo driver to poppulate platform SMBIOS private data. 4. Put device tree SMBIOS node as a fallback solution when SMBIOS data is missing from sysinfo driver. 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).
Raymond Mao (10): sysinfo: Add sysinfo API for accessing data area sysinfo: Add sysinfo driver and data structure for SMBIOS smbios: Refactor SMBIOS library smbios: ignore the non-existence of platform sysinfo detect armv8: Add arch-specific sysinfo driver sysinfo: Add sysinfo driver for SMBIOS type 7 smbios: Add support to SMBIOS type 7 armv8: Add sysinfo driver for cache information configs: Enable sysinfo for QEMU Arm64 tests: update smbios pytest
arch/arm/cpu/armv8/Makefile | 5 + arch/arm/cpu/armv8/sysinfo.c | 391 ++++++++++++++++++++++++++ cmd/smbios.c | 350 ++++++++++++++++++++++- configs/qemu_arm64_defconfig | 2 + drivers/misc/Kconfig | 2 +- drivers/sysinfo/Makefile | 1 + drivers/sysinfo/smbios_plat.c | 442 +++++++++++++++++++++++++++++ drivers/sysinfo/smbios_plat.h | 131 +++++++++ drivers/sysinfo/sysinfo-uclass.c | 20 ++ include/smbios.h | 240 ++++++++++++++-- include/sysinfo.h | 124 ++++++++- lib/Makefile | 2 + lib/smbios.c | 461 ++++++++++++++++++++++++++----- test/py/tests/test_smbios.py | 2 +- 14 files changed, 2058 insertions(+), 115 deletions(-) create mode 100644 arch/arm/cpu/armv8/sysinfo.c create mode 100644 drivers/sysinfo/smbios_plat.c create mode 100644 drivers/sysinfo/smbios_plat.h
-- 2.25.1
As a general comment, this is adding a load of code which is used by a lot of platforms. As more and more aarch64 platforms are created, this data grows. Why not use the devicetree for this hardware information? That is what it is for.
Some of the information detected makes sense, such as cache setup, but some of it seems like an approximation, or is missing, but suggests it is authoritative.
The idea is that precise information can still come from dt (if the node
exists, but as a fact, not many platforms have it up to now). When it does not exist, system drivers provides the information as much as it can (some comes from registers, some comes from generic strings/enums). So it is not assumed that each vendor to add their code but just uses the arch-specific code in this series - if vendors want precise information they can still add into the dt.
Regards, Raymond

Hi Raymond,
On Tue, 3 Sept 2024 at 10:07, Raymond Mao raymond.mao@linaro.org wrote:
Hi Simon,
On Sat, 17 Aug 2024 at 11:58, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Fri, 16 Aug 2024 at 09:47, Raymond Mao raymond.mao@linaro.org 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.
- Create a sysinfo driver to poppulate platform SMBIOS private data.
- Put device tree SMBIOS node as a fallback solution when SMBIOS data is missing from sysinfo driver.
- 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).
Raymond Mao (10): sysinfo: Add sysinfo API for accessing data area sysinfo: Add sysinfo driver and data structure for SMBIOS smbios: Refactor SMBIOS library smbios: ignore the non-existence of platform sysinfo detect armv8: Add arch-specific sysinfo driver sysinfo: Add sysinfo driver for SMBIOS type 7 smbios: Add support to SMBIOS type 7 armv8: Add sysinfo driver for cache information configs: Enable sysinfo for QEMU Arm64 tests: update smbios pytest
arch/arm/cpu/armv8/Makefile | 5 + arch/arm/cpu/armv8/sysinfo.c | 391 ++++++++++++++++++++++++++ cmd/smbios.c | 350 ++++++++++++++++++++++- configs/qemu_arm64_defconfig | 2 + drivers/misc/Kconfig | 2 +- drivers/sysinfo/Makefile | 1 + drivers/sysinfo/smbios_plat.c | 442 +++++++++++++++++++++++++++++ drivers/sysinfo/smbios_plat.h | 131 +++++++++ drivers/sysinfo/sysinfo-uclass.c | 20 ++ include/smbios.h | 240 ++++++++++++++-- include/sysinfo.h | 124 ++++++++- lib/Makefile | 2 + lib/smbios.c | 461 ++++++++++++++++++++++++++----- test/py/tests/test_smbios.py | 2 +- 14 files changed, 2058 insertions(+), 115 deletions(-) create mode 100644 arch/arm/cpu/armv8/sysinfo.c create mode 100644 drivers/sysinfo/smbios_plat.c create mode 100644 drivers/sysinfo/smbios_plat.h
-- 2.25.1
As a general comment, this is adding a load of code which is used by a lot of platforms. As more and more aarch64 platforms are created, this data grows. Why not use the devicetree for this hardware information? That is what it is for.
Some of the information detected makes sense, such as cache setup, but some of it seems like an approximation, or is missing, but suggests it is authoritative.
The idea is that precise information can still come from dt (if the node exists, but as a fact, not many platforms have it up to now). When it does not exist, system drivers provides the information as much as it can (some comes from registers, some comes from generic strings/enums). So it is not assumed that each vendor to add their code but just uses the arch-specific code in this series - if vendors want precise information they can still add into the dt.
I fully understand what you are doing. I just don't think it is a great idea. We should have a clear boundary between:
1. things which are part of the hardware (although not explicitly in the devicetree) and can be probed 2. things which we can only guess at 3. grey area
I am very happy with 1). It is just 2) that I want to avoid.
The grey area is where your series adds lots of strings for different hardware...that just seems like code-size bloat to me.
How about working on a devicetree binding for this stuff? Or perhaps add the info to the boards you care about?
Regards, Simon

Hi Simon,
On Tue, 10 Sept 2024 at 14:44, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Tue, 3 Sept 2024 at 10:07, Raymond Mao raymond.mao@linaro.org wrote:
Hi Simon,
On Sat, 17 Aug 2024 at 11:58, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Fri, 16 Aug 2024 at 09:47, Raymond Mao raymond.mao@linaro.org
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. 3. Create a sysinfo driver to poppulate platform SMBIOS private data. 4. Put device tree SMBIOS node as a fallback solution when SMBIOS
data is
missing from sysinfo driver. 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).
Raymond Mao (10): sysinfo: Add sysinfo API for accessing data area sysinfo: Add sysinfo driver and data structure for SMBIOS smbios: Refactor SMBIOS library smbios: ignore the non-existence of platform sysinfo detect armv8: Add arch-specific sysinfo driver sysinfo: Add sysinfo driver for SMBIOS type 7 smbios: Add support to SMBIOS type 7 armv8: Add sysinfo driver for cache information configs: Enable sysinfo for QEMU Arm64 tests: update smbios pytest
arch/arm/cpu/armv8/Makefile | 5 + arch/arm/cpu/armv8/sysinfo.c | 391 ++++++++++++++++++++++++++ cmd/smbios.c | 350 ++++++++++++++++++++++- configs/qemu_arm64_defconfig | 2 + drivers/misc/Kconfig | 2 +- drivers/sysinfo/Makefile | 1 + drivers/sysinfo/smbios_plat.c | 442 +++++++++++++++++++++++++++++ drivers/sysinfo/smbios_plat.h | 131 +++++++++ drivers/sysinfo/sysinfo-uclass.c | 20 ++ include/smbios.h | 240 ++++++++++++++-- include/sysinfo.h | 124 ++++++++- lib/Makefile | 2 + lib/smbios.c | 461
++++++++++++++++++++++++++-----
test/py/tests/test_smbios.py | 2 +- 14 files changed, 2058 insertions(+), 115 deletions(-) create mode 100644 arch/arm/cpu/armv8/sysinfo.c create mode 100644 drivers/sysinfo/smbios_plat.c create mode 100644 drivers/sysinfo/smbios_plat.h
-- 2.25.1
As a general comment, this is adding a load of code which is used by a lot of platforms. As more and more aarch64 platforms are created, this data grows. Why not use the devicetree for this hardware information? That is what it is for.
Some of the information detected makes sense, such as cache setup, but some of it seems like an approximation, or is missing, but suggests it is authoritative.
The idea is that precise information can still come from dt (if the node
exists,
but as a fact, not many platforms have it up to now). When it does not exist, system drivers provides the information as much
as
it can (some comes from registers, some comes from generic
strings/enums).
So it is not assumed that each vendor to add their code but just uses the arch-specific code in this series - if vendors want precise information
they can
still add into the dt.
I fully understand what you are doing. I just don't think it is a great idea. We should have a clear boundary between:
- things which are part of the hardware (although not explicitly in
the devicetree) and can be probed 2. things which we can only guess at 3. grey area
I am very happy with 1). It is just 2) that I want to avoid.
The grey area is where your series adds lots of strings for different hardware...that just seems like code-size bloat to me.
How about working on a devicetree binding for this stuff? Or perhaps add the info to the boards you care about?
What I planned to do is to have a general one for arm64, then all the
arm64 boards missing the dt node can leverage it. Regarding to 2) you pointed out, maybe we can leave them to the dt later, my patch can go first with those architectural common stuffs, for example, cache information. I will think about it before posting the next version.
Regards, Raymond

Hi Raymond,
On Tue, 10 Sept 2024 at 13:20, Raymond Mao raymond.mao@linaro.org wrote:
Hi Simon,
On Tue, 10 Sept 2024 at 14:44, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Tue, 3 Sept 2024 at 10:07, Raymond Mao raymond.mao@linaro.org wrote:
Hi Simon,
On Sat, 17 Aug 2024 at 11:58, Simon Glass sjg@chromium.org wrote:
Hi Raymond,
On Fri, 16 Aug 2024 at 09:47, Raymond Mao raymond.mao@linaro.org 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.
- Create a sysinfo driver to poppulate platform SMBIOS private data.
- Put device tree SMBIOS node as a fallback solution when SMBIOS data is missing from sysinfo driver.
- 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).
Raymond Mao (10): sysinfo: Add sysinfo API for accessing data area sysinfo: Add sysinfo driver and data structure for SMBIOS smbios: Refactor SMBIOS library smbios: ignore the non-existence of platform sysinfo detect armv8: Add arch-specific sysinfo driver sysinfo: Add sysinfo driver for SMBIOS type 7 smbios: Add support to SMBIOS type 7 armv8: Add sysinfo driver for cache information configs: Enable sysinfo for QEMU Arm64 tests: update smbios pytest
arch/arm/cpu/armv8/Makefile | 5 + arch/arm/cpu/armv8/sysinfo.c | 391 ++++++++++++++++++++++++++ cmd/smbios.c | 350 ++++++++++++++++++++++- configs/qemu_arm64_defconfig | 2 + drivers/misc/Kconfig | 2 +- drivers/sysinfo/Makefile | 1 + drivers/sysinfo/smbios_plat.c | 442 +++++++++++++++++++++++++++++ drivers/sysinfo/smbios_plat.h | 131 +++++++++ drivers/sysinfo/sysinfo-uclass.c | 20 ++ include/smbios.h | 240 ++++++++++++++-- include/sysinfo.h | 124 ++++++++- lib/Makefile | 2 + lib/smbios.c | 461 ++++++++++++++++++++++++++----- test/py/tests/test_smbios.py | 2 +- 14 files changed, 2058 insertions(+), 115 deletions(-) create mode 100644 arch/arm/cpu/armv8/sysinfo.c create mode 100644 drivers/sysinfo/smbios_plat.c create mode 100644 drivers/sysinfo/smbios_plat.h
-- 2.25.1
As a general comment, this is adding a load of code which is used by a lot of platforms. As more and more aarch64 platforms are created, this data grows. Why not use the devicetree for this hardware information? That is what it is for.
Some of the information detected makes sense, such as cache setup, but some of it seems like an approximation, or is missing, but suggests it is authoritative.
The idea is that precise information can still come from dt (if the node exists, but as a fact, not many platforms have it up to now). When it does not exist, system drivers provides the information as much as it can (some comes from registers, some comes from generic strings/enums). So it is not assumed that each vendor to add their code but just uses the arch-specific code in this series - if vendors want precise information they can still add into the dt.
I fully understand what you are doing. I just don't think it is a great idea. We should have a clear boundary between:
- things which are part of the hardware (although not explicitly in
the devicetree) and can be probed 2. things which we can only guess at 3. grey area
I am very happy with 1). It is just 2) that I want to avoid.
The grey area is where your series adds lots of strings for different hardware...that just seems like code-size bloat to me.
How about working on a devicetree binding for this stuff? Or perhaps add the info to the boards you care about?
What I planned to do is to have a general one for arm64, then all the arm64 boards missing the dt node can leverage it. Regarding to 2) you pointed out, maybe we can leave them to the dt later, my patch can go first with those architectural common stuffs, for example, cache information. I will think about it before posting the next version.
OK. Let's try to avoid tables of strings.
Regards, Simon

Hi Raymond,
I haven't managed to root cause it yet, but this series seems to make the RB3 Gen 2 Qualcomm board hang during relocation.
How early post-relocation does any code here get called?
On 16/08/2024 17:46, 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.
- Create a sysinfo driver to poppulate platform SMBIOS private data.
- Put device tree SMBIOS node as a fallback solution when SMBIOS data is missing from sysinfo driver.
- 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).
Raymond Mao (10): sysinfo: Add sysinfo API for accessing data area sysinfo: Add sysinfo driver and data structure for SMBIOS smbios: Refactor SMBIOS library smbios: ignore the non-existence of platform sysinfo detect armv8: Add arch-specific sysinfo driver sysinfo: Add sysinfo driver for SMBIOS type 7 smbios: Add support to SMBIOS type 7 armv8: Add sysinfo driver for cache information configs: Enable sysinfo for QEMU Arm64 tests: update smbios pytest
arch/arm/cpu/armv8/Makefile | 5 + arch/arm/cpu/armv8/sysinfo.c | 391 ++++++++++++++++++++++++++ cmd/smbios.c | 350 ++++++++++++++++++++++- configs/qemu_arm64_defconfig | 2 + drivers/misc/Kconfig | 2 +- drivers/sysinfo/Makefile | 1 + drivers/sysinfo/smbios_plat.c | 442 +++++++++++++++++++++++++++++ drivers/sysinfo/smbios_plat.h | 131 +++++++++ drivers/sysinfo/sysinfo-uclass.c | 20 ++ include/smbios.h | 240 ++++++++++++++-- include/sysinfo.h | 124 ++++++++- lib/Makefile | 2 + lib/smbios.c | 461 ++++++++++++++++++++++++++----- test/py/tests/test_smbios.py | 2 +- 14 files changed, 2058 insertions(+), 115 deletions(-) create mode 100644 arch/arm/cpu/armv8/sysinfo.c create mode 100644 drivers/sysinfo/smbios_plat.c create mode 100644 drivers/sysinfo/smbios_plat.h

Hi Caleb,
On Mon, 19 Aug 2024 at 07:56, Caleb Connolly caleb.connolly@linaro.org wrote:
Hi Raymond,
I haven't managed to root cause it yet, but this series seems to make the RB3 Gen 2 Qualcomm board hang during relocation.
How early post-relocation does any code here get called?
Does it have permission to access MIDR_EL1, MPIDR_EL1 or CLIDR_EL1?
I don't have a Qualcomm board in hand but can you try if the hang still appears if we comment out the reg access lines in patch #5 and #8? I guess just about 3 lines.
[snip]
Regards, Raymond
participants (6)
-
Caleb Connolly
-
Heinrich Schuchardt
-
Michal Simek
-
Raymond Mao
-
Simon Glass
-
Tom Rini