[PATCH 02/10] sysinfo: Add sysinfo driver and data structure for SMBIOS

Michal Simek michal.simek at amd.com
Mon Aug 26 11:01:18 CEST 2024



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


More information about the U-Boot mailing list