summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/cpu/armv8/Makefile2
-rw-r--r--arch/arm/cpu/armv8/sysinfo.c292
-rw-r--r--arch/arm/dts/qemu-arm64.dts4
-rw-r--r--arch/arm/dts/smbios_generic.dtsi82
-rw-r--r--cmd/smbios.c348
-rw-r--r--configs/qemu_arm64_defconfig3
-rw-r--r--drivers/misc/Kconfig2
-rw-r--r--drivers/sysinfo/sandbox.c19
-rw-r--r--drivers/sysinfo/sandbox.h1
-rw-r--r--drivers/sysinfo/smbios.c228
-rw-r--r--drivers/sysinfo/sysinfo-uclass.c20
-rw-r--r--include/smbios.h158
-rw-r--r--include/smbios_def.h194
-rw-r--r--include/smbios_plat.h79
-rw-r--r--include/sysinfo.h125
-rw-r--r--lib/Kconfig6
-rw-r--r--lib/smbios.c445
-rw-r--r--test/dm/sysinfo.c6
-rw-r--r--test/py/tests/test_smbios.py18
19 files changed, 1863 insertions, 169 deletions
diff --git a/arch/arm/cpu/armv8/Makefile b/arch/arm/cpu/armv8/Makefile
index 2e71ff2dc97..b4126c61df1 100644
--- a/arch/arm/cpu/armv8/Makefile
+++ b/arch/arm/cpu/armv8/Makefile
@@ -46,3 +46,5 @@ obj-$(CONFIG_TARGET_BCMNS3) += bcmns3/
obj-$(CONFIG_XEN) += xen/
obj-$(CONFIG_ARMV8_CE_SHA1) += sha1_ce_glue.o sha1_ce_core.o
obj-$(CONFIG_ARMV8_CE_SHA256) += sha256_ce_glue.o sha256_ce_core.o
+
+obj-$(CONFIG_SYSINFO_SMBIOS) += sysinfo.o
diff --git a/arch/arm/cpu/armv8/sysinfo.c b/arch/arm/cpu/armv8/sysinfo.c
new file mode 100644
index 00000000000..850142da37d
--- /dev/null
+++ b/arch/arm/cpu/armv8/sysinfo.c
@@ -0,0 +1,292 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2024 Linaro Limited
+ * Author: Raymond Mao <raymond.mao@linaro.org>
+ */
+#include <dm.h>
+#include <smbios_plat.h>
+#include <stdio.h>
+#include <sysinfo.h>
+
+union ccsidr_el1 {
+ struct {
+ u64 linesize:3;
+ u64 associativity:10;
+ u64 numsets:15;
+ u64 unknown:4;
+ u64 reserved:32;
+ } no_ccidx;
+ struct {
+ u64 linesize:3;
+ u64 associativity:21;
+ u64 reserved1:8;
+ u64 numsets:24;
+ u64 reserved2:8;
+ } ccidx_aarch64;
+ struct {
+ u64 linesize:3;
+ u64 associativity:21;
+ u64 reserved:8;
+ u64 unallocated:32;
+ } ccidx_aarch32;
+ u64 data;
+};
+
+union midr_el1 {
+ struct {
+ u64 revision:4;
+ u64 partnum:12;
+ u64 architecture:4;
+ u64 variant:4;
+ u64 implementer:8;
+ u64 reserved:32;
+ } fields;
+ u64 data;
+};
+
+enum {
+ CACHE_NONE,
+ CACHE_INST_ONLY,
+ CACHE_DATA_ONLY,
+ CACHE_INST_WITH_DATA,
+ CACHE_UNIFIED,
+};
+
+enum {
+ CACHE_ASSOC_DIRECT_MAPPED = 1,
+ CACHE_ASSOC_2WAY = 2,
+ CACHE_ASSOC_4WAY = 4,
+ CACHE_ASSOC_8WAY = 8,
+ CACHE_ASSOC_16WAY = 16,
+ CACHE_ASSOC_12WAY = 12,
+ CACHE_ASSOC_24WAY = 24,
+ CACHE_ASSOC_32WAY = 32,
+ CACHE_ASSOC_48WAY = 48,
+ CACHE_ASSOC_64WAY = 64,
+ CACHE_ASSOC_20WAY = 20,
+};
+
+enum {
+ VENDOR_RESERVED = 0,
+ VENDOR_ARM = 0x41,
+ VENDOR_BROADCOM = 0x42,
+ VENDOR_CAVIUM = 0x43,
+ VENDOR_DEC = 0x44,
+ VENDOR_FUJITSU = 0x46,
+ VENDOR_INFINEON = 0x49,
+ VENDOR_FREESCALE = 0x4d,
+ VENDOR_NVIDIA = 0x4e,
+ VENDOR_AMCC = 0x50,
+ VENDOR_QUALCOMM = 0x51,
+ VENDOR_MARVELL = 0x56,
+ VENDOR_INTEL = 0x69,
+ VENDOR_AMPERE = 0xc0,
+};
+
+/*
+ * TODO:
+ * To support ARMv8.3, we need to read "CCIDX, bits [23:20]" from
+ * ID_AA64MMFR2_EL1 to get the format of CCSIDR_EL1:
+ *
+ * 0b0000 - 32-bit format implemented for all levels of the CCSIDR_EL1.
+ * 0b0001 - 64-bit format implemented for all levels of the CCSIDR_EL1.
+ *
+ * Here we assume to use CCSIDR_EL1 in no CCIDX layout:
+ * NumSets, bits [27:13]: (Number of sets in cache) - 1
+ * Associativity, bits [12:3]: (Associativity of cache) - 1
+ * LineSize, bits [2:0]: (Log2(Number of bytes in cache line)) - 4
+ */
+int sysinfo_get_cache_info(u8 level, struct cache_info *cinfo)
+{
+ u64 clidr_el1;
+ u32 csselr_el1;
+ u32 num_sets;
+ union ccsidr_el1 creg;
+ int cache_type;
+
+ sysinfo_cache_info_default(cinfo);
+
+ /* Read CLIDR_EL1 */
+ asm volatile("mrs %0, clidr_el1" : "=r" (clidr_el1));
+ debug("CLIDR_EL1: 0x%llx\n", clidr_el1);
+
+ cache_type = (clidr_el1 >> (3 * level)) & 0x7;
+ if (cache_type == CACHE_NONE) /* level does not exist */
+ return -1;
+
+ switch (cache_type) {
+ case CACHE_INST_ONLY:
+ cinfo->cache_type = SMBIOS_CACHE_SYSCACHE_TYPE_INST;
+ break;
+ case CACHE_DATA_ONLY:
+ cinfo->cache_type = SMBIOS_CACHE_SYSCACHE_TYPE_DATA;
+ break;
+ case CACHE_UNIFIED:
+ cinfo->cache_type = SMBIOS_CACHE_SYSCACHE_TYPE_UNIFIED;
+ break;
+ case CACHE_INST_WITH_DATA:
+ cinfo->cache_type = SMBIOS_CACHE_SYSCACHE_TYPE_OTHER;
+ break;
+ default:
+ cinfo->cache_type = SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN;
+ break;
+ }
+
+ /* Select cache level */
+ csselr_el1 = (level << 1);
+ asm volatile("msr csselr_el1, %0" : : "r" (csselr_el1));
+
+ /* Read CCSIDR_EL1 */
+ asm volatile("mrs %0, ccsidr_el1" : "=r" (creg.data));
+ debug("CCSIDR_EL1 (Level %d): 0x%llx\n", level + 1, creg.data);
+
+ /* Extract cache size and associativity */
+ cinfo->line_size = 1 << (creg.no_ccidx.linesize + 4);
+
+ /* Map the associativity value */
+ switch (creg.no_ccidx.associativity + 1) {
+ case CACHE_ASSOC_DIRECT_MAPPED:
+ cinfo->associativity = SMBIOS_CACHE_ASSOC_DMAPPED;
+ break;
+ case CACHE_ASSOC_2WAY:
+ cinfo->associativity = SMBIOS_CACHE_ASSOC_2WAY;
+ break;
+ case CACHE_ASSOC_4WAY:
+ cinfo->associativity = SMBIOS_CACHE_ASSOC_4WAY;
+ break;
+ case CACHE_ASSOC_8WAY:
+ cinfo->associativity = SMBIOS_CACHE_ASSOC_8WAY;
+ break;
+ case CACHE_ASSOC_16WAY:
+ cinfo->associativity = SMBIOS_CACHE_ASSOC_16WAY;
+ break;
+ case CACHE_ASSOC_12WAY:
+ cinfo->associativity = SMBIOS_CACHE_ASSOC_12WAY;
+ break;
+ case CACHE_ASSOC_24WAY:
+ cinfo->associativity = SMBIOS_CACHE_ASSOC_24WAY;
+ break;
+ case CACHE_ASSOC_32WAY:
+ cinfo->associativity = SMBIOS_CACHE_ASSOC_32WAY;
+ break;
+ case CACHE_ASSOC_48WAY:
+ cinfo->associativity = SMBIOS_CACHE_ASSOC_48WAY;
+ break;
+ case CACHE_ASSOC_64WAY:
+ cinfo->associativity = SMBIOS_CACHE_ASSOC_64WAY;
+ break;
+ case CACHE_ASSOC_20WAY:
+ cinfo->associativity = SMBIOS_CACHE_ASSOC_20WAY;
+ break;
+ default:
+ cinfo->associativity = SMBIOS_CACHE_ASSOC_UNKNOWN;
+ break;
+ }
+
+ num_sets = creg.no_ccidx.numsets + 1;
+ /* Size in KB */
+ cinfo->max_size = (cinfo->associativity * num_sets * cinfo->line_size) /
+ 1024;
+
+ debug("L%d Cache:\n", level + 1);
+ debug("Number of bytes in cache line:%u\n", cinfo->line_size);
+ debug("Associativity of cache:%u\n", cinfo->associativity);
+ debug("Number of sets in cache:%u\n", num_sets);
+ debug("Cache size in KB:%u\n", cinfo->max_size);
+
+ cinfo->inst_size = cinfo->max_size;
+
+ /*
+ * Below fields with common values are placed under DT smbios node
+ * socket-design, config
+ * Other fields are typically specific to the implementation of the ARM
+ * processor by the silicon vendor:
+ * supp_sram_type, curr_sram_type, speed, err_corr_type
+ */
+
+ return 0;
+}
+
+int sysinfo_get_processor_info(struct processor_info *pinfo)
+{
+ u64 mpidr, core_count;
+ union midr_el1 midr;
+
+ /* Read the MIDR_EL1 register */
+ asm volatile("mrs %0, MIDR_EL1" : "=r"(midr.data));
+ /* Read the MPIDR_EL1 register */
+ asm volatile("mrs %0, MPIDR_EL1" : "=r"(mpidr));
+
+ debug("MIDR: 0x%016llx\n", midr.data);
+ debug("MPIDR: 0x%016llx\n", mpidr);
+ debug("CPU Implementer: 0x%02x\n", midr.fields.implementer);
+
+ switch (midr.fields.implementer) {
+ case VENDOR_ARM:
+ pinfo->manufacturer = "ARM Limited";
+ break;
+ case VENDOR_BROADCOM:
+ pinfo->manufacturer = "Broadcom Corporation";
+ break;
+ case VENDOR_CAVIUM:
+ pinfo->manufacturer = "Cavium Inc";
+ break;
+ case VENDOR_DEC:
+ pinfo->manufacturer = "Digital Equipment Corporation";
+ break;
+ case VENDOR_FUJITSU:
+ pinfo->manufacturer = "Fujitsu Ltd";
+ break;
+ case VENDOR_INFINEON:
+ pinfo->manufacturer = "Infineon Technologies AG";
+ break;
+ case VENDOR_FREESCALE:
+ pinfo->manufacturer = "Freescale Semiconductor Inc";
+ break;
+ case VENDOR_NVIDIA:
+ pinfo->manufacturer = "NVIDIA Corporation";
+ break;
+ case VENDOR_AMCC:
+ pinfo->manufacturer =
+ "Applied Micro Circuits Corporation";
+ break;
+ case VENDOR_QUALCOMM:
+ pinfo->manufacturer = "Qualcomm Inc";
+ break;
+ case VENDOR_MARVELL:
+ pinfo->manufacturer = "Marvell International Ltd";
+ break;
+ case VENDOR_INTEL:
+ pinfo->manufacturer = "Intel Corporation";
+ break;
+ case VENDOR_AMPERE:
+ pinfo->manufacturer = "Ampere Computing";
+ break;
+ default:
+ pinfo->manufacturer = "Unknown";
+ break;
+ }
+ debug("CPU part number: 0x%x\n", midr.fields.partnum);
+ debug("CPU revision: 0x%x\n", midr.fields.revision);
+ debug("CPU architecture: 0x%x\n", midr.fields.architecture);
+ debug("CPU variant: 0x%x\n", midr.fields.variant);
+
+ /* Extract number of cores */
+ core_count = (mpidr >> 0) & 0xFF;
+ pinfo->core_count = core_count + 1;
+ debug("CPU Core Count: %d\n", pinfo->core_count);
+
+ pinfo->core_enabled = pinfo->core_count;
+ pinfo->characteristics = SMBIOS_PROCESSOR_64BIT |
+ SMBIOS_PROCESSOR_ARM64_SOCID;
+ if (pinfo->core_count > 1)
+ pinfo->characteristics |= SMBIOS_PROCESSOR_MULTICORE;
+
+ /*
+ * Below fields with common values are placed under DT smbios node
+ * version, processor-type, processor-status, upgrade, family2,
+ * socket-design, serial, asset-tag, part-number
+ */
+
+ return 0;
+}
diff --git a/arch/arm/dts/qemu-arm64.dts b/arch/arm/dts/qemu-arm64.dts
index 096b3910728..95fcf53ed74 100644
--- a/arch/arm/dts/qemu-arm64.dts
+++ b/arch/arm/dts/qemu-arm64.dts
@@ -7,5 +7,9 @@
/dts-v1/;
+#if defined(CONFIG_SYSINFO_SMBIOS) && !defined(QFW_SMBIOS)
+#include "smbios_generic.dtsi"
+#endif
+
/ {
};
diff --git a/arch/arm/dts/smbios_generic.dtsi b/arch/arm/dts/smbios_generic.dtsi
new file mode 100644
index 00000000000..fc168317c9e
--- /dev/null
+++ b/arch/arm/dts/smbios_generic.dtsi
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Default SMBIOS information for Arm64 platforms
+ *
+ * Copyright (c) 2024 Linaro Limited
+ * Author: Raymond Mao <raymond.mao@linaro.org>
+ */
+#include <config.h>
+#include <smbios_def.h>
+
+/ {
+ smbios {
+ compatible = "u-boot,sysinfo-smbios";
+
+ smbios {
+ system {
+ manufacturer = CONFIG_SYS_VENDOR;
+ product = CONFIG_SYS_BOARD;
+ version = "";
+ serial = "";
+ wakeup-type = <SMBIOS_WAKEUP_TYPE_UNKNOWN>;
+ sku = "";
+ family = "armv8";
+ };
+
+ baseboard {
+ manufacturer = CONFIG_SYS_VENDOR;
+ product = CONFIG_SYS_BOARD;
+ version = "";
+ serial = "";
+ asset-tag = "";
+ chassis-location = "";
+ feature-flags = <SMBIOS_BOARD_FEAT_HOST_BOARD>;
+ board-type = <SMBIOS_BOARD_TYPE_MOTHERBOARD>;
+ };
+
+ chassis {
+ manufacturer = CONFIG_SYS_VENDOR;
+ version = "";
+ serial = "";
+ asset-tag = "";
+ chassis-type = <SMBIOS_ENCLOSURE_DESKTOP>;
+ bootup-state = <SMBIOS_STATE_SAFE>;
+ power-supply-state = <SMBIOS_STATE_SAFE>;
+ thermal-state = <SMBIOS_STATE_SAFE>;
+ security-status = <SMBIOS_SECURITY_NONE>;
+ oem-defined = <SMBIOS_ENCLOSURE_OEM_UND>;
+ height = <SMBIOS_ENCLOSURE_HEIGHT_UND>;
+ number-of-power-cords = <SMBIOS_POWCORD_NUM_UND>;
+ };
+
+ processor {
+ version = "";
+ processor-type = <SMBIOS_PROCESSOR_TYPE_CENTRAL>;
+ processor-status = <SMBIOS_PROCESSOR_STATUS_ENABLED>;
+ upgrade = <SMBIOS_PROCESSOR_UPGRADE_NONE>;
+ family = <SMBIOS_PROCESSOR_FAMILY_EXT>;
+ family2 = <SMBIOS_PROCESSOR_FAMILY_ARMV8>;
+ socket-design = "";
+ serial = "";
+ asset-tag = "";
+ part-number = "";
+ };
+
+ cache {
+ l1-cache {
+ socket-design = "";
+ config = <(SMBIOS_CACHE_LEVEL_1 |
+ SMBIOS_CACHE_ENABLED |
+ SMBIOS_CACHE_OP_WB)>;
+ };
+
+ l2-cache {
+ socket-design = "";
+ config = <(SMBIOS_CACHE_LEVEL_2 |
+ SMBIOS_CACHE_ENABLED |
+ SMBIOS_CACHE_OP_WB)>;
+ };
+ };
+ };
+ };
+};
diff --git a/cmd/smbios.c b/cmd/smbios.c
index d3bd8b12a67..562dd7959be 100644
--- a/cmd/smbios.c
+++ b/cmd/smbios.c
@@ -14,16 +14,109 @@
DECLARE_GLOBAL_DATA_PTR;
-static const char * const wakeup_type_strings[] = {
- "Reserved", /* 0x00 */
- "Other", /* 0x01 */
- "Unknown", /* 0x02 */
- "APM Timer", /* 0x03 */
- "Modem Ring", /* 0x04 */
- "Lan Remote", /* 0x05 */
- "Power Switch", /* 0x06 */
- "PCI PME#", /* 0x07 */
- "AC Power Restored", /* 0x08 */
+static const struct str_lookup_table wakeup_type_strings[] = {
+ { SMBIOS_WAKEUP_TYPE_RESERVED, "Reserved" },
+ { SMBIOS_WAKEUP_TYPE_OTHER, "Other" },
+ { SMBIOS_WAKEUP_TYPE_UNKNOWN, "Unknown" },
+ { SMBIOS_WAKEUP_TYPE_APM_TIMER, "APM Timer" },
+ { SMBIOS_WAKEUP_TYPE_MODEM_RING, "Modem Ring" },
+ { SMBIOS_WAKEUP_TYPE_LAN_REMOTE, "Lan Remote" },
+ { SMBIOS_WAKEUP_TYPE_POWER_SWITCH, "Power Switch" },
+ { SMBIOS_WAKEUP_TYPE_PCI_PME, "PCI PME#" },
+ { SMBIOS_WAKEUP_TYPE_AC_POWER_RESTORED, "AC Power Restored" },
+};
+
+static const struct str_lookup_table boardtype_strings[] = {
+ { SMBIOS_BOARD_TYPE_UNKNOWN, "Unknown" },
+ { SMBIOS_BOARD_TYPE_OTHER, "Other" },
+ { SMBIOS_BOARD_TYPE_SERVER_BLADE, "Server Blade" },
+ { SMBIOS_BOARD_TYPE_CON_SWITCH, "Connectivity Switch" },
+ { SMBIOS_BOARD_TYPE_SM_MODULE, "System Management Module" },
+ { SMBIOS_BOARD_TYPE_PROCESSOR_MODULE, "Processor Module" },
+ { SMBIOS_BOARD_TYPE_IO_MODULE, "I/O Module" },
+ { SMBIOS_BOARD_TYPE_MEM_MODULE, "Memory Module" },
+ { SMBIOS_BOARD_TYPE_DAUGHTER_BOARD, "Daughter board" },
+ { SMBIOS_BOARD_TYPE_MOTHERBOARD, "Motherboard" },
+ { SMBIOS_BOARD_TYPE_PROC_MEM_MODULE, "Processor/Memory Module" },
+ { SMBIOS_BOARD_TYPE_PROC_IO_MODULE, "Processor/IO Module" },
+ { SMBIOS_BOARD_TYPE_INTERCON, "Interconnect board" },
+};
+
+static const struct str_lookup_table chassis_state_strings[] = {
+ { SMBIOS_STATE_OTHER, "Other" },
+ { SMBIOS_STATE_UNKNOWN, "Unknown" },
+ { SMBIOS_STATE_SAFE, "Safe" },
+ { SMBIOS_STATE_WARNING, "Warning" },
+ { SMBIOS_STATE_CRITICAL, "Critical" },
+ { SMBIOS_STATE_NONRECOVERABLE, "Non-recoverable" },
+};
+
+static const struct str_lookup_table chassis_security_strings[] = {
+ { SMBIOS_SECURITY_OTHER, "Other" },
+ { SMBIOS_SECURITY_UNKNOWN, "Unknown" },
+ { SMBIOS_SECURITY_NONE, "None" },
+ { SMBIOS_SECURITY_EXTINT_LOCK, "External interface locked out" },
+ { SMBIOS_SECURITY_EXTINT_EN, "External interface enabled" },
+};
+
+static const struct str_lookup_table processor_type_strings[] = {
+ { SMBIOS_PROCESSOR_TYPE_OTHER, "Other" },
+ { SMBIOS_PROCESSOR_TYPE_UNKNOWN, "Unknown" },
+ { SMBIOS_PROCESSOR_TYPE_CENTRAL, "Central Processor" },
+ { SMBIOS_PROCESSOR_TYPE_MATH, "Math Processor" },
+ { SMBIOS_PROCESSOR_TYPE_DSP, "DSP Processor" },
+ { SMBIOS_PROCESSOR_TYPE_VIDEO, "Video Processor" },
+};
+
+static const struct str_lookup_table processor_family_strings[] = {
+ { SMBIOS_PROCESSOR_FAMILY_OTHER, "Other" },
+ { SMBIOS_PROCESSOR_FAMILY_UNKNOWN, "Unknown" },
+ { SMBIOS_PROCESSOR_FAMILY_RSVD, "Reserved" },
+ { SMBIOS_PROCESSOR_FAMILY_ARMV7, "ARMv7" },
+ { SMBIOS_PROCESSOR_FAMILY_ARMV8, "ARMv8" },
+ { SMBIOS_PROCESSOR_FAMILY_RV32, "RISC-V RV32" },
+ { SMBIOS_PROCESSOR_FAMILY_RV64, "RISC-V RV64" },
+};
+
+static const struct str_lookup_table processor_upgrade_strings[] = {
+ { SMBIOS_PROCESSOR_UPGRADE_OTHER, "Other" },
+ { SMBIOS_PROCESSOR_UPGRADE_UNKNOWN, "Unknown" },
+ { SMBIOS_PROCESSOR_UPGRADE_NONE, "None" },
+};
+
+static const struct str_lookup_table err_corr_type_strings[] = {
+ { SMBIOS_CACHE_ERRCORR_OTHER, "Other" },
+ { SMBIOS_CACHE_ERRCORR_UNKNOWN, "Unknown" },
+ { SMBIOS_CACHE_ERRCORR_NONE, "None" },
+ { SMBIOS_CACHE_ERRCORR_PARITY, "Parity" },
+ { SMBIOS_CACHE_ERRCORR_SBITECC, "Single-bit ECC" },
+ { SMBIOS_CACHE_ERRCORR_MBITECC, "Multi-bit ECC" },
+};
+
+static const struct str_lookup_table sys_cache_type_strings[] = {
+ { SMBIOS_CACHE_SYSCACHE_TYPE_OTHER, "Other" },
+ { SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN, "Unknown" },
+ { SMBIOS_CACHE_SYSCACHE_TYPE_INST, "Instruction" },
+ { SMBIOS_CACHE_SYSCACHE_TYPE_DATA, "Data" },
+ { SMBIOS_CACHE_SYSCACHE_TYPE_UNIFIED, "Unified" },
+};
+
+static const struct str_lookup_table associativity_strings[] = {
+ { SMBIOS_CACHE_ASSOC_OTHER, "Other" },
+ { SMBIOS_CACHE_ASSOC_UNKNOWN, "Unknown" },
+ { SMBIOS_CACHE_ASSOC_DMAPPED, "Direct Mapped" },
+ { SMBIOS_CACHE_ASSOC_2WAY, "2-way Set-Associative" },
+ { SMBIOS_CACHE_ASSOC_4WAY, "4-way Set-Associative" },
+ { SMBIOS_CACHE_ASSOC_FULLY, "Fully Associative" },
+ { SMBIOS_CACHE_ASSOC_8WAY, "8-way Set-Associative" },
+ { SMBIOS_CACHE_ASSOC_16WAY, "16-way Set-Associative" },
+ { SMBIOS_CACHE_ASSOC_12WAY, "12-way Set-Associative" },
+ { SMBIOS_CACHE_ASSOC_24WAY, "24-way Set-Associative" },
+ { SMBIOS_CACHE_ASSOC_32WAY, "32-way Set-Associative" },
+ { SMBIOS_CACHE_ASSOC_48WAY, "48-way Set-Associative" },
+ { SMBIOS_CACHE_ASSOC_64WAY, "64-way Set-Associative" },
+ { SMBIOS_CACHE_ASSOC_20WAY, "20-way Set-Associative" },
+
};
/**
@@ -37,7 +130,7 @@ static const char *smbios_get_string(void *table, int index)
{
const char *str = (char *)table +
((struct smbios_header *)table)->length;
- static const char fallback[] = "Not Specified";
+ static const char fallback[] = "";
if (!index)
return fallback;
@@ -79,17 +172,53 @@ static void smbios_print_generic(struct smbios_header *table)
}
}
-void smbios_print_str(const char *label, void *table, u8 index)
+static void smbios_print_str(const char *label, void *table, u8 index)
{
printf("\t%s: %s\n", label, smbios_get_string(table, index));
}
-const char *smbios_wakeup_type_str(u8 wakeup_type)
+static void smbios_print_lookup_str(const struct str_lookup_table *table,
+ u16 index, u16 array_size,
+ const char *prefix)
+{
+ int i;
+ const char *str = NULL;
+
+ for (i = 0; i < array_size; i++) {
+ if ((table + i)->idx == index)
+ str = (table + i)->str;
+ }
+
+ if (str)
+ printf("\t%s: %s\n", prefix, str);
+ else
+ printf("\t%s: [%04x]\n", prefix, index);
+}
+
+static void smbios_print_type0(struct smbios_type0 *table)
{
- if (wakeup_type >= ARRAY_SIZE(wakeup_type_strings))
- /* Values over 0x08 are reserved. */
- wakeup_type = 0;
- return wakeup_type_strings[wakeup_type];
+ printf("BIOS Information\n");
+ smbios_print_str("Vendor", table, table->vendor);
+ smbios_print_str("BIOS Version", table, table->bios_ver);
+ /* Keep table->bios_start_segment as 0 for UEFI-based systems */
+ smbios_print_str("BIOS Release Date", table, table->bios_release_date);
+ printf("\tBIOS ROM Size: 0x%02x\n", table->bios_rom_size);
+ printf("\tBIOS Characteristics: 0x%016llx\n",
+ table->bios_characteristics);
+ printf("\tBIOS Characteristics Extension Byte 1: 0x%02x\n",
+ table->bios_characteristics_ext1);
+ printf("\tBIOS Characteristics Extension Byte 2: 0x%02x\n",
+ table->bios_characteristics_ext2);
+ printf("\tSystem BIOS Major Release: 0x%02x\n",
+ table->bios_major_release);
+ printf("\tSystem BIOS Minor Release: 0x%02x\n",
+ table->bios_minor_release);
+ printf("\tEmbedded Controller Firmware Major Release: 0x%02x\n",
+ table->ec_major_release);
+ printf("\tEmbedded Controller Firmware Minor Release: 0x%02x\n",
+ table->ec_minor_release);
+ printf("\tExtended BIOS ROM Size: 0x%04x\n",
+ table->extended_bios_rom_size);
}
static void smbios_print_type1(struct smbios_type1 *table)
@@ -99,12 +228,14 @@ 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));
+ smbios_print_lookup_str(wakeup_type_strings,
+ table->wakeup_type,
+ ARRAY_SIZE(wakeup_type_strings),
+ "Wake-up 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);
}
@@ -112,25 +243,166 @@ static void smbios_print_type1(struct smbios_type1 *table)
static void smbios_print_type2(struct smbios_type2 *table)
{
- u16 *handle;
+ int i;
+ u8 *addr = (u8 *)table + offsetof(struct smbios_type2, eos);
- printf("Base Board Information\n");
+ printf("Baseboard Information\n");
smbios_print_str("Manufacturer", table, table->manufacturer);
smbios_print_str("Product Name", table, table->product_name);
smbios_print_str("Version", table, table->version);
smbios_print_str("Serial Number", table, table->serial_number);
smbios_print_str("Asset Tag", table, table->asset_tag_number);
- printf("\tFeature Flags: 0x%04x\n", table->feature_flags);
+ printf("\tFeature Flags: 0x%02x\n", table->feature_flags);
smbios_print_str("Chassis Location", table, table->chassis_location);
printf("\tChassis Handle: 0x%04x\n", table->chassis_handle);
- smbios_print_str("Board Type", table, table->board_type);
- printf("\tContained Object Handles: ");
- handle = (void *)table->eos;
- for (int i = 0; i < table->number_contained_objects; ++i)
- printf("0x%04x ", handle[i]);
+ smbios_print_lookup_str(boardtype_strings,
+ table->board_type,
+ ARRAY_SIZE(boardtype_strings),
+ "Board Type");
+ printf("\tNumber of Contained Object Handles: 0x%02x\n",
+ table->number_contained_objects);
+ if (!table->number_contained_objects)
+ return;
+
+ printf("\tContained Object Handles:\n");
+ for (i = 0; i < table->number_contained_objects; i++) {
+ printf("\t\tObject[%03d]:\n", i);
+ if (CONFIG_IS_ENABLED(HEXDUMP))
+ print_hex_dump("\t\t", DUMP_PREFIX_OFFSET, 16, 1, addr,
+ sizeof(u16), false);
+ addr += sizeof(u16);
+ }
printf("\n");
}
+static void smbios_print_type3(struct smbios_type3 *table)
+{
+ int i;
+ u8 *addr = (u8 *)table + offsetof(struct smbios_type3, sku_number);
+
+ printf("Baseboard Information\n");
+ smbios_print_str("Manufacturer", table, table->manufacturer);
+ printf("\tType: 0x%02x\n", table->chassis_type);
+ smbios_print_str("Version", table, table->version);
+ smbios_print_str("Serial Number", table, table->serial_number);
+ smbios_print_str("Asset Tag", table, table->asset_tag_number);
+ smbios_print_lookup_str(chassis_state_strings,
+ table->bootup_state,
+ ARRAY_SIZE(chassis_state_strings),
+ "Boot-up State");
+ smbios_print_lookup_str(chassis_state_strings,
+ table->power_supply_state,
+ ARRAY_SIZE(chassis_state_strings),
+ "Power Supply State");
+ smbios_print_lookup_str(chassis_state_strings,
+ table->thermal_state,
+ ARRAY_SIZE(chassis_state_strings),
+ "Thermal State");
+ smbios_print_lookup_str(chassis_security_strings,
+ table->security_status,
+ ARRAY_SIZE(chassis_security_strings),
+ "Security Status");
+ printf("\tOEM-defined: 0x%08x\n", table->oem_defined);
+ printf("\tHeight: 0x%02x\n", table->height);
+ printf("\tNumber of Power Cords: 0x%02x\n",
+ table->number_of_power_cords);
+ printf("\tContained Element Count: 0x%02x\n", table->element_count);
+ printf("\tContained Element Record Length: 0x%02x\n",
+ table->element_record_length);
+ if (table->element_count) {
+ printf("\tContained Elements:\n");
+ for (i = 0; i < table->element_count; i++) {
+ printf("\t\tElement[%03d]:\n", i);
+ if (CONFIG_IS_ENABLED(HEXDUMP))
+ print_hex_dump("\t\t", DUMP_PREFIX_OFFSET, 16,
+ 1, addr,
+ table->element_record_length,
+ false);
+ printf("\t\tContained Element Type: 0x%02x\n", *addr);
+ printf("\t\tContained Element Minimum: 0x%02x\n",
+ *(addr + 1));
+ printf("\t\tContained Element Maximum: 0x%02x\n",
+ *(addr + 2));
+ addr += table->element_record_length;
+ }
+ }
+ smbios_print_str("SKU Number", table, *addr);
+}
+
+static void smbios_print_type4(struct smbios_type4 *table)
+{
+ printf("Processor Information:\n");
+ smbios_print_str("Socket Designation", table, table->socket_design);
+ smbios_print_lookup_str(processor_type_strings,
+ table->processor_type,
+ ARRAY_SIZE(processor_type_strings),
+ "Processor Type");
+ smbios_print_lookup_str(processor_family_strings,
+ table->processor_family,
+ ARRAY_SIZE(processor_family_strings),
+ "Processor Family");
+ smbios_print_str("Processor Manufacturer", table,
+ table->processor_manufacturer);
+ printf("\tProcessor ID word 0: 0x%08x\n", table->processor_id[0]);
+ printf("\tProcessor ID word 1: 0x%08x\n", table->processor_id[1]);
+ smbios_print_str("Processor Version", table, table->processor_version);
+ printf("\tVoltage: 0x%02x\n", table->voltage);
+ printf("\tExternal Clock: 0x%04x\n", table->external_clock);
+ printf("\tMax Speed: 0x%04x\n", table->max_speed);
+ printf("\tCurrent Speed: 0x%04x\n", table->current_speed);
+ printf("\tStatus: 0x%02x\n", table->status);
+ smbios_print_lookup_str(processor_upgrade_strings,
+ table->processor_upgrade,
+ ARRAY_SIZE(processor_upgrade_strings),
+ "Processor Upgrade");
+ printf("\tL1 Cache Handle: 0x%04x\n", table->l1_cache_handle);
+ printf("\tL2 Cache Handle: 0x%04x\n", table->l2_cache_handle);
+ printf("\tL3 Cache Handle: 0x%04x\n", table->l3_cache_handle);
+ smbios_print_str("Serial Number", table, table->serial_number);
+ smbios_print_str("Asset Tag", table, table->asset_tag);
+ smbios_print_str("Part Number", table, table->part_number);
+ printf("\tCore Count: 0x%02x\n", table->core_count);
+ printf("\tCore Enabled: 0x%02x\n", table->core_enabled);
+ printf("\tThread Count: 0x%02x\n", table->thread_count);
+ printf("\tProcessor Characteristics: 0x%04x\n",
+ table->processor_characteristics);
+ smbios_print_lookup_str(processor_family_strings,
+ table->processor_family2,
+ ARRAY_SIZE(processor_family_strings),
+ "Processor Family 2");
+ printf("\tCore Count 2: 0x%04x\n", table->core_count2);
+ printf("\tCore Enabled 2: 0x%04x\n", table->core_enabled2);
+ printf("\tThread Count 2: 0x%04x\n", table->thread_count2);
+ printf("\tThread Enabled: 0x%04x\n", table->thread_enabled);
+}
+
+static void smbios_print_type7(struct smbios_type7 *table)
+{
+ printf("Cache Information:\n");
+ smbios_print_str("Socket Designation", table,
+ table->socket_design);
+ printf("\tCache Configuration: 0x%04x\n", table->config.data);
+ printf("\tMaximum Cache Size: 0x%04x\n", table->max_size.data);
+ printf("\tInstalled Size: 0x%04x\n", table->inst_size.data);
+ printf("\tSupported SRAM Type: 0x%04x\n", table->supp_sram_type.data);
+ printf("\tCurrent SRAM Type: 0x%04x\n", table->curr_sram_type.data);
+ printf("\tCache Speed: 0x%02x\n", table->speed);
+ smbios_print_lookup_str(err_corr_type_strings,
+ table->err_corr_type,
+ ARRAY_SIZE(err_corr_type_strings),
+ "Error Correction Type");
+ smbios_print_lookup_str(sys_cache_type_strings,
+ table->sys_cache_type,
+ ARRAY_SIZE(sys_cache_type_strings),
+ "System Cache Type");
+ smbios_print_lookup_str(associativity_strings,
+ table->associativity,
+ ARRAY_SIZE(associativity_strings),
+ "Associativity");
+ printf("\tMaximum Cache Size 2: 0x%08x\n", table->max_size2.data);
+ printf("\tInstalled Cache Size 2: 0x%08x\n", table->inst_size2.data);
+}
+
static void smbios_print_type127(struct smbios_type127 *table)
{
printf("End Of Table\n");
@@ -192,13 +464,25 @@ static int do_smbios(struct cmd_tbl *cmdtp, int flag, int argc,
pos->handle, pos->type, pos->length,
(unsigned long long)map_to_sysmem(pos));
switch (pos->type) {
- case 1:
+ case SMBIOS_BIOS_INFORMATION:
+ smbios_print_type0((struct smbios_type0 *)pos);
+ break;
+ case SMBIOS_SYSTEM_INFORMATION:
smbios_print_type1((struct smbios_type1 *)pos);
break;
- case 2:
+ case SMBIOS_BOARD_INFORMATION:
smbios_print_type2((struct smbios_type2 *)pos);
break;
- case 127:
+ case SMBIOS_SYSTEM_ENCLOSURE:
+ smbios_print_type3((struct smbios_type3 *)pos);
+ break;
+ case SMBIOS_PROCESSOR_INFORMATION:
+ smbios_print_type4((struct smbios_type4 *)pos);
+ break;
+ case SMBIOS_CACHE_INFORMATION:
+ smbios_print_type7((struct smbios_type7 *)pos);
+ break;
+ case SMBIOS_END_OF_TABLE:
smbios_print_type127((struct smbios_type127 *)pos);
break;
default:
diff --git a/configs/qemu_arm64_defconfig b/configs/qemu_arm64_defconfig
index 06ac6fed3bc..0c7107c1f41 100644
--- a/configs/qemu_arm64_defconfig
+++ b/configs/qemu_arm64_defconfig
@@ -61,6 +61,8 @@ CONFIG_PCIE_ECAM_GENERIC=y
CONFIG_SCSI=y
CONFIG_DEBUG_UART_PL011=y
CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYSINFO=y
+CONFIG_SYSINFO_SMBIOS=y
CONFIG_SYSRESET=y
CONFIG_SYSRESET_CMD_POWEROFF=y
CONFIG_SYSRESET_PSCI=y
@@ -70,3 +72,4 @@ CONFIG_USB_EHCI_PCI=y
CONFIG_SEMIHOSTING=y
CONFIG_MBEDTLS_LIB=y
CONFIG_TPM=y
+CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE=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.
diff --git a/drivers/sysinfo/sandbox.c b/drivers/sysinfo/sandbox.c
index d39720958f0..af54fe87596 100644
--- a/drivers/sysinfo/sandbox.c
+++ b/drivers/sysinfo/sandbox.c
@@ -13,6 +13,7 @@ struct sysinfo_sandbox_priv {
bool called_detect;
int test_i1;
int test_i2;
+ u32 test_data[2];
};
char vacation_spots[][64] = {"R'lyeh", "Dreamlands", "Plateau of Leng",
@@ -24,6 +25,8 @@ int sysinfo_sandbox_detect(struct udevice *dev)
priv->called_detect = true;
priv->test_i2 = 100;
+ priv->test_data[0] = 0xabcdabcd;
+ priv->test_data[1] = 0xdeadbeef;
return 0;
}
@@ -79,6 +82,21 @@ int sysinfo_sandbox_get_str(struct udevice *dev, int id, size_t size, char *val)
return -ENOENT;
}
+int sysinfo_sandbox_get_data(struct udevice *dev, int id, void **buf,
+ size_t *size)
+{
+ struct sysinfo_sandbox_priv *priv = dev_get_priv(dev);
+
+ switch (id) {
+ case DATA_TEST:
+ *buf = priv->test_data;
+ *size = sizeof(priv->test_data);
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
static const struct udevice_id sysinfo_sandbox_ids[] = {
{ .compatible = "sandbox,sysinfo-sandbox" },
{ /* sentinel */ }
@@ -89,6 +107,7 @@ static const struct sysinfo_ops sysinfo_sandbox_ops = {
.get_bool = sysinfo_sandbox_get_bool,
.get_int = sysinfo_sandbox_get_int,
.get_str = sysinfo_sandbox_get_str,
+ .get_data = sysinfo_sandbox_get_data,
};
int sysinfo_sandbox_probe(struct udevice *dev)
diff --git a/drivers/sysinfo/sandbox.h b/drivers/sysinfo/sandbox.h
index a7cbac0ce18..47b7f5ef9fe 100644
--- a/drivers/sysinfo/sandbox.h
+++ b/drivers/sysinfo/sandbox.h
@@ -9,4 +9,5 @@ enum {
INT_TEST1,
INT_TEST2,
STR_VACATIONSPOT,
+ DATA_TEST,
};
diff --git a/drivers/sysinfo/smbios.c b/drivers/sysinfo/smbios.c
index a7ac8e3f072..99104274f72 100644
--- a/drivers/sysinfo/smbios.c
+++ b/drivers/sysinfo/smbios.c
@@ -5,14 +5,240 @@
*/
#include <dm.h>
+#include <smbios_plat.h>
#include <sysinfo.h>
+/* platform information storage */
+struct processor_info processor_info;
+struct cache_info cache_info[SYSINFO_CACHE_LVL_MAX];
+struct sysinfo_plat sysinfo_smbios_p = {
+ /* Processor Information */
+ .processor = &processor_info,
+ /* Cache Information */
+ .cache = &cache_info[0],
+};
+
+/* structure for smbios private data storage */
+struct sysinfo_plat_priv {
+ struct processor_info *t4;
+ struct smbios_type7 t7[SYSINFO_CACHE_LVL_MAX];
+ u16 cache_handles[SYSINFO_CACHE_LVL_MAX];
+ u8 cache_level;
+};
+
+static void smbios_cache_info_dump(struct smbios_type7 *cache_info)
+{
+ log_debug("SMBIOS Type 7 (Cache Information):\n");
+ log_debug("Cache Configuration: 0x%04x\n", cache_info->config.data);
+ log_debug("Maximum Cache Size: %u KB\n", cache_info->max_size.data);
+ log_debug("Installed Size: %u KB\n", cache_info->inst_size.data);
+ log_debug("Supported SRAM Type: 0x%04x\n",
+ cache_info->supp_sram_type.data);
+ log_debug("Current SRAM Type: 0x%04x\n",
+ cache_info->curr_sram_type.data);
+ log_debug("Cache Speed: %u\n", cache_info->speed);
+ log_debug("Error Correction Type: %u\n", cache_info->err_corr_type);
+ log_debug("System Cache Type: %u\n", cache_info->sys_cache_type);
+ log_debug("Associativity: %u\n", cache_info->associativity);
+ log_debug("Maximum Cache Size 2: %u KB\n", cache_info->max_size2.data);
+ log_debug("Installed Cache Size 2: %u KB\n",
+ cache_info->inst_size2.data);
+}
+
+/* weak function for the platforms not yet supported */
+__weak int sysinfo_get_cache_info(u8 level, struct cache_info *cache_info)
+{
+ return -ENOSYS;
+}
+
+__weak int sysinfo_get_processor_info(struct processor_info *pinfo)
+{
+ return -ENOSYS;
+}
+
+void sysinfo_cache_info_default(struct cache_info *ci)
+{
+ memset(ci, 0, sizeof(*ci));
+ ci->config.data = SMBIOS_CACHE_LOCATE_UNKNOWN | SMBIOS_CACHE_OP_UND;
+ ci->supp_sram_type.fields.unknown = 1;
+ ci->curr_sram_type.fields.unknown = 1;
+ ci->speed = SMBIOS_CACHE_SPEED_UNKNOWN;
+ ci->err_corr_type = SMBIOS_CACHE_ERRCORR_UNKNOWN;
+ ci->cache_type = SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN;
+}
+
+static int sysinfo_plat_detect(struct udevice *dev)
+{
+ return 0;
+}
+
+static int sysinfo_plat_get_str(struct udevice *dev, int id,
+ size_t size, char *val)
+{
+ struct sysinfo_plat_priv *priv = dev_get_priv(dev);
+ const char *str = NULL;
+
+ switch (id) {
+ case SYSID_SM_PROCESSOR_MANUFACT:
+ str = priv->t4->manufacturer;
+ break;
+ default:
+ break;
+ }
+
+ if (!str)
+ return -ENOSYS;
+
+ strlcpy(val, str, size);
+
+ return 0;
+}
+
+static int sysinfo_plat_get_int(struct udevice *dev, int id, int *val)
+{
+ struct sysinfo_plat_priv *priv = dev_get_priv(dev);
+ u8 i;
+
+ if (id >= SYSID_SM_CACHE_INFO_START &&
+ id <= SYSID_SM_CACHE_INFO_END) {
+ /* For smbios type 7 */
+ for (i = 0; i < priv->cache_level; i++) {
+ switch (id - i) {
+ case SYSID_SM_CACHE_MAX_SIZE:
+ *val = priv->t7[i].max_size.data;
+ return 0;
+ case SYSID_SM_CACHE_INST_SIZE:
+ *val = priv->t7[i].inst_size.data;
+ return 0;
+ case SYSID_SM_CACHE_SCACHE_TYPE:
+ *val = priv->t7[i].sys_cache_type;
+ return 0;
+ case SYSID_SM_CACHE_ASSOC:
+ *val = priv->t7[i].associativity;
+ return 0;
+ case SYSID_SM_CACHE_MAX_SIZE2:
+ *val = priv->t7[i].max_size2.data;
+ return 0;
+ case SYSID_SM_CACHE_INST_SIZE2:
+ *val = priv->t7[i].inst_size2.data;
+ return 0;
+ default:
+ break;
+ }
+ }
+ return -ENOSYS;
+ }
+
+ switch (id) {
+ case SYSID_SM_PROCESSOR_CORE_CNT:
+ *val = priv->t4->core_count;
+ break;
+ case SYSID_SM_PROCESSOR_CORE_EN:
+ *val = priv->t4->core_enabled;
+ break;
+ case SYSID_SM_PROCESSOR_CHARA:
+ *val = priv->t4->characteristics;
+ break;
+ case SYSID_SM_CACHE_LEVEL:
+ if (!priv->cache_level) /* No cache detected */
+ return -ENOSYS;
+ *val = priv->cache_level - 1;
+ break;
+ default:
+ return -ENOSYS;
+ }
+
+ return 0;
+}
+
+static int sysinfo_plat_get_data(struct udevice *dev, int id, void **buf,
+ size_t *size)
+{
+ struct sysinfo_plat_priv *priv = dev_get_priv(dev);
+
+ switch (id) {
+ case SYSID_SM_PROCESSOR_ID:
+ *buf = priv->t4->id;
+ *size = sizeof(priv->t4->id);
+ break;
+ case SYSID_SM_CACHE_HANDLE:
+ *buf = &priv->cache_handles[0];
+ *size = sizeof(priv->cache_handles);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+static int sysinfo_plat_probe(struct udevice *dev)
+{
+ struct sysinfo_plat_priv *priv = dev_get_priv(dev);
+ struct sysinfo_plat *plat = &sysinfo_smbios_p;
+ u8 level;
+
+ if (!sysinfo_get_processor_info(plat->processor))
+ priv->t4 = plat->processor;
+
+ for (level = 0; level < SYSINFO_CACHE_LVL_MAX; level++) {
+ struct cache_info *pcache = plat->cache + level;
+
+ if (sysinfo_get_cache_info(level, pcache))
+ break; /* no more levels */
+
+ /*
+ * Fill in the SMBIOS type 7 structure,
+ * skip the header members (type, length, handle),
+ * and the ones in DT smbios node.
+ */
+ priv->t7[level].sys_cache_type = pcache->cache_type;
+ priv->t7[level].associativity = pcache->associativity;
+
+ if (pcache->max_size > SMBIOS_CACHE_SIZE_EXT_KB) {
+ priv->t7[level].max_size.data = 0xFFFF;
+ priv->t7[level].max_size2.fields.size =
+ pcache->max_size / 64;
+ priv->t7[level].max_size2.fields.granu =
+ SMBIOS_CACHE_GRANU_64K;
+ } else {
+ priv->t7[level].max_size.fields.size = pcache->max_size;
+ priv->t7[level].max_size.fields.granu =
+ SMBIOS_CACHE_GRANU_1K;
+ priv->t7[level].max_size2.data = 0;
+ }
+ if (pcache->inst_size > SMBIOS_CACHE_SIZE_EXT_KB) {
+ priv->t7[level].inst_size.data = 0xFFFF;
+ priv->t7[level].inst_size2.fields.size =
+ pcache->inst_size / 64;
+ priv->t7[level].inst_size2.fields.granu =
+ SMBIOS_CACHE_GRANU_64K;
+ } else {
+ priv->t7[level].inst_size.fields.size =
+ pcache->inst_size;
+ priv->t7[level].inst_size.fields.granu =
+ SMBIOS_CACHE_GRANU_1K;
+ priv->t7[level].inst_size2.data = 0;
+ }
+ smbios_cache_info_dump(&priv->t7[level]);
+ }
+ if (!level) /* no cache detected */
+ return -ENOSYS;
+
+ priv->cache_level = level;
+
+ return 0;
+}
+
static const struct udevice_id sysinfo_smbios_ids[] = {
{ .compatible = "u-boot,sysinfo-smbios" },
{ /* sentinel */ }
};
static const struct sysinfo_ops sysinfo_smbios_ops = {
+ .detect = sysinfo_plat_detect,
+ .get_str = sysinfo_plat_get_str,
+ .get_int = sysinfo_plat_get_int,
+ .get_data = sysinfo_plat_get_data,
};
U_BOOT_DRIVER(sysinfo_smbios) = {
@@ -20,4 +246,6 @@ U_BOOT_DRIVER(sysinfo_smbios) = {
.id = UCLASS_SYSINFO,
.of_match = sysinfo_smbios_ids,
.ops = &sysinfo_smbios_ops,
+ .priv_auto = sizeof(struct sysinfo_plat_priv),
+ .probe = sysinfo_plat_probe,
};
diff --git a/drivers/sysinfo/sysinfo-uclass.c b/drivers/sysinfo/sysinfo-uclass.c
index d77d1e3ee44..3c0cd51273e 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, void **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/smbios.h b/include/smbios.h
index 00119d7a60c..b5fed57aba2 100644
--- a/include/smbios.h
+++ b/include/smbios.h
@@ -9,6 +9,7 @@
#define _SMBIOS_H_
#include <linux/types.h>
+#include <smbios_def.h>
/* SMBIOS spec version implemented */
#define SMBIOS_MAJOR_VER 3
@@ -37,6 +38,11 @@ enum {
#define SMBIOS_INTERMEDIATE_OFFSET 16
#define SMBIOS_STRUCT_EOS_BYTES 2
+struct str_lookup_table {
+ u16 idx;
+ const char *str;
+};
+
struct __packed smbios_entry {
u8 anchor[4];
u8 checksum;
@@ -80,19 +86,14 @@ struct __packed smbios3_entry {
u64 struct_table_address;
};
-/* BIOS characteristics */
-#define BIOS_CHARACTERISTICS_PCI_SUPPORTED (1 << 7)
-#define BIOS_CHARACTERISTICS_UPGRADEABLE (1 << 11)
-#define BIOS_CHARACTERISTICS_SELECTABLE_BOOT (1 << 16)
-
-#define BIOS_CHARACTERISTICS_EXT1_ACPI (1 << 0)
-#define BIOS_CHARACTERISTICS_EXT2_UEFI (1 << 3)
-#define BIOS_CHARACTERISTICS_EXT2_TARGET (1 << 2)
-
-struct __packed smbios_type0 {
+struct __packed smbios_header {
u8 type;
u8 length;
u16 handle;
+};
+
+struct __packed smbios_type0 {
+ struct smbios_header hdr;
u8 vendor;
u8 bios_ver;
u16 bios_start_segment;
@@ -109,37 +110,12 @@ struct __packed smbios_type0 {
char eos[SMBIOS_STRUCT_EOS_BYTES];
};
-/**
- * enum smbios_wakeup_type - wake-up type
- *
- * These constants are used for the Wake-Up Type field in the SMBIOS
- * System Information (Type 1) structure.
- */
-enum smbios_wakeup_type {
- /** @SMBIOS_WAKEUP_TYPE_RESERVED: Reserved */
- SMBIOS_WAKEUP_TYPE_RESERVED,
- /** @SMBIOS_WAKEUP_TYPE_OTHER: Other */
- SMBIOS_WAKEUP_TYPE_OTHER,
- /** @SMBIOS_WAKEUP_TYPE_UNKNOWN: Unknown */
- SMBIOS_WAKEUP_TYPE_UNKNOWN,
- /** @SMBIOS_WAKEUP_TYPE_APM_TIMER: APM Timer */
- SMBIOS_WAKEUP_TYPE_APM_TIMER,
- /** @SMBIOS_WAKEUP_TYPE_MODEM_RING: Modem Ring */
- SMBIOS_WAKEUP_TYPE_MODEM_RING,
- /** @SMBIOS_WAKEUP_TYPE_LAN_REMOTE: LAN Remote */
- SMBIOS_WAKEUP_TYPE_LAN_REMOTE,
- /** @SMBIOS_WAKEUP_TYPE_POWER_SWITCH: Power Switch */
- SMBIOS_WAKEUP_TYPE_POWER_SWITCH,
- /** @SMBIOS_WAKEUP_TYPE_PCI_PME: PCI PME# */
- SMBIOS_WAKEUP_TYPE_PCI_PME,
- /** @SMBIOS_WAKEUP_TYPE_AC_POWER_RESTORED: AC Power Restored */
- SMBIOS_WAKEUP_TYPE_AC_POWER_RESTORED,
-};
+#define SMBIOS_TYPE1_LENGTH_V20 0x08
+#define SMBIOS_TYPE1_LENGTH_V21 0x19
+#define SMBIOS_TYPE1_LENGTH_V24 0x1b
struct __packed smbios_type1 {
- u8 type;
- u8 length;
- u16 handle;
+ struct smbios_header hdr;
u8 manufacturer;
u8 product_name;
u8 version;
@@ -151,13 +127,10 @@ struct __packed smbios_type1 {
char eos[SMBIOS_STRUCT_EOS_BYTES];
};
-#define SMBIOS_BOARD_FEATURE_HOSTING (1 << 0)
-#define SMBIOS_BOARD_MOTHERBOARD 10
+#define SMBIOS_TYPE2_CON_OBJ_HANDLE_SIZE sizeof(u16)
struct __packed smbios_type2 {
- u8 type;
- u8 length;
- u16 handle;
+ struct smbios_header hdr;
u8 manufacturer;
u8 product_name;
u8 version;
@@ -168,17 +141,15 @@ 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
-
struct __packed smbios_type3 {
- u8 type;
- u8 length;
- u16 handle;
+ struct smbios_header hdr;
u8 manufacturer;
u8 chassis_type;
u8 version;
@@ -193,21 +164,17 @@ struct __packed smbios_type3 {
u8 number_of_power_cords;
u8 element_count;
u8 element_record_length;
+ /*
+ * Dynamic bytes will be inserted here to store the elements.
+ * length is equal to 'element_record_length' * 'element_record_length'
+ */
+ u8 sku_number;
char eos[SMBIOS_STRUCT_EOS_BYTES];
};
-#define SMBIOS_PROCESSOR_TYPE_CENTRAL 3
-#define SMBIOS_PROCESSOR_STATUS_ENABLED 1
-#define SMBIOS_PROCESSOR_UPGRADE_NONE 6
-
-#define SMBIOS_PROCESSOR_FAMILY_OTHER 1
-#define SMBIOS_PROCESSOR_FAMILY_UNKNOWN 2
-
struct __packed smbios_type4 {
- u8 type;
- u8 length;
- u16 handle;
- u8 socket_designation;
+ struct smbios_header hdr;
+ u8 socket_design;
u8 processor_type;
u8 processor_family;
u8 processor_manufacturer;
@@ -233,6 +200,67 @@ struct __packed smbios_type4 {
u16 core_count2;
u16 core_enabled2;
u16 thread_count2;
+ u16 thread_enabled;
+ char eos[SMBIOS_STRUCT_EOS_BYTES];
+};
+
+union cache_config {
+ struct {
+ u16 level:3;
+ u16 bsocketed:1;
+ u16 rsvd0:1;
+ u16 locate:2;
+ u16 benabled:1;
+ u16 opmode:2;
+ u16 rsvd1:6;
+ } fields;
+ u16 data;
+};
+
+union cache_size_word {
+ struct {
+ u16 size:15;
+ u16 granu:1;
+ } fields;
+ u16 data;
+};
+
+union cache_size_dword {
+ struct {
+ u32 size:31;
+ u32 granu:1;
+ } fields;
+ u32 data;
+};
+
+union cache_sram_type {
+ struct {
+ u16 other:1;
+ u16 unknown:1;
+ u16 nonburst:1;
+ u16 burst:1;
+ u16 plburst:1;
+ u16 sync:1;
+ u16 async:1;
+ u16 rsvd:9;
+ } fields;
+ u16 data;
+};
+
+struct __packed smbios_type7 {
+ struct smbios_header hdr;
+ u8 socket_design;
+ union cache_config config;
+ union cache_size_word max_size;
+ union cache_size_word inst_size;
+ union cache_sram_type supp_sram_type;
+ union cache_sram_type curr_sram_type;
+ u8 speed;
+ u8 err_corr_type;
+ u8 sys_cache_type;
+ u8 associativity;
+ union cache_size_dword max_size2;
+ union cache_size_dword inst_size2;
char eos[SMBIOS_STRUCT_EOS_BYTES];
};
@@ -252,12 +280,6 @@ struct __packed smbios_type127 {
char eos[SMBIOS_STRUCT_EOS_BYTES];
};
-struct __packed smbios_header {
- u8 type;
- u8 length;
- u16 handle;
-};
-
/**
* fill_smbios_header() - Fill the header of an SMBIOS table
*
diff --git a/include/smbios_def.h b/include/smbios_def.h
new file mode 100644
index 00000000000..81c5781217f
--- /dev/null
+++ b/include/smbios_def.h
@@ -0,0 +1,194 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2024 Linaro Limited
+ * Author: Raymond Mao <raymond.mao@linaro.org>
+ */
+
+#ifndef _SMBIOS_DEF_H_
+#define _SMBIOS_DEF_H_
+
+/*
+ * BIOS characteristics
+ */
+
+#define BIOS_CHARACTERISTICS_PCI_SUPPORTED 0x80 /* BIT(7) */
+#define BIOS_CHARACTERISTICS_UPGRADEABLE 0x800 /* BIT(11) */
+#define BIOS_CHARACTERISTICS_SELECTABLE_BOOT 0x10000 /* BIT(16) */
+
+#define BIOS_CHARACTERISTICS_EXT1_ACPI 1 /* BIT(0) */
+#define BIOS_CHARACTERISTICS_EXT2_UEFI 8 /* BIT(3) */
+#define BIOS_CHARACTERISTICS_EXT2_TARGET 4 /* BIT(2) */
+
+/*
+ * System Information
+ */
+
+#define SMBIOS_WAKEUP_TYPE_RESERVED 0
+#define SMBIOS_WAKEUP_TYPE_OTHER 1
+#define SMBIOS_WAKEUP_TYPE_UNKNOWN 2
+#define SMBIOS_WAKEUP_TYPE_APM_TIMER 3
+#define SMBIOS_WAKEUP_TYPE_MODEM_RING 4
+#define SMBIOS_WAKEUP_TYPE_LAN_REMOTE 5
+#define SMBIOS_WAKEUP_TYPE_POWER_SWITCH 6
+#define SMBIOS_WAKEUP_TYPE_PCI_PME 7
+#define SMBIOS_WAKEUP_TYPE_AC_POWER_RESTORED 8
+
+/*
+ * Baseboard Information
+ */
+
+#define SMBIOS_BOARD_FEAT_HOST_BOARD 1 /* BIT(0) */
+#define SMBIOS_BOARD_FEAT_REQ_AUX 2 /* BIT(1) */
+#define SMBIOS_BOARD_FEAT_REMOVABLE 4 /* BIT(2) */
+#define SMBIOS_BOARD_FEAT_REPLACEABLE 8 /* BIT(3) */
+#define SMBIOS_BOARD_FEAT_HOT_SWAPPABLE 16 /* BIT(4) */
+
+#define SMBIOS_BOARD_TYPE_UNKNOWN 1
+#define SMBIOS_BOARD_TYPE_OTHER 2
+#define SMBIOS_BOARD_TYPE_SERVER_BLADE 3
+#define SMBIOS_BOARD_TYPE_CON_SWITCH 4
+#define SMBIOS_BOARD_TYPE_SM_MODULE 5
+#define SMBIOS_BOARD_TYPE_PROCESSOR_MODULE 6
+#define SMBIOS_BOARD_TYPE_IO_MODULE 7
+#define SMBIOS_BOARD_TYPE_MEM_MODULE 8
+#define SMBIOS_BOARD_TYPE_DAUGHTER_BOARD 9
+#define SMBIOS_BOARD_TYPE_MOTHERBOARD 10
+#define SMBIOS_BOARD_TYPE_PROC_MEM_MODULE 11
+#define SMBIOS_BOARD_TYPE_PROC_IO_MODULE 12
+#define SMBIOS_BOARD_TYPE_INTERCON 13
+
+/*
+ * System Enclosure or Chassis
+ */
+#define SMBIOS_ENCLOSURE_UNKNOWN 2
+#define SMBIOS_ENCLOSURE_DESKTOP 3
+
+#define SMBIOS_STATE_OTHER 1
+#define SMBIOS_STATE_UNKNOWN 2
+#define SMBIOS_STATE_SAFE 3
+#define SMBIOS_STATE_WARNING 4
+#define SMBIOS_STATE_CRITICAL 5
+#define SMBIOS_STATE_NONRECOVERABLE 6
+
+#define SMBIOS_SECURITY_OTHER 1
+#define SMBIOS_SECURITY_UNKNOWN 2
+#define SMBIOS_SECURITY_NONE 3
+#define SMBIOS_SECURITY_EXTINT_LOCK 4
+#define SMBIOS_SECURITY_EXTINT_EN 5
+
+#define SMBIOS_ENCLOSURE_OEM_UND 0
+#define SMBIOS_ENCLOSURE_HEIGHT_UND 0
+#define SMBIOS_POWCORD_NUM_UND 0
+#define SMBIOS_ELEMENT_TYPE_SELECT 0x80 /* BIT(7) */
+
+/*
+ * Processor Information
+ */
+
+#define SMBIOS_PROCESSOR_TYPE_OTHER 1
+#define SMBIOS_PROCESSOR_TYPE_UNKNOWN 2
+#define SMBIOS_PROCESSOR_TYPE_CENTRAL 3
+#define SMBIOS_PROCESSOR_TYPE_MATH 4
+#define SMBIOS_PROCESSOR_TYPE_DSP 5
+#define SMBIOS_PROCESSOR_TYPE_VIDEO 6
+
+#define SMBIOS_PROCESSOR_STATUS_UNKNOWN 0
+#define SMBIOS_PROCESSOR_STATUS_ENABLED 1
+#define SMBIOS_PROCESSOR_STATUS_DISABLED_USER 2
+#define SMBIOS_PROCESSOR_STATUS_DISABLED_BIOS 3
+#define SMBIOS_PROCESSOR_STATUS_IDLE 4
+#define SMBIOS_PROCESSOR_STATUS_OTHER 7
+
+#define SMBIOS_PROCESSOR_UPGRADE_OTHER 1
+#define SMBIOS_PROCESSOR_UPGRADE_UNKNOWN 2
+#define SMBIOS_PROCESSOR_UPGRADE_NONE 6
+
+#define SMBIOS_PROCESSOR_FAMILY_OTHER 1
+#define SMBIOS_PROCESSOR_FAMILY_UNKNOWN 2
+#define SMBIOS_PROCESSOR_FAMILY_RSVD 255
+#define SMBIOS_PROCESSOR_FAMILY_ARMV7 256
+#define SMBIOS_PROCESSOR_FAMILY_ARMV8 257
+#define SMBIOS_PROCESSOR_FAMILY_RV32 512
+#define SMBIOS_PROCESSOR_FAMILY_RV64 513
+
+#define SMBIOS_PROCESSOR_FAMILY_EXT 0xfe
+
+/* Processor Characteristics */
+#define SMBIOS_PROCESSOR_RSVD 1 /* BIT(0) */
+#define SMBIOS_PROCESSOR_UND 2 /* BIT(1) */
+#define SMBIOS_PROCESSOR_64BIT 4 /* BIT(2) */
+#define SMBIOS_PROCESSOR_MULTICORE 8 /* BIT(3) */
+#define SMBIOS_PROCESSOR_HWTHREAD 16 /* BIT(4) */
+#define SMBIOS_PROCESSOR_EXEC_PROT 32 /* BIT(5) */
+#define SMBIOS_PROCESSOR_ENH_VIRT 64 /* BIT(6) */
+#define SMBIOS_PROCESSOR_POW_CON 0x80 /* BIT(7) */
+#define SMBIOS_PROCESSOR_128BIT 0x100 /* BIT(8) */
+#define SMBIOS_PROCESSOR_ARM64_SOCID 0x200 /* BIT(9) */
+
+/*
+ * Cache Information
+ */
+
+#define SMBIOS_CACHE_SIZE_EXT_KB (2047 * 1024) /* 2047 MiB */
+#define SMBIOS_CACHE_HANDLE_NONE 0xffff
+
+/* System Cache Type */
+#define SMBIOS_CACHE_SYSCACHE_TYPE_OTHER 1
+#define SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN 2
+#define SMBIOS_CACHE_SYSCACHE_TYPE_INST 3
+#define SMBIOS_CACHE_SYSCACHE_TYPE_DATA 4
+#define SMBIOS_CACHE_SYSCACHE_TYPE_UNIFIED 5
+
+/* Cache Speed */
+#define SMBIOS_CACHE_SPEED_UNKNOWN 0
+
+/* SRAM Type */
+#define SMBIOS_CACHE_SRAM_TYPE_UNKNOWN 2 /* BIT(1) */
+
+/* Error Correction Type */
+#define SMBIOS_CACHE_ERRCORR_OTHER 1
+#define SMBIOS_CACHE_ERRCORR_UNKNOWN 2
+#define SMBIOS_CACHE_ERRCORR_NONE 3
+#define SMBIOS_CACHE_ERRCORR_PARITY 4
+#define SMBIOS_CACHE_ERRCORR_SBITECC 5
+#define SMBIOS_CACHE_ERRCORR_MBITECC 6
+
+/* Cache Configuration */
+#define SMBIOS_CACHE_LEVEL_1 0
+#define SMBIOS_CACHE_LEVEL_2 1
+#define SMBIOS_CACHE_LEVEL_3 2
+#define SMBIOS_CACHE_LEVEL_4 3
+#define SMBIOS_CACHE_LEVEL_5 4
+#define SMBIOS_CACHE_LEVEL_6 5
+#define SMBIOS_CACHE_LEVEL_7 6
+#define SMBIOS_CACHE_LEVEL_8 7
+#define SMBIOS_CACHE_SOCKETED 8 /* BIT(3) */
+#define SMBIOS_CACHE_LOCATE_EXTERNAL 32 /* BIT(5) */
+#define SMBIOS_CACHE_LOCATE_RESERVED 64 /* BIT(6) */
+#define SMBIOS_CACHE_LOCATE_UNKNOWN 96 /* (BIT(5) | BIT(6)) */
+#define SMBIOS_CACHE_ENABLED 0x80 /* BIT(7) */
+#define SMBIOS_CACHE_OP_WB 0x100 /* BIT(8), Write Back */
+#define SMBIOS_CACHE_OP_VAR 0x200 /* BIT(9), Varies with Memory Address */
+#define SMBIOS_CACHE_OP_UND 0x300 /* (BIT(8) | BIT(9)), Unknown*/
+
+/* Cache Granularity */
+#define SMBIOS_CACHE_GRANU_1K 0
+#define SMBIOS_CACHE_GRANU_64K 1
+
+/* Cache Associativity */
+#define SMBIOS_CACHE_ASSOC_OTHER 1
+#define SMBIOS_CACHE_ASSOC_UNKNOWN 2
+#define SMBIOS_CACHE_ASSOC_DMAPPED 3
+#define SMBIOS_CACHE_ASSOC_2WAY 4
+#define SMBIOS_CACHE_ASSOC_4WAY 5
+#define SMBIOS_CACHE_ASSOC_FULLY 6
+#define SMBIOS_CACHE_ASSOC_8WAY 7
+#define SMBIOS_CACHE_ASSOC_16WAY 8
+#define SMBIOS_CACHE_ASSOC_12WAY 9
+#define SMBIOS_CACHE_ASSOC_24WAY 10
+#define SMBIOS_CACHE_ASSOC_32WAY 11
+#define SMBIOS_CACHE_ASSOC_48WAY 12
+#define SMBIOS_CACHE_ASSOC_64WAY 13
+#define SMBIOS_CACHE_ASSOC_20WAY 14
+
+#endif /* _SMBIOS_DEF_H_ */
diff --git a/include/smbios_plat.h b/include/smbios_plat.h
new file mode 100644
index 00000000000..70089d5a2ba
--- /dev/null
+++ b/include/smbios_plat.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2024 Linaro Limited
+ * Author: Raymond Mao <raymond.mao@linaro.org>
+ */
+#ifndef __SMBIOS_PLAT_H
+#define __SMBIOS_PLAT_H
+
+#include <smbios.h>
+
+struct cache_info {
+ union cache_config config;
+ union cache_sram_type supp_sram_type;
+ union cache_sram_type curr_sram_type;
+ u32 line_size;
+ u32 associativity;
+ u32 max_size;
+ u32 inst_size;
+ u8 cache_type;
+ u8 speed;
+ u8 err_corr_type;
+ char *socket_design;
+};
+
+struct processor_info {
+ u32 id[2];
+ u16 ext_clock;
+ u16 max_speed;
+ u16 curr_speed;
+ u16 characteristics;
+ u16 family2;
+ u16 core_count2;
+ u16 core_enabled2;
+ u16 thread_count2;
+ u16 thread_enabled;
+ u8 type;
+ u8 family;
+ u8 voltage;
+ u8 status;
+ u8 upgrade;
+ u8 core_count;
+ u8 core_enabled;
+ u8 thread_count;
+ char *socket_design;
+ char *manufacturer;
+ char *version;
+ char *sn;
+ char *asset_tag;
+ char *pn;
+};
+
+struct sysinfo_plat {
+ struct processor_info *processor;
+ struct cache_info *cache;
+ /* add other sysinfo structure here */
+};
+
+#if defined CONFIG_SYSINFO_SMBIOS
+int sysinfo_get_cache_info(u8 level, struct cache_info *cache_info);
+void sysinfo_cache_info_default(struct cache_info *ci);
+int sysinfo_get_processor_info(struct processor_info *pinfo);
+#else
+static inline int sysinfo_get_cache_info(u8 level,
+ struct cache_info *cache_info)
+{
+ return -ENOSYS;
+}
+
+static inline void sysinfo_cache_info_default(struct cache_info *ci)
+{
+}
+
+static inline int sysinfo_get_processor_info(struct processor_info *pinfo)
+{
+ return -ENOSYS;
+}
+#endif
+
+#endif /* __SMBIOS_PLAT_H */
diff --git a/include/sysinfo.h b/include/sysinfo.h
index 027a463dc33..ba2ac273e8e 100644
--- a/include/sysinfo.h
+++ b/include/sysinfo.h
@@ -11,6 +11,8 @@
struct udevice;
+#define SYSINFO_CACHE_LVL_MAX 3
+
/*
* This uclass encapsulates hardware methods to gather information about a
* sysinfo or a specific device such as hard-wired GPIOs on GPIO expanders,
@@ -42,18 +44,109 @@ struct udevice;
enum sysinfo_id {
SYSID_NONE,
- /* For SMBIOS tables */
+ /* BIOS Information (Type 0) */
+ SYSID_SM_BIOS_VENDOR,
+ SYSID_SM_BIOS_VER,
+ SYSID_SM_BIOS_REL_DATE,
+
+ /* System Information (Type 1) */
SYSID_SM_SYSTEM_MANUFACTURER,
SYSID_SM_SYSTEM_PRODUCT,
SYSID_SM_SYSTEM_VERSION,
SYSID_SM_SYSTEM_SERIAL,
+ SYSID_SM_SYSTEM_WAKEUP,
SYSID_SM_SYSTEM_SKU,
SYSID_SM_SYSTEM_FAMILY,
+
+ /* Baseboard (or Module) Information (Type 2) */
SYSID_SM_BASEBOARD_MANUFACTURER,
SYSID_SM_BASEBOARD_PRODUCT,
SYSID_SM_BASEBOARD_VERSION,
SYSID_SM_BASEBOARD_SERIAL,
SYSID_SM_BASEBOARD_ASSET_TAG,
+ SYSID_SM_BASEBOARD_FEATURE,
+ SYSID_SM_BASEBOARD_CHASSIS_LOCAT,
+ SYSID_SM_BASEBOARD_TYPE,
+ SYSID_SM_BASEBOARD_OBJS_NUM,
+ SYSID_SM_BASEBOARD_OBJS_HANDLE,
+
+ /* System Enclosure or Chassis (Type 3) */
+ SYSID_SM_ENCLOSURE_MANUFACTURER,
+ SYSID_SM_ENCLOSURE_VERSION,
+ SYSID_SM_ENCLOSURE_SERIAL,
+ SYSID_SM_ENCLOSURE_ASSET_TAG,
+ SYSID_SM_ENCLOSURE_TYPE,
+ SYSID_SM_ENCLOSURE_BOOTUP,
+ SYSID_SM_ENCLOSURE_POW,
+ SYSID_SM_ENCLOSURE_THERMAL,
+ SYSID_SM_ENCLOSURE_SECURITY,
+ SYSID_SM_ENCLOSURE_OEM,
+ SYSID_SM_ENCLOSURE_HEIGHT,
+ SYSID_SM_ENCLOSURE_POWCORE_NUM,
+ SYSID_SM_ENCLOSURE_ELEMENT_CNT,
+ SYSID_SM_ENCLOSURE_ELEMENT_LEN,
+ SYSID_SM_ENCLOSURE_ELEMENTS,
+ SYSID_SM_ENCLOSURE_SKU,
+
+ /* Processor Information (Type 4) */
+ SYSID_SM_PROCESSOR_SOCKET,
+ SYSID_SM_PROCESSOR_TYPE,
+ SYSID_SM_PROCESSOR_MANUFACT,
+ SYSID_SM_PROCESSOR_ID,
+ SYSID_SM_PROCESSOR_VERSION,
+ SYSID_SM_PROCESSOR_VOLTAGE,
+ SYSID_SM_PROCESSOR_EXT_CLOCK,
+ SYSID_SM_PROCESSOR_MAX_SPEED,
+ SYSID_SM_PROCESSOR_CUR_SPEED,
+ SYSID_SM_PROCESSOR_STATUS,
+ SYSID_SM_PROCESSOR_UPGRADE,
+ SYSID_SM_PROCESSOR_SN,
+ SYSID_SM_PROCESSOR_ASSET_TAG,
+ SYSID_SM_PROCESSOR_PN,
+ SYSID_SM_PROCESSOR_CORE_CNT,
+ SYSID_SM_PROCESSOR_CORE_EN,
+ SYSID_SM_PROCESSOR_THREAD_CNT,
+ SYSID_SM_PROCESSOR_CHARA,
+ SYSID_SM_PROCESSOR_FAMILY,
+ SYSID_SM_PROCESSOR_FAMILY2,
+ SYSID_SM_PROCESSOR_CORE_CNT2,
+ SYSID_SM_PROCESSOR_CORE_EN2,
+ SYSID_SM_PROCESSOR_THREAD_CNT2,
+ SYSID_SM_PROCESSOR_THREAD_EN,
+
+ /*
+ * Cache Information (Type 7)
+ * Each of the id should reserve space for up to
+ * SYSINFO_CACHE_LVL_MAX levels of cache
+ */
+ SYSID_SM_CACHE_LEVEL,
+ SYSID_SM_CACHE_HANDLE,
+ SYSID_SM_CACHE_INFO_START,
+ SYSID_SM_CACHE_SOCKET = SYSID_SM_CACHE_INFO_START,
+ SYSID_SM_CACHE_CONFIG =
+ SYSID_SM_CACHE_SOCKET + SYSINFO_CACHE_LVL_MAX,
+ SYSID_SM_CACHE_MAX_SIZE =
+ SYSID_SM_CACHE_CONFIG + SYSINFO_CACHE_LVL_MAX,
+ SYSID_SM_CACHE_INST_SIZE =
+ SYSID_SM_CACHE_MAX_SIZE + SYSINFO_CACHE_LVL_MAX,
+ SYSID_SM_CACHE_SUPSRAM_TYPE =
+ SYSID_SM_CACHE_INST_SIZE + SYSINFO_CACHE_LVL_MAX,
+ SYSID_SM_CACHE_CURSRAM_TYPE =
+ SYSID_SM_CACHE_SUPSRAM_TYPE + SYSINFO_CACHE_LVL_MAX,
+ SYSID_SM_CACHE_SPEED =
+ SYSID_SM_CACHE_CURSRAM_TYPE + SYSINFO_CACHE_LVL_MAX,
+ SYSID_SM_CACHE_ERRCOR_TYPE =
+ SYSID_SM_CACHE_SPEED + SYSINFO_CACHE_LVL_MAX,
+ SYSID_SM_CACHE_SCACHE_TYPE =
+ SYSID_SM_CACHE_ERRCOR_TYPE + SYSINFO_CACHE_LVL_MAX,
+ SYSID_SM_CACHE_ASSOC =
+ SYSID_SM_CACHE_SCACHE_TYPE + SYSINFO_CACHE_LVL_MAX,
+ SYSID_SM_CACHE_MAX_SIZE2 =
+ SYSID_SM_CACHE_ASSOC + SYSINFO_CACHE_LVL_MAX,
+ SYSID_SM_CACHE_INST_SIZE2 =
+ SYSID_SM_CACHE_MAX_SIZE2 + SYSINFO_CACHE_LVL_MAX,
+ SYSID_SM_CACHE_INFO_END =
+ SYSID_SM_CACHE_INST_SIZE2 + SYSINFO_CACHE_LVL_MAX - 1,
/* For show_board_info() */
SYSID_BOARD_MODEL,
@@ -116,6 +209,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, void **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
* detection. A classic use-case would when DTBOs are used to describe
@@ -187,6 +292,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, void **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 +358,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, void **data,
+ size_t *size)
+{
+ return -ENOSYS;
+}
+
static inline int sysinfo_get(struct udevice **devp)
{
return -ENOSYS;
diff --git a/lib/Kconfig b/lib/Kconfig
index 8f1a96d98c4..baeb615626d 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -1091,6 +1091,12 @@ config GENERATE_SMBIOS_TABLE
See also SYSINFO_SMBIOS which allows SMBIOS values to be provided in
the devicetree.
+config GENERATE_SMBIOS_TABLE_VERBOSE
+ bool "Generate a verbose SMBIOS (System Management BIOS) table"
+ depends on GENERATE_SMBIOS_TABLE
+ help
+ Provide verbose SMBIOS information.
+
endmenu
config LIB_RATIONAL
diff --git a/lib/smbios.c b/lib/smbios.c
index defb6b42f45..78cee8c0c26 100644
--- a/lib/smbios.c
+++ b/lib/smbios.c
@@ -208,6 +208,43 @@ void get_str_from_dt(const struct map_sysinfo *nprop, char *str, size_t size)
}
/**
+ * smbios_get_val_si() - Get value from the devicetree or sysinfo
+ *
+ * @ctx: context of SMBIOS
+ * @prop: property to read
+ * @sysinfo_id: unique identifier for the value to be read
+ * @val_def: Default value
+ * Return: Valid value from sysinfo or device tree, otherwise val_def.
+ */
+static int smbios_get_val_si(struct smbios_ctx * __maybe_unused ctx,
+ const char * __maybe_unused prop,
+ int __maybe_unused sysinfo_id, int val_def)
+{
+#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE)
+ int val;
+
+ if (!ctx->dev)
+ return val_def;
+
+ if (!sysinfo_get_int(ctx->dev, sysinfo_id, &val))
+ return val;
+
+ if (!IS_ENABLED(CONFIG_OF_CONTROL) || !prop)
+ return val_def;
+
+ if (ofnode_valid(ctx->node) && !ofnode_read_u32(ctx->node, prop, &val))
+ return val;
+
+ /*
+ * If the node or property is not valid fallback and try the root
+ */
+ if (!ofnode_read_u32(ofnode_root(), prop, &val))
+ return val;
+#endif
+ return val_def;
+}
+
+/**
* smbios_add_prop_si() - Add a property from the devicetree or sysinfo
*
* Sysinfo is used if available, with a fallback to devicetree
@@ -226,9 +263,6 @@ static int smbios_add_prop_si(struct smbios_ctx *ctx, const char *prop,
if (!dval || !*dval)
dval = NULL;
- if (!prop)
- return smbios_add_string(ctx, dval);
-
if (sysinfo_id && ctx->dev) {
char val[SMBIOS_STR_MAX];
@@ -236,6 +270,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 };
@@ -331,15 +368,17 @@ 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, SYSID_SM_BIOS_VENDOR,
+ "U-Boot");
- t->bios_ver = smbios_add_prop(ctx, "version", PLAIN_VERSION);
+ t->bios_ver = smbios_add_prop_si(ctx, "version", SYSID_SM_BIOS_VER,
+ PLAIN_VERSION);
if (t->bios_ver)
gd->smbios_version = ctx->last_str;
log_debug("smbios_version = %p: '%s'\n", gd->smbios_version,
@@ -348,7 +387,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,
+ SYSID_SM_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;
@@ -375,7 +416,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);
@@ -386,37 +427,38 @@ 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",
SYSID_SM_SYSTEM_MANUFACTURER,
NULL);
t->product_name = smbios_add_prop_si(ctx, "product",
- SYSID_SM_SYSTEM_PRODUCT,
- NULL);
- t->version = smbios_add_prop_si(ctx, "version",
- SYSID_SM_SYSTEM_VERSION,
+ SYSID_SM_SYSTEM_PRODUCT, NULL);
+ t->version = smbios_add_prop_si(ctx, "version", SYSID_SM_SYSTEM_VERSION,
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",
SYSID_SM_SYSTEM_SERIAL,
NULL);
}
- t->wakeup_type = SMBIOS_WAKEUP_TYPE_UNKNOWN;
- t->sku_number = smbios_add_prop_si(ctx, "sku",
- SYSID_SM_SYSTEM_SKU, NULL);
- t->family = smbios_add_prop_si(ctx, "family",
- SYSID_SM_SYSTEM_FAMILY, NULL);
-
- len = t->length + smbios_string_table_len(ctx);
+ t->wakeup_type = smbios_get_val_si(ctx, "wakeup-type",
+ SYSID_SM_SYSTEM_WAKEUP,
+ SMBIOS_WAKEUP_TYPE_UNKNOWN);
+ t->sku_number = smbios_add_prop_si(ctx, "sku", SYSID_SM_SYSTEM_SKU,
+ NULL);
+ t->family = smbios_add_prop_si(ctx, "family", SYSID_SM_SYSTEM_FAMILY,
+ NULL);
+
+ len = t->hdr.length + smbios_string_table_len(ctx);
*current += len;
unmap_sysmem(t);
@@ -427,33 +469,53 @@ 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);
+ u8 *eos_addr;
+ /*
+ * reserve the space for the dynamic bytes of contained object handles.
+ * TODO: len += <obj_handle_num> * SMBIOS_TYPE2_CON_OBJ_HANDLE_SIZE
+ * obj_handle_num can be from DT node "baseboard" or sysinfo driver.
+ */
t = map_sysmem(*current, len);
- memset(t, 0, sizeof(struct smbios_type2));
+ memset(t, 0, len);
fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, handle);
- smbios_set_eos(ctx, t->eos);
+
+ /* 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",
SYSID_SM_BASEBOARD_MANUFACTURER,
NULL);
t->product_name = smbios_add_prop_si(ctx, "product",
- SYSID_SM_BASEBOARD_PRODUCT,
- NULL);
+ SYSID_SM_BASEBOARD_PRODUCT, NULL);
t->version = smbios_add_prop_si(ctx, "version",
- SYSID_SM_BASEBOARD_VERSION,
- NULL);
-
+ SYSID_SM_BASEBOARD_VERSION, NULL);
t->serial_number = smbios_add_prop_si(ctx, "serial",
- SYSID_SM_BASEBOARD_SERIAL,
- NULL);
+ SYSID_SM_BASEBOARD_SERIAL, NULL);
t->asset_tag_number = smbios_add_prop_si(ctx, "asset-tag",
SYSID_SM_BASEBOARD_ASSET_TAG,
NULL);
- t->feature_flags = SMBIOS_BOARD_FEATURE_HOSTING;
- t->board_type = SMBIOS_BOARD_MOTHERBOARD;
+ t->feature_flags = smbios_get_val_si(ctx, "feature-flags",
+ SYSID_SM_BASEBOARD_FEATURE, 0);
+
+ t->chassis_location =
+ smbios_add_prop_si(ctx, "chassis-location",
+ SYSID_SM_BASEBOARD_CHASSIS_LOCAT, NULL);
+ t->board_type = smbios_get_val_si(ctx, "board-type",
+ SYSID_SM_BASEBOARD_TYPE,
+ SMBIOS_BOARD_TYPE_UNKNOWN);
+
+ /*
+ * TODO:
+ * Populate the Contained Object Handles if they exist
+ * t->number_contained_objects = <obj_handle_num>;
+ */
+
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);
@@ -464,20 +526,77 @@ 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 *eos_addr;
+ size_t elem_size = 0;
+ __maybe_unused u8 *elem_addr;
+ __maybe_unused u8 *sku_num_addr;
+
+ /*
+ * reserve the space for the dynamic bytes of contained elements.
+ * TODO: elem_size = <element_count> * <element_record_length>
+ * element_count and element_record_length can be from DT node
+ * "chassis" or sysinfo driver.
+ */
+ len += elem_size;
t = map_sysmem(*current, len);
- memset(t, 0, sizeof(struct smbios_type3));
+ memset(t, 0, len);
fill_smbios_header(t, SMBIOS_SYSTEM_ENCLOSURE, len, handle);
- smbios_set_eos(ctx, t->eos);
- t->manufacturer = smbios_add_prop(ctx, "manufacturer", NULL);
- 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);
+#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE)
+ elem_addr = (u8 *)t + offsetof(struct smbios_type3, sku_number);
+ sku_num_addr = elem_addr + elem_size;
+#endif
+ /* 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",
+ SYSID_SM_ENCLOSURE_MANUFACTURER,
+ NULL);
+ t->chassis_type = smbios_get_val_si(ctx, "chassis-type",
+ SYSID_SM_ENCLOSURE_TYPE,
+ SMBIOS_ENCLOSURE_UNKNOWN);
+ t->bootup_state = smbios_get_val_si(ctx, "bootup-state",
+ SYSID_SM_ENCLOSURE_BOOTUP,
+ SMBIOS_STATE_UNKNOWN);
+ t->power_supply_state = smbios_get_val_si(ctx, "power-supply-state",
+ SYSID_SM_ENCLOSURE_POW,
+ SMBIOS_STATE_UNKNOWN);
+ t->thermal_state = smbios_get_val_si(ctx, "thermal-state",
+ SYSID_SM_ENCLOSURE_THERMAL,
+ SMBIOS_STATE_UNKNOWN);
+ t->security_status = smbios_get_val_si(ctx, "security-status",
+ SYSID_SM_ENCLOSURE_SECURITY,
+ SMBIOS_SECURITY_UNKNOWN);
+
+#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE)
+ t->version = smbios_add_prop_si(ctx, "version",
+ SYSID_SM_ENCLOSURE_VERSION, NULL);
+ t->serial_number = smbios_add_prop_si(ctx, "serial",
+ SYSID_SM_ENCLOSURE_SERIAL, NULL);
+ t->asset_tag_number = smbios_add_prop_si(ctx, "asset-tag",
+ SYSID_SM_BASEBOARD_ASSET_TAG,
+ NULL);
+ t->oem_defined = smbios_get_val_si(ctx, "oem-defined",
+ SYSID_SM_ENCLOSURE_OEM, 0);
+ t->height = smbios_get_val_si(ctx, "height",
+ SYSID_SM_ENCLOSURE_HEIGHT, 0);
+ t->number_of_power_cords =
+ smbios_get_val_si(ctx, "number-of-power-cords",
+ SYSID_SM_ENCLOSURE_POWCORE_NUM, 0);
+
+ /*
+ * TODO: Populate the Contained Element Record if they exist
+ * t->element_count = <element_num>;
+ * t->element_record_length = <element_len>;
+ */
+
+ *sku_num_addr = smbios_add_prop_si(ctx, "sku", SYSID_SM_ENCLOSURE_SKU,
+ NULL);
+#endif
+
+ len = t->hdr.length + smbios_string_table_len(ctx);
*current += len;
unmap_sysmem(t);
@@ -490,6 +609,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;
+ __maybe_unused void *id_data = NULL;
+ __maybe_unused size_t id_size = 0;
#ifdef CONFIG_CPU
char processor_name[49];
@@ -511,46 +632,234 @@ static void smbios_write_type4_dm(struct smbios_type4 *t,
name = processor_name;
}
#endif
+ if (processor_family == SMBIOS_PROCESSOR_FAMILY_UNKNOWN)
+ processor_family =
+ smbios_get_val_si(ctx, "family",
+ SYSID_SM_PROCESSOR_FAMILY,
+ SMBIOS_PROCESSOR_FAMILY_UNKNOWN);
+
+ if (processor_family == SMBIOS_PROCESSOR_FAMILY_EXT)
+ t->processor_family2 =
+ smbios_get_val_si(ctx, "family2",
+ SYSID_SM_PROCESSOR_FAMILY2,
+ SMBIOS_PROCESSOR_FAMILY_UNKNOWN);
+
+ t->processor_family = processor_family;
+ t->processor_manufacturer =
+ smbios_add_prop_si(ctx, "manufacturer",
+ SYSID_SM_PROCESSOR_MANUFACT, vendor);
+ t->processor_version = smbios_add_prop_si(ctx, "version",
+ SYSID_SM_PROCESSOR_VERSION,
+ name);
+
+#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE)
+ if (t->processor_id[0] || t->processor_id[1] ||
+ sysinfo_get_data(ctx->dev, SYSID_SM_PROCESSOR_ID, &id_data,
+ &id_size))
+ return;
- t->processor_family = 0xfe;
- t->processor_family2 = processor_family;
- t->processor_manufacturer = smbios_add_prop(ctx, NULL, vendor);
- t->processor_version = smbios_add_prop(ctx, NULL, name);
+ if (id_data && id_size == sizeof(t->processor_id))
+ memcpy((u8 *)t->processor_id, id_data, id_size);
+#endif
}
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);
+ __maybe_unused void *hdl;
+ __maybe_unused size_t hdl_size;
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, "socket-design",
+ SYSID_SM_PROCESSOR_SOCKET, NULL);
+ t->processor_type = smbios_get_val_si(ctx, "processor-type",
+ SYSID_SM_PROCESSOR_TYPE,
+ SMBIOS_PROCESSOR_TYPE_UNKNOWN);
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->status = smbios_get_val_si(ctx, "processor-status",
+ SYSID_SM_PROCESSOR_STATUS,
+ SMBIOS_PROCESSOR_STATUS_UNKNOWN);
+ t->processor_upgrade =
+ smbios_get_val_si(ctx, "upgrade", SYSID_SM_PROCESSOR_UPGRADE,
+ SMBIOS_PROCESSOR_UPGRADE_UNKNOWN);
+
+ t->l1_cache_handle = SMBIOS_CACHE_HANDLE_NONE;
+ t->l2_cache_handle = SMBIOS_CACHE_HANDLE_NONE;
+ t->l3_cache_handle = SMBIOS_CACHE_HANDLE_NONE;
+
+#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE)
+ t->voltage = smbios_get_val_si(ctx, "voltage",
+ SYSID_SM_PROCESSOR_VOLTAGE, 0);
+ t->external_clock = smbios_get_val_si(ctx, "external-clock",
+ SYSID_SM_PROCESSOR_EXT_CLOCK, 0);
+ t->max_speed = smbios_get_val_si(ctx, "max-speed",
+ SYSID_SM_PROCESSOR_MAX_SPEED, 0);
+ t->current_speed = smbios_get_val_si(ctx, "current-speed",
+ SYSID_SM_PROCESSOR_CUR_SPEED, 0);
+
+ /* Read the cache handles */
+ if (!sysinfo_get_data(ctx->dev, SYSID_SM_CACHE_HANDLE, &hdl,
+ &hdl_size) &&
+ (hdl_size == SYSINFO_CACHE_LVL_MAX * sizeof(u16))) {
+ u16 *handle = (u16 *)hdl;
+
+ if (*handle)
+ t->l1_cache_handle = *handle;
+
+ handle++;
+ if (*handle)
+ t->l2_cache_handle = *handle;
+
+ handle++;
+ if (*handle)
+ t->l3_cache_handle = *handle;
+ }
+
+ t->serial_number = smbios_add_prop_si(ctx, "serial",
+ SYSID_SM_PROCESSOR_SN, NULL);
+ t->asset_tag = smbios_add_prop_si(ctx, "asset-tag",
+ SYSID_SM_PROCESSOR_ASSET_TAG, NULL);
+ t->part_number = smbios_add_prop_si(ctx, "part-number",
+ SYSID_SM_PROCESSOR_PN, NULL);
+ t->core_count = smbios_get_val_si(ctx, "core-count",
+ SYSID_SM_PROCESSOR_CORE_CNT, 0);
+ t->core_enabled = smbios_get_val_si(ctx, "core-enabled",
+ SYSID_SM_PROCESSOR_CORE_EN, 0);
+ t->thread_count = smbios_get_val_si(ctx, "thread-count",
+ SYSID_SM_PROCESSOR_THREAD_CNT, 0);
+ t->processor_characteristics =
+ smbios_get_val_si(ctx, "characteristics",
+ SYSID_SM_PROCESSOR_CHARA,
+ SMBIOS_PROCESSOR_UND);
+ t->core_count2 = smbios_get_val_si(ctx, "core-count2",
+ SYSID_SM_PROCESSOR_CORE_CNT2, 0);
+ t->core_enabled2 = smbios_get_val_si(ctx, "core-enabled2",
+ SYSID_SM_PROCESSOR_CORE_EN2, 0);
+ t->thread_count2 = smbios_get_val_si(ctx, "thread-count2",
+ SYSID_SM_PROCESSOR_THREAD_CNT2, 0);
+ t->thread_enabled = smbios_get_val_si(ctx, "thread-enabled",
+ SYSID_SM_PROCESSOR_THREAD_EN, 0);
+#endif
+
+ len = t->hdr.length + smbios_string_table_len(ctx);
+ *current += len;
+ unmap_sysmem(t);
+
+ return len;
+}
+
+#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE)
+
+static int smbios_write_type7_1level(ulong *current, int handle,
+ struct smbios_ctx *ctx, int level)
+{
+ struct smbios_type7 *t;
+ int len = sizeof(*t);
+ void *hdl;
+ size_t hdl_size;
+
+ t = map_sysmem(*current, len);
+ memset(t, 0, len);
+ fill_smbios_header(t, SMBIOS_CACHE_INFORMATION, len, handle);
+ smbios_set_eos(ctx, t->eos);
+
+ t->socket_design = smbios_add_prop_si(ctx, "socket-design",
+ SYSID_SM_CACHE_SOCKET + level,
+ NULL);
+ t->config.data = smbios_get_val_si(ctx, "config",
+ SYSID_SM_CACHE_CONFIG + level,
+ (level - 1) | SMBIOS_CACHE_OP_UND);
+ t->max_size.data = smbios_get_val_si(ctx, "max-size",
+ SYSID_SM_CACHE_MAX_SIZE + level,
+ 0);
+ t->inst_size.data = smbios_get_val_si(ctx, "installed-size",
+ SYSID_SM_CACHE_INST_SIZE + level,
+ 0);
+ t->supp_sram_type.data =
+ smbios_get_val_si(ctx, "supported-sram-type",
+ SYSID_SM_CACHE_SUPSRAM_TYPE + level,
+ SMBIOS_CACHE_SRAM_TYPE_UNKNOWN);
+ t->curr_sram_type.data =
+ smbios_get_val_si(ctx, "current-sram-type",
+ SYSID_SM_CACHE_CURSRAM_TYPE + level,
+ SMBIOS_CACHE_SRAM_TYPE_UNKNOWN);
+ t->speed = smbios_get_val_si(ctx, "speed", SYSID_SM_CACHE_SPEED + level,
+ 0);
+ t->err_corr_type = smbios_get_val_si(ctx, "error-correction-type",
+ SYSID_SM_CACHE_ERRCOR_TYPE + level,
+ SMBIOS_CACHE_ERRCORR_UNKNOWN);
+ t->sys_cache_type =
+ smbios_get_val_si(ctx, "system-cache-type",
+ SYSID_SM_CACHE_SCACHE_TYPE + level,
+ SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN);
+ t->associativity = smbios_get_val_si(ctx, "associativity",
+ SYSID_SM_CACHE_ASSOC + level,
+ SMBIOS_CACHE_ASSOC_UNKNOWN);
+ t->max_size2.data = smbios_get_val_si(ctx, "max-size2",
+ SYSID_SM_CACHE_MAX_SIZE2 + level,
+ 0);
+ t->inst_size2.data =
+ smbios_get_val_si(ctx, "installed-size2",
+ SYSID_SM_CACHE_INST_SIZE2 + level, 0);
+
+ /* Save the cache handles */
+ if (!sysinfo_get_data(ctx->dev, SYSID_SM_CACHE_HANDLE, &hdl,
+ &hdl_size)) {
+ if (hdl_size == SYSINFO_CACHE_LVL_MAX * sizeof(u16))
+ *((u16 *)hdl + level) = handle;
+ }
+
+ len = t->hdr.length + smbios_string_table_len(ctx);
*current += len;
unmap_sysmem(t);
return len;
}
+static int smbios_write_type7(ulong *current, int handle,
+ struct smbios_ctx *ctx)
+{
+ int len = 0;
+ int i, level;
+ ofnode parent = ctx->node;
+ struct smbios_ctx ctx_bak;
+
+ memcpy(&ctx_bak, ctx, sizeof(ctx_bak));
+
+ /* Get the number of level */
+ level = smbios_get_val_si(ctx, NULL, SYSID_SM_CACHE_LEVEL, 0);
+ if (level >= SYSINFO_CACHE_LVL_MAX) /* Error, return 0-length */
+ return 0;
+
+ for (i = 0; i <= level; i++) {
+ char buf[9] = "";
+
+ if (!snprintf(buf, sizeof(buf), "l%d-cache", i + 1))
+ return 0;
+ ctx->subnode_name = buf;
+ ctx->node = ofnode_find_subnode(parent, ctx->subnode_name);
+ len += smbios_write_type7_1level(current, handle++, ctx, i);
+ memcpy(ctx, &ctx_bak, sizeof(*ctx));
+ }
+ return len;
+}
+
+#endif /* #if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) */
+
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);
@@ -564,10 +873,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;
@@ -582,7 +891,11 @@ static struct smbios_write_method smbios_write_funcs[] = {
{ smbios_write_type2, "baseboard", },
/* Type 3 must immediately follow type 2 due to chassis handle. */
{ smbios_write_type3, "chassis", },
- { smbios_write_type4, },
+#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE)
+ /* Type 7 must ahead of type 4 to get cache handles. */
+ { smbios_write_type7, "cache", },
+#endif
+ { smbios_write_type4, "processor"},
{ smbios_write_type32, },
{ smbios_write_type127 },
};
@@ -599,7 +912,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;
diff --git a/test/dm/sysinfo.c b/test/dm/sysinfo.c
index 6c0d2d7e4df..14ebe6b42e7 100644
--- a/test/dm/sysinfo.c
+++ b/test/dm/sysinfo.c
@@ -19,6 +19,9 @@ static int dm_test_sysinfo(struct unit_test_state *uts)
bool called_detect = false;
char str[64];
int i;
+ void *data = NULL;
+ size_t data_size = 0;
+ u32 gdata[] = {0xabcdabcd, 0xdeadbeef};
ut_assertok(sysinfo_get(&sysinfo));
ut_assert(sysinfo);
@@ -57,6 +60,9 @@ static int dm_test_sysinfo(struct unit_test_state *uts)
str));
ut_assertok(strcmp(str, "Yuggoth"));
+ ut_assertok(sysinfo_get_data(sysinfo, DATA_TEST, &data, &data_size));
+ ut_assertok(memcmp(gdata, data, data_size));
+
return 0;
}
DM_TEST(dm_test_sysinfo, UTF_SCAN_PDATA | UTF_SCAN_FDT);
diff --git a/test/py/tests/test_smbios.py b/test/py/tests/test_smbios.py
index 82b0b689830..0405a9b9d38 100644
--- a/test/py/tests/test_smbios.py
+++ b/test/py/tests/test_smbios.py
@@ -32,10 +32,26 @@ 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
assert 'DMI type 3,' in output
assert 'DMI type 4,' in output
assert 'DMI type 127,' in output
+
+@pytest.mark.buildconfigspec('cmd_smbios')
+@pytest.mark.buildconfigspec('sysinfo_smbios')
+@pytest.mark.buildconfigspec('generate_smbios_table_verbose')
+def test_cmd_smbios_sysinfo_verbose(u_boot_console):
+ """Run the smbios command"""
+ output = u_boot_console.run_command('smbios')
+ assert 'DMI type 0,' in output
+ assert 'Vendor: U-Boot' in output
+ assert 'DMI type 1,' in output
+ assert 'Manufacturer: linux' in output
+ assert 'DMI type 2,' in output
+ assert 'DMI type 3,' in output
+ assert 'DMI type 7,' in output
+ assert 'DMI type 4,' in output
+ assert 'DMI type 127,' in output