[U-Boot] [PATCH 1/2] Makefile: Generate U_BOOT_DMI_DATE for SMBIOS

Add U_BOOT_DMI_DATE (format mm/dd/yyyy) generation to be used by SMBIOS tables, as required by SMBIOS spec 3.0 [1]. See chapter 7.1, BIOS information structure offset 08h for details.
[1] http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.0.0.pd...
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
Makefile | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/Makefile b/Makefile index 8c0ca1b..3177e43 100644 --- a/Makefile +++ b/Makefile @@ -1278,6 +1278,7 @@ define filechk_timestamp.h LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_DATE "%b %d %C%y"'; \ LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_TIME "%T"'; \ LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_TZ "%z"'; \ + LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_DMI_DATE "%m/%d/%Y"'; \ else \ return 42; \ fi; \ @@ -1285,6 +1286,7 @@ define filechk_timestamp.h LC_ALL=C date +'#define U_BOOT_DATE "%b %d %C%y"'; \ LC_ALL=C date +'#define U_BOOT_TIME "%T"'; \ LC_ALL=C date +'#define U_BOOT_TZ "%z"'; \ + LC_ALL=C date +'#define U_BOOT_DMI_DATE "%m/%d/%Y"'; \ fi) endef

System Management BIOS (SMBIOS) is a specification for how motherboard and system vendors present management information about their products in a standard format by extending the BIOS interface on Intel architecture systems. As of today the latest spec is 3.0 and can be downloaded from DMTF website. This commit adds a simple and minimum required implementation.
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
arch/x86/Kconfig | 11 ++ arch/x86/include/asm/smbios.h | 181 +++++++++++++++++++++++++++++++ arch/x86/lib/Makefile | 1 + arch/x86/lib/smbios.c | 242 ++++++++++++++++++++++++++++++++++++++++++ arch/x86/lib/tables.c | 5 + doc/README.x86 | 2 - 6 files changed, 440 insertions(+), 2 deletions(-) create mode 100644 arch/x86/include/asm/smbios.h create mode 100644 arch/x86/lib/smbios.c
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5e42d7d..bf09b21 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -358,6 +358,17 @@ config GENERATE_ACPI_TABLE by the operating system. It defines platform-independent interfaces for configuration and power management monitoring.
+config GENERATE_SMBIOS_TABLE + bool "Generate an SMBIOS (System Management BIOS) table" + default y + help + The System Management BIOS (SMBIOS) specification addresses how + motherboard and system vendors present management information about + their products in a standard format by extending the BIOS interface + on Intel architecture systems. + + Check http://www.dmtf.org/standards/smbios for details. + endmenu
config MAX_PIRQ_LINKS diff --git a/arch/x86/include/asm/smbios.h b/arch/x86/include/asm/smbios.h new file mode 100644 index 0000000..1fa7d74 --- /dev/null +++ b/arch/x86/include/asm/smbios.h @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2015, Bin Meng bmeng.cn@gmail.com + * + * Adapted from coreboot src/include/smbios.h + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _SMBIOS_H_ +#define _SMBIOS_H_ + +/* SMBIOS spec version implemented */ +#define SMBIOS_MAJOR_VER 3 +#define SMBIOS_MINOR_VER 0 + +/* SMBIOS structure types */ +enum { + SMBIOS_BIOS_INFORMATION = 0, + SMBIOS_SYSTEM_INFORMATION = 1, + SMBIOS_SYSTEM_ENCLOSURE = 3, + SMBIOS_PROCESSOR_INFORMATION = 4, + SMBIOS_CACHE_INFORMATION = 7, + SMBIOS_SYSTEM_SLOTS = 9, + SMBIOS_PHYS_MEMORY_ARRAY = 16, + SMBIOS_MEMORY_DEVICE = 17, + SMBIOS_MEMORY_ARRAY_MAPPED_ADDRESS = 19, + SMBIOS_SYSTEM_BOOT_INFORMATION = 32, + SMBIOS_END_OF_TABLE = 127 +}; + +#define SMBIOS_INTERMEDIATE_OFFSET 16 +#define SMBIOS_STRUCT_EOS_BYTES 2 + +struct __packed smbios_entry { + u8 anchor[4]; + u8 checksum; + u8 length; + u8 major_ver; + u8 minor_ver; + u16 max_struct_size; + u8 entry_point_rev; + u8 formatted_area[5]; + u8 intermediate_anchor[5]; + u8 intermediate_checksum; + u16 struct_table_length; + u32 struct_table_address; + u16 struct_count; + u8 bcd_rev; +}; + +/* 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_TARGET (1 << 2) + +struct __packed smbios_type0 { + u8 type; + u8 length; + u16 handle; + u8 vendor; + u8 bios_ver; + u16 bios_start_segment; + u8 bios_release_date; + u8 bios_rom_size; + u64 bios_characteristics; + u8 bios_characteristics_ext1; + u8 bios_characteristics_ext2; + u8 bios_major_release; + u8 bios_minor_release; + u8 ec_major_release; + u8 ec_minor_release; + char eos[SMBIOS_STRUCT_EOS_BYTES]; +}; + +struct __packed smbios_type1 { + u8 type; + u8 length; + u16 handle; + u8 manufacturer; + u8 product_name; + u8 version; + u8 serial_number; + u8 uuid[16]; + u8 wakeup_type; + u8 sku_number; + u8 family; + 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; + u8 manufacturer; + u8 chassis_type; + u8 version; + u8 serial_number; + u8 asset_tag_number; + 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; + char eos[SMBIOS_STRUCT_EOS_BYTES]; +}; + +#define SMBIOS_PROCESSOR_TYPE_CENTRAL 3 +#define SMBIOS_PROCESSOR_STATUS_ENABLED 1 +#define SMBIOS_PROCESSOR_UPGRADE_NONE 6 + +struct __packed smbios_type4 { + u8 type; + u8 length; + u16 handle; + u8 socket_designation; + u8 processor_type; + u8 processor_family; + u8 processor_manufacturer; + u32 processor_id[2]; + u8 processor_version; + u8 voltage; + u16 external_clock; + u16 max_speed; + u16 current_speed; + u8 status; + u8 processor_upgrade; + u16 l1_cache_handle; + u16 l2_cache_handle; + u16 l3_cache_handle; + u8 serial_number; + u8 asset_tag; + u8 part_number; + u8 core_count; + u8 core_enabled; + u8 thread_count; + u16 processor_characteristics; + u16 processor_family2; + u16 core_count2; + u16 core_enabled2; + u16 thread_count2; + char eos[SMBIOS_STRUCT_EOS_BYTES]; +}; + +struct __packed smbios_type32 { + u8 type; + u8 length; + u16 handle; + u8 reserved[6]; + u8 boot_status; + u8 eos[SMBIOS_STRUCT_EOS_BYTES]; +}; + +struct __packed smbios_type127 { + u8 type; + u8 length; + u16 handle; + u8 eos[SMBIOS_STRUCT_EOS_BYTES]; +}; + +/** + * write_smbios_table() - Write SMBIOS table + * + * This writes SMBIOS table at a given address. + * + * @addr: start address to write SMBIOS table + * @return: end address of SMBIOS table + */ +u32 write_smbios_table(u32 addr); + +#endif /* _SMBIOS_H_ */ diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 169062e..4ac9956 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -30,6 +30,7 @@ obj-y += relocate.o obj-y += physmem.o obj-$(CONFIG_X86_RAMTEST) += ramtest.o obj-y += sfi.o +obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o obj-y += string.o obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi_table.o obj-y += tables.o diff --git a/arch/x86/lib/smbios.c b/arch/x86/lib/smbios.c new file mode 100644 index 0000000..2cb2d0c --- /dev/null +++ b/arch/x86/lib/smbios.c @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2015, Bin Meng bmeng.cn@gmail.com + * + * Adapted from coreboot src/arch/x86/smbios.c + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <version.h> +#include <asm/cpu.h> +#include <asm/smbios.h> +#include <asm/tables.h> + +DECLARE_GLOBAL_DATA_PTR; + +static int smbios_add_string(char *start, const char *str) +{ + int i = 1; + char *p = start; + + for (;;) { + if (!*p) { + strcpy(p, str); + p += strlen(str); + *p++ = '\0'; + *p++ = '\0'; + + return i; + } + + if (!strcmp(p, str)) + return i; + + p += strlen(p) + 1; + i++; + } +} + +static int smbios_string_table_len(char *start) +{ + char *p = start; + int i, len = 0; + + while (*p) { + i = strlen(p) + 1; + p += i; + len += i; + } + + return len + 1; +} + +static int smbios_write_type0(u32 *current, int handle) +{ + struct smbios_type0 *t = (struct smbios_type0 *)*current; + int len = sizeof(struct smbios_type0); + + memset(t, 0, sizeof(struct smbios_type0)); + t->type = SMBIOS_BIOS_INFORMATION; + t->length = len - SMBIOS_STRUCT_EOS_BYTES; + t->handle = handle; + t->vendor = smbios_add_string(t->eos, "U-Boot"); + t->bios_ver = smbios_add_string(t->eos, PLAIN_VERSION); + t->bios_release_date = smbios_add_string(t->eos, U_BOOT_DMI_DATE); + t->bios_rom_size = (CONFIG_ROM_SIZE / 65536) - 1; + t->bios_characteristics = BIOS_CHARACTERISTICS_PCI_SUPPORTED | + BIOS_CHARACTERISTICS_SELECTABLE_BOOT | + BIOS_CHARACTERISTICS_UPGRADEABLE; +#ifdef CONFIG_GENERATE_ACPI_TABLE + t->bios_characteristics_ext1 = BIOS_CHARACTERISTICS_EXT1_ACPI; +#endif + t->bios_characteristics_ext2 = BIOS_CHARACTERISTICS_EXT2_TARGET; + t->bios_major_release = 0xff; + t->bios_minor_release = 0xff; + t->ec_major_release = 0xff; + t->ec_minor_release = 0xff; + + len = t->length + smbios_string_table_len(t->eos); + *current += len; + + return len; +} + +static int smbios_write_type1(u32 *current, int handle) +{ + struct smbios_type1 *t = (struct smbios_type1 *)*current; + int len = sizeof(struct smbios_type1); + + memset(t, 0, sizeof(struct smbios_type1)); + t->type = SMBIOS_SYSTEM_INFORMATION; + t->length = len - SMBIOS_STRUCT_EOS_BYTES; + t->handle = handle; + t->manufacturer = smbios_add_string(t->eos, CONFIG_SYS_VENDOR); + t->product_name = smbios_add_string(t->eos, CONFIG_SYS_BOARD); + + len = t->length + smbios_string_table_len(t->eos); + *current += len; + + return len; +} + +static int smbios_write_type3(u32 *current, int handle) +{ + struct smbios_type3 *t = (struct smbios_type3 *)*current; + int len = sizeof(struct smbios_type3); + + memset(t, 0, sizeof(struct smbios_type3)); + t->type = SMBIOS_SYSTEM_ENCLOSURE; + t->length = len - SMBIOS_STRUCT_EOS_BYTES; + t->handle = handle; + t->manufacturer = smbios_add_string(t->eos, CONFIG_SYS_VENDOR); + 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(t->eos); + *current += len; + + return len; +} + +static int smbios_write_type4(u32 *current, int handle) +{ + struct smbios_type4 *t = (struct smbios_type4 *)*current; + int len = sizeof(struct smbios_type4); + const char *vendor; + char *name; + char processor_name[CPU_MAX_NAME_LEN]; + struct cpuid_result res; + + memset(t, 0, sizeof(struct smbios_type4)); + t->type = SMBIOS_PROCESSOR_INFORMATION; + t->length = len - SMBIOS_STRUCT_EOS_BYTES; + t->handle = handle; + t->processor_type = SMBIOS_PROCESSOR_TYPE_CENTRAL; + t->processor_family = gd->arch.x86; + vendor = cpu_vendor_name(gd->arch.x86_vendor); + t->processor_manufacturer = smbios_add_string(t->eos, vendor); + res = cpuid(1); + t->processor_id[0] = res.eax; + t->processor_id[1] = res.edx; + name = cpu_get_name(processor_name); + t->processor_version = smbios_add_string(t->eos, name); + t->status = SMBIOS_PROCESSOR_STATUS_ENABLED; + t->processor_upgrade = SMBIOS_PROCESSOR_UPGRADE_NONE; + t->l1_cache_handle = 0xffff; + t->l2_cache_handle = 0xffff; + t->l3_cache_handle = 0xffff; + t->processor_family2 = t->processor_family; + + len = t->length + smbios_string_table_len(t->eos); + *current += len; + + return len; +} + +static int smbios_write_type32(u32 *current, int handle) +{ + struct smbios_type32 *t = (struct smbios_type32 *)*current; + int len = sizeof(struct smbios_type32); + + memset(t, 0, sizeof(struct smbios_type32)); + t->type = SMBIOS_SYSTEM_BOOT_INFORMATION; + t->length = len - SMBIOS_STRUCT_EOS_BYTES; + t->handle = handle; + + *current += len; + + return len; +} + +static int smbios_write_type127(u32 *current, int handle) +{ + struct smbios_type127 *t = (struct smbios_type127 *)*current; + int len = sizeof(struct smbios_type127); + + memset(t, 0, sizeof(struct smbios_type127)); + t->type = SMBIOS_END_OF_TABLE; + t->length = len - SMBIOS_STRUCT_EOS_BYTES; + t->handle = handle; + + *current += len; + + return len; +} + +#define update_max(len, max_len, stmt) \ + do { \ + int tmp = stmt; \ + max_len = max(max_len, tmp); \ + len += tmp; \ + } while (0) + +u32 write_smbios_table(u32 addr) +{ + struct smbios_entry *se; + u32 tables; + int len = 0; + int max_struct_size = 0; + int handle = 0; + char *istart; + int isize; + + /* 16 byte align the table address */ + addr = ALIGN(addr, 16); + + se = (struct smbios_entry *)addr; + memset(se, 0, sizeof(struct smbios_entry)); + + addr += sizeof(struct smbios_entry); + addr = ALIGN(addr, 16); + tables = addr; + + /* populate minimum required tables */ + update_max(len, max_struct_size, smbios_write_type0(&addr, handle++)); + update_max(len, max_struct_size, smbios_write_type1(&addr, handle++)); + update_max(len, max_struct_size, smbios_write_type3(&addr, handle++)); + update_max(len, max_struct_size, smbios_write_type4(&addr, handle++)); + update_max(len, max_struct_size, smbios_write_type32(&addr, handle++)); + update_max(len, max_struct_size, smbios_write_type127(&addr, handle++)); + + memcpy(se->anchor, "_SM_", 4); + se->length = sizeof(struct smbios_entry); + se->major_ver = SMBIOS_MAJOR_VER; + se->minor_ver = SMBIOS_MINOR_VER; + se->max_struct_size = max_struct_size; + memcpy(se->intermediate_anchor, "_DMI_", 5); + se->struct_table_length = len; + se->struct_table_address = tables; + se->struct_count = handle; + + /* calculate checksums */ + istart = (char *)se + SMBIOS_INTERMEDIATE_OFFSET; + isize = sizeof(struct smbios_entry) - SMBIOS_INTERMEDIATE_OFFSET; + se->intermediate_checksum = table_compute_checksum(istart, isize); + se->checksum = table_compute_checksum(se, sizeof(struct smbios_entry)); + + return addr; +} diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c index f15b2e2..14b15cf 100644 --- a/arch/x86/lib/tables.c +++ b/arch/x86/lib/tables.c @@ -7,6 +7,7 @@ #include <common.h> #include <asm/sfi.h> #include <asm/mpspec.h> +#include <asm/smbios.h> #include <asm/tables.h> #include <asm/acpi_table.h>
@@ -56,4 +57,8 @@ void write_tables(void) rom_table_end = write_acpi_tables(rom_table_end); rom_table_end = ALIGN(rom_table_end, 1024); #endif +#ifdef CONFIG_GENERATE_SMBIOS_TABLE + rom_table_end = write_smbios_table(rom_table_end); + rom_table_end = ALIGN(rom_table_end, 1024); +#endif } diff --git a/doc/README.x86 b/doc/README.x86 index a4f5321..18fed82 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -764,7 +764,6 @@ TODO List - Audio - Chrome OS verified boot - SMI and ACPI support, to provide platform info and facilities to Linux -- Desktop Management Interface (DMI) [15] support
References ---------- @@ -782,4 +781,3 @@ References [12] http://events.linuxfoundation.org/sites/events/files/slides/chromeos_and_diy... [13] http://events.linuxfoundation.org/sites/events/files/slides/elce-2014.pdf [14] doc/device-tree-bindings/misc/intel,irq-router.txt -[15] http://en.wikipedia.org/wiki/Desktop_Management_Interface

Hi Bin,
On 9 October 2015 at 11:17, Bin Meng bmeng.cn@gmail.com wrote:
System Management BIOS (SMBIOS) is a specification for how motherboard and system vendors present management information about their products in a standard format by extending the BIOS interface on Intel architecture systems. As of today the latest spec is 3.0 and can be downloaded from DMTF website. This commit adds a simple and minimum required implementation.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
arch/x86/Kconfig | 11 ++ arch/x86/include/asm/smbios.h | 181 +++++++++++++++++++++++++++++++ arch/x86/lib/Makefile | 1 + arch/x86/lib/smbios.c | 242 ++++++++++++++++++++++++++++++++++++++++++ arch/x86/lib/tables.c | 5 + doc/README.x86 | 2 - 6 files changed, 440 insertions(+), 2 deletions(-) create mode 100644 arch/x86/include/asm/smbios.h create mode 100644 arch/x86/lib/smbios.c
Looks good - just a few style requests.
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5e42d7d..bf09b21 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -358,6 +358,17 @@ config GENERATE_ACPI_TABLE by the operating system. It defines platform-independent interfaces for configuration and power management monitoring.
+config GENERATE_SMBIOS_TABLE
bool "Generate an SMBIOS (System Management BIOS) table"
default y
help
The System Management BIOS (SMBIOS) specification addresses how
motherboard and system vendors present management information about
their products in a standard format by extending the BIOS interface
on Intel architecture systems.
Check http://www.dmtf.org/standards/smbios for details.
endmenu
config MAX_PIRQ_LINKS diff --git a/arch/x86/include/asm/smbios.h b/arch/x86/include/asm/smbios.h new file mode 100644 index 0000000..1fa7d74 --- /dev/null +++ b/arch/x86/include/asm/smbios.h @@ -0,0 +1,181 @@ +/*
- Copyright (C) 2015, Bin Meng bmeng.cn@gmail.com
- Adapted from coreboot src/include/smbios.h
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef _SMBIOS_H_ +#define _SMBIOS_H_
+/* SMBIOS spec version implemented */ +#define SMBIOS_MAJOR_VER 3 +#define SMBIOS_MINOR_VER 0
+/* SMBIOS structure types */ +enum {
SMBIOS_BIOS_INFORMATION = 0,
SMBIOS_SYSTEM_INFORMATION = 1,
SMBIOS_SYSTEM_ENCLOSURE = 3,
SMBIOS_PROCESSOR_INFORMATION = 4,
SMBIOS_CACHE_INFORMATION = 7,
SMBIOS_SYSTEM_SLOTS = 9,
SMBIOS_PHYS_MEMORY_ARRAY = 16,
SMBIOS_MEMORY_DEVICE = 17,
SMBIOS_MEMORY_ARRAY_MAPPED_ADDRESS = 19,
SMBIOS_SYSTEM_BOOT_INFORMATION = 32,
SMBIOS_END_OF_TABLE = 127
+};
+#define SMBIOS_INTERMEDIATE_OFFSET 16 +#define SMBIOS_STRUCT_EOS_BYTES 2
+struct __packed smbios_entry {
u8 anchor[4];
u8 checksum;
u8 length;
u8 major_ver;
u8 minor_ver;
u16 max_struct_size;
u8 entry_point_rev;
u8 formatted_area[5];
u8 intermediate_anchor[5];
u8 intermediate_checksum;
u16 struct_table_length;
u32 struct_table_address;
u16 struct_count;
u8 bcd_rev;
+};
+/* 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_TARGET (1 << 2)
+struct __packed smbios_type0 {
u8 type;
u8 length;
u16 handle;
u8 vendor;
u8 bios_ver;
u16 bios_start_segment;
u8 bios_release_date;
u8 bios_rom_size;
u64 bios_characteristics;
u8 bios_characteristics_ext1;
u8 bios_characteristics_ext2;
u8 bios_major_release;
u8 bios_minor_release;
u8 ec_major_release;
u8 ec_minor_release;
char eos[SMBIOS_STRUCT_EOS_BYTES];
+};
+struct __packed smbios_type1 {
u8 type;
u8 length;
u16 handle;
u8 manufacturer;
u8 product_name;
u8 version;
u8 serial_number;
u8 uuid[16];
u8 wakeup_type;
u8 sku_number;
u8 family;
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;
u8 manufacturer;
u8 chassis_type;
u8 version;
u8 serial_number;
u8 asset_tag_number;
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;
char eos[SMBIOS_STRUCT_EOS_BYTES];
+};
+#define SMBIOS_PROCESSOR_TYPE_CENTRAL 3 +#define SMBIOS_PROCESSOR_STATUS_ENABLED 1 +#define SMBIOS_PROCESSOR_UPGRADE_NONE 6
+struct __packed smbios_type4 {
u8 type;
u8 length;
u16 handle;
u8 socket_designation;
u8 processor_type;
u8 processor_family;
u8 processor_manufacturer;
u32 processor_id[2];
u8 processor_version;
u8 voltage;
u16 external_clock;
u16 max_speed;
u16 current_speed;
u8 status;
u8 processor_upgrade;
u16 l1_cache_handle;
u16 l2_cache_handle;
u16 l3_cache_handle;
u8 serial_number;
u8 asset_tag;
u8 part_number;
u8 core_count;
u8 core_enabled;
u8 thread_count;
u16 processor_characteristics;
u16 processor_family2;
u16 core_count2;
u16 core_enabled2;
u16 thread_count2;
char eos[SMBIOS_STRUCT_EOS_BYTES];
+};
+struct __packed smbios_type32 {
u8 type;
u8 length;
u16 handle;
u8 reserved[6];
u8 boot_status;
u8 eos[SMBIOS_STRUCT_EOS_BYTES];
+};
+struct __packed smbios_type127 {
u8 type;
u8 length;
u16 handle;
u8 eos[SMBIOS_STRUCT_EOS_BYTES];
+};
+/**
- write_smbios_table() - Write SMBIOS table
- This writes SMBIOS table at a given address.
- @addr: start address to write SMBIOS table
- @return: end address of SMBIOS table
- */
+u32 write_smbios_table(u32 addr);
+#endif /* _SMBIOS_H_ */ diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 169062e..4ac9956 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -30,6 +30,7 @@ obj-y += relocate.o obj-y += physmem.o obj-$(CONFIG_X86_RAMTEST) += ramtest.o obj-y += sfi.o +obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o obj-y += string.o obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi_table.o obj-y += tables.o diff --git a/arch/x86/lib/smbios.c b/arch/x86/lib/smbios.c new file mode 100644 index 0000000..2cb2d0c --- /dev/null +++ b/arch/x86/lib/smbios.c @@ -0,0 +1,242 @@ +/*
- Copyright (C) 2015, Bin Meng bmeng.cn@gmail.com
- Adapted from coreboot src/arch/x86/smbios.c
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <version.h> +#include <asm/cpu.h> +#include <asm/smbios.h> +#include <asm/tables.h>
+DECLARE_GLOBAL_DATA_PTR;
+static int smbios_add_string(char *start, const char *str)
Can you please add a comment about what this function does, args and @return? It seems really bizarre.
+{
int i = 1;
char *p = start;
for (;;) {
if (!*p) {
strcpy(p, str);
p += strlen(str);
*p++ = '\0';
*p++ = '\0';
return i;
}
if (!strcmp(p, str))
return i;
p += strlen(p) + 1;
i++;
}
+}
+static int smbios_string_table_len(char *start) +{
char *p = start;
int i, len = 0;
while (*p) {
i = strlen(p) + 1;
p += i;
len += i;
}
return len + 1;
+}
+static int smbios_write_type0(u32 *current, int handle) +{
struct smbios_type0 *t = (struct smbios_type0 *)*current;
int len = sizeof(struct smbios_type0);
memset(t, 0, sizeof(struct smbios_type0));
t->type = SMBIOS_BIOS_INFORMATION;
t->length = len - SMBIOS_STRUCT_EOS_BYTES;
t->handle = handle;
t->vendor = smbios_add_string(t->eos, "U-Boot");
t->bios_ver = smbios_add_string(t->eos, PLAIN_VERSION);
t->bios_release_date = smbios_add_string(t->eos, U_BOOT_DMI_DATE);
t->bios_rom_size = (CONFIG_ROM_SIZE / 65536) - 1;
t->bios_characteristics = BIOS_CHARACTERISTICS_PCI_SUPPORTED |
BIOS_CHARACTERISTICS_SELECTABLE_BOOT |
BIOS_CHARACTERISTICS_UPGRADEABLE;
+#ifdef CONFIG_GENERATE_ACPI_TABLE
t->bios_characteristics_ext1 = BIOS_CHARACTERISTICS_EXT1_ACPI;
+#endif
t->bios_characteristics_ext2 = BIOS_CHARACTERISTICS_EXT2_TARGET;
t->bios_major_release = 0xff;
t->bios_minor_release = 0xff;
t->ec_major_release = 0xff;
t->ec_minor_release = 0xff;
len = t->length + smbios_string_table_len(t->eos);
*current += len;
return len;
+}
+static int smbios_write_type1(u32 *current, int handle) +{
struct smbios_type1 *t = (struct smbios_type1 *)*current;
int len = sizeof(struct smbios_type1);
memset(t, 0, sizeof(struct smbios_type1));
t->type = SMBIOS_SYSTEM_INFORMATION;
t->length = len - SMBIOS_STRUCT_EOS_BYTES;
t->handle = handle;
Can we have a common function that sets up this header given the length? This code seems the same in each function.
t->manufacturer = smbios_add_string(t->eos, CONFIG_SYS_VENDOR);
t->product_name = smbios_add_string(t->eos, CONFIG_SYS_BOARD);
len = t->length + smbios_string_table_len(t->eos);
*current += len;
return len;
+}
+static int smbios_write_type3(u32 *current, int handle) +{
struct smbios_type3 *t = (struct smbios_type3 *)*current;
int len = sizeof(struct smbios_type3);
memset(t, 0, sizeof(struct smbios_type3));
t->type = SMBIOS_SYSTEM_ENCLOSURE;
t->length = len - SMBIOS_STRUCT_EOS_BYTES;
t->handle = handle;
t->manufacturer = smbios_add_string(t->eos, CONFIG_SYS_VENDOR);
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(t->eos);
*current += len;
return len;
+}
+static int smbios_write_type4(u32 *current, int handle) +{
struct smbios_type4 *t = (struct smbios_type4 *)*current;
int len = sizeof(struct smbios_type4);
const char *vendor;
char *name;
char processor_name[CPU_MAX_NAME_LEN];
struct cpuid_result res;
memset(t, 0, sizeof(struct smbios_type4));
t->type = SMBIOS_PROCESSOR_INFORMATION;
t->length = len - SMBIOS_STRUCT_EOS_BYTES;
t->handle = handle;
t->processor_type = SMBIOS_PROCESSOR_TYPE_CENTRAL;
t->processor_family = gd->arch.x86;
vendor = cpu_vendor_name(gd->arch.x86_vendor);
t->processor_manufacturer = smbios_add_string(t->eos, vendor);
res = cpuid(1);
t->processor_id[0] = res.eax;
t->processor_id[1] = res.edx;
name = cpu_get_name(processor_name);
t->processor_version = smbios_add_string(t->eos, name);
t->status = SMBIOS_PROCESSOR_STATUS_ENABLED;
t->processor_upgrade = SMBIOS_PROCESSOR_UPGRADE_NONE;
t->l1_cache_handle = 0xffff;
t->l2_cache_handle = 0xffff;
t->l3_cache_handle = 0xffff;
t->processor_family2 = t->processor_family;
len = t->length + smbios_string_table_len(t->eos);
*current += len;
return len;
+}
+static int smbios_write_type32(u32 *current, int handle) +{
struct smbios_type32 *t = (struct smbios_type32 *)*current;
int len = sizeof(struct smbios_type32);
memset(t, 0, sizeof(struct smbios_type32));
t->type = SMBIOS_SYSTEM_BOOT_INFORMATION;
t->length = len - SMBIOS_STRUCT_EOS_BYTES;
t->handle = handle;
*current += len;
return len;
+}
+static int smbios_write_type127(u32 *current, int handle) +{
struct smbios_type127 *t = (struct smbios_type127 *)*current;
int len = sizeof(struct smbios_type127);
memset(t, 0, sizeof(struct smbios_type127));
t->type = SMBIOS_END_OF_TABLE;
t->length = len - SMBIOS_STRUCT_EOS_BYTES;
t->handle = handle;
*current += len;
return len;
+}
+#define update_max(len, max_len, stmt) \
do { \
int tmp = stmt; \
max_len = max(max_len, tmp); \
len += tmp; \
} while (0)
+u32 write_smbios_table(u32 addr) +{
struct smbios_entry *se;
u32 tables;
int len = 0;
int max_struct_size = 0;
int handle = 0;
char *istart;
int isize;
/* 16 byte align the table address */
addr = ALIGN(addr, 16);
se = (struct smbios_entry *)addr;
memset(se, 0, sizeof(struct smbios_entry));
addr += sizeof(struct smbios_entry);
addr = ALIGN(addr, 16);
tables = addr;
/* populate minimum required tables */
update_max(len, max_struct_size, smbios_write_type0(&addr, handle++));
update_max(len, max_struct_size, smbios_write_type1(&addr, handle++));
update_max(len, max_struct_size, smbios_write_type3(&addr, handle++));
update_max(len, max_struct_size, smbios_write_type4(&addr, handle++));
update_max(len, max_struct_size, smbios_write_type32(&addr, handle++));
update_max(len, max_struct_size, smbios_write_type127(&addr, handle++));
I'm not keen on this #define approach. Perhaps this would be better as a table of functions to call, and a loop that calls them in turn, updating 'max_struct_size'?
memcpy(se->anchor, "_SM_", 4);
se->length = sizeof(struct smbios_entry);
se->major_ver = SMBIOS_MAJOR_VER;
se->minor_ver = SMBIOS_MINOR_VER;
se->max_struct_size = max_struct_size;
memcpy(se->intermediate_anchor, "_DMI_", 5);
se->struct_table_length = len;
se->struct_table_address = tables;
se->struct_count = handle;
/* calculate checksums */
istart = (char *)se + SMBIOS_INTERMEDIATE_OFFSET;
isize = sizeof(struct smbios_entry) - SMBIOS_INTERMEDIATE_OFFSET;
se->intermediate_checksum = table_compute_checksum(istart, isize);
se->checksum = table_compute_checksum(se, sizeof(struct smbios_entry));
return addr;
+} diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c index f15b2e2..14b15cf 100644 --- a/arch/x86/lib/tables.c +++ b/arch/x86/lib/tables.c @@ -7,6 +7,7 @@ #include <common.h> #include <asm/sfi.h> #include <asm/mpspec.h> +#include <asm/smbios.h> #include <asm/tables.h> #include <asm/acpi_table.h>
@@ -56,4 +57,8 @@ void write_tables(void) rom_table_end = write_acpi_tables(rom_table_end); rom_table_end = ALIGN(rom_table_end, 1024); #endif +#ifdef CONFIG_GENERATE_SMBIOS_TABLE
rom_table_end = write_smbios_table(rom_table_end);
rom_table_end = ALIGN(rom_table_end, 1024);
+#endif } diff --git a/doc/README.x86 b/doc/README.x86 index a4f5321..18fed82 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -764,7 +764,6 @@ TODO List
- Audio
- Chrome OS verified boot
- SMI and ACPI support, to provide platform info and facilities to Linux
-- Desktop Management Interface (DMI) [15] support
References
@@ -782,4 +781,3 @@ References [12] http://events.linuxfoundation.org/sites/events/files/slides/chromeos_and_diy... [13] http://events.linuxfoundation.org/sites/events/files/slides/elce-2014.pdf [14] doc/device-tree-bindings/misc/intel,irq-router.txt
-[15] http://en.wikipedia.org/wiki/Desktop_Management_Interface
1.8.2.1
It might be worth adding docs to the README about what tables U-Boot now supports, how to enable each and what is recommended. There are quite a few now. My head is spinning!
Regards, Simon

Hi Simon,
On Fri, Oct 9, 2015 at 9:02 PM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 9 October 2015 at 11:17, Bin Meng bmeng.cn@gmail.com wrote:
System Management BIOS (SMBIOS) is a specification for how motherboard and system vendors present management information about their products in a standard format by extending the BIOS interface on Intel architecture systems. As of today the latest spec is 3.0 and can be downloaded from DMTF website. This commit adds a simple and minimum required implementation.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
arch/x86/Kconfig | 11 ++ arch/x86/include/asm/smbios.h | 181 +++++++++++++++++++++++++++++++ arch/x86/lib/Makefile | 1 + arch/x86/lib/smbios.c | 242 ++++++++++++++++++++++++++++++++++++++++++ arch/x86/lib/tables.c | 5 + doc/README.x86 | 2 - 6 files changed, 440 insertions(+), 2 deletions(-) create mode 100644 arch/x86/include/asm/smbios.h create mode 100644 arch/x86/lib/smbios.c
Looks good - just a few style requests.
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5e42d7d..bf09b21 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -358,6 +358,17 @@ config GENERATE_ACPI_TABLE by the operating system. It defines platform-independent interfaces for configuration and power management monitoring.
+config GENERATE_SMBIOS_TABLE
bool "Generate an SMBIOS (System Management BIOS) table"
default y
help
The System Management BIOS (SMBIOS) specification addresses how
motherboard and system vendors present management information about
their products in a standard format by extending the BIOS interface
on Intel architecture systems.
Check http://www.dmtf.org/standards/smbios for details.
endmenu
config MAX_PIRQ_LINKS diff --git a/arch/x86/include/asm/smbios.h b/arch/x86/include/asm/smbios.h new file mode 100644 index 0000000..1fa7d74 --- /dev/null +++ b/arch/x86/include/asm/smbios.h @@ -0,0 +1,181 @@ +/*
- Copyright (C) 2015, Bin Meng bmeng.cn@gmail.com
- Adapted from coreboot src/include/smbios.h
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef _SMBIOS_H_ +#define _SMBIOS_H_
+/* SMBIOS spec version implemented */ +#define SMBIOS_MAJOR_VER 3 +#define SMBIOS_MINOR_VER 0
+/* SMBIOS structure types */ +enum {
SMBIOS_BIOS_INFORMATION = 0,
SMBIOS_SYSTEM_INFORMATION = 1,
SMBIOS_SYSTEM_ENCLOSURE = 3,
SMBIOS_PROCESSOR_INFORMATION = 4,
SMBIOS_CACHE_INFORMATION = 7,
SMBIOS_SYSTEM_SLOTS = 9,
SMBIOS_PHYS_MEMORY_ARRAY = 16,
SMBIOS_MEMORY_DEVICE = 17,
SMBIOS_MEMORY_ARRAY_MAPPED_ADDRESS = 19,
SMBIOS_SYSTEM_BOOT_INFORMATION = 32,
SMBIOS_END_OF_TABLE = 127
+};
+#define SMBIOS_INTERMEDIATE_OFFSET 16 +#define SMBIOS_STRUCT_EOS_BYTES 2
+struct __packed smbios_entry {
u8 anchor[4];
u8 checksum;
u8 length;
u8 major_ver;
u8 minor_ver;
u16 max_struct_size;
u8 entry_point_rev;
u8 formatted_area[5];
u8 intermediate_anchor[5];
u8 intermediate_checksum;
u16 struct_table_length;
u32 struct_table_address;
u16 struct_count;
u8 bcd_rev;
+};
+/* 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_TARGET (1 << 2)
+struct __packed smbios_type0 {
u8 type;
u8 length;
u16 handle;
u8 vendor;
u8 bios_ver;
u16 bios_start_segment;
u8 bios_release_date;
u8 bios_rom_size;
u64 bios_characteristics;
u8 bios_characteristics_ext1;
u8 bios_characteristics_ext2;
u8 bios_major_release;
u8 bios_minor_release;
u8 ec_major_release;
u8 ec_minor_release;
char eos[SMBIOS_STRUCT_EOS_BYTES];
+};
+struct __packed smbios_type1 {
u8 type;
u8 length;
u16 handle;
u8 manufacturer;
u8 product_name;
u8 version;
u8 serial_number;
u8 uuid[16];
u8 wakeup_type;
u8 sku_number;
u8 family;
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;
u8 manufacturer;
u8 chassis_type;
u8 version;
u8 serial_number;
u8 asset_tag_number;
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;
char eos[SMBIOS_STRUCT_EOS_BYTES];
+};
+#define SMBIOS_PROCESSOR_TYPE_CENTRAL 3 +#define SMBIOS_PROCESSOR_STATUS_ENABLED 1 +#define SMBIOS_PROCESSOR_UPGRADE_NONE 6
+struct __packed smbios_type4 {
u8 type;
u8 length;
u16 handle;
u8 socket_designation;
u8 processor_type;
u8 processor_family;
u8 processor_manufacturer;
u32 processor_id[2];
u8 processor_version;
u8 voltage;
u16 external_clock;
u16 max_speed;
u16 current_speed;
u8 status;
u8 processor_upgrade;
u16 l1_cache_handle;
u16 l2_cache_handle;
u16 l3_cache_handle;
u8 serial_number;
u8 asset_tag;
u8 part_number;
u8 core_count;
u8 core_enabled;
u8 thread_count;
u16 processor_characteristics;
u16 processor_family2;
u16 core_count2;
u16 core_enabled2;
u16 thread_count2;
char eos[SMBIOS_STRUCT_EOS_BYTES];
+};
+struct __packed smbios_type32 {
u8 type;
u8 length;
u16 handle;
u8 reserved[6];
u8 boot_status;
u8 eos[SMBIOS_STRUCT_EOS_BYTES];
+};
+struct __packed smbios_type127 {
u8 type;
u8 length;
u16 handle;
u8 eos[SMBIOS_STRUCT_EOS_BYTES];
+};
+/**
- write_smbios_table() - Write SMBIOS table
- This writes SMBIOS table at a given address.
- @addr: start address to write SMBIOS table
- @return: end address of SMBIOS table
- */
+u32 write_smbios_table(u32 addr);
+#endif /* _SMBIOS_H_ */ diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 169062e..4ac9956 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -30,6 +30,7 @@ obj-y += relocate.o obj-y += physmem.o obj-$(CONFIG_X86_RAMTEST) += ramtest.o obj-y += sfi.o +obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o obj-y += string.o obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi_table.o obj-y += tables.o diff --git a/arch/x86/lib/smbios.c b/arch/x86/lib/smbios.c new file mode 100644 index 0000000..2cb2d0c --- /dev/null +++ b/arch/x86/lib/smbios.c @@ -0,0 +1,242 @@ +/*
- Copyright (C) 2015, Bin Meng bmeng.cn@gmail.com
- Adapted from coreboot src/arch/x86/smbios.c
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <version.h> +#include <asm/cpu.h> +#include <asm/smbios.h> +#include <asm/tables.h>
+DECLARE_GLOBAL_DATA_PTR;
+static int smbios_add_string(char *start, const char *str)
Can you please add a comment about what this function does, args and @return? It seems really bizarre.
Sure.
+{
int i = 1;
char *p = start;
for (;;) {
if (!*p) {
strcpy(p, str);
p += strlen(str);
*p++ = '\0';
*p++ = '\0';
return i;
}
if (!strcmp(p, str))
return i;
p += strlen(p) + 1;
i++;
}
+}
+static int smbios_string_table_len(char *start) +{
char *p = start;
int i, len = 0;
while (*p) {
i = strlen(p) + 1;
p += i;
len += i;
}
return len + 1;
+}
+static int smbios_write_type0(u32 *current, int handle) +{
struct smbios_type0 *t = (struct smbios_type0 *)*current;
int len = sizeof(struct smbios_type0);
memset(t, 0, sizeof(struct smbios_type0));
t->type = SMBIOS_BIOS_INFORMATION;
t->length = len - SMBIOS_STRUCT_EOS_BYTES;
t->handle = handle;
t->vendor = smbios_add_string(t->eos, "U-Boot");
t->bios_ver = smbios_add_string(t->eos, PLAIN_VERSION);
t->bios_release_date = smbios_add_string(t->eos, U_BOOT_DMI_DATE);
t->bios_rom_size = (CONFIG_ROM_SIZE / 65536) - 1;
t->bios_characteristics = BIOS_CHARACTERISTICS_PCI_SUPPORTED |
BIOS_CHARACTERISTICS_SELECTABLE_BOOT |
BIOS_CHARACTERISTICS_UPGRADEABLE;
+#ifdef CONFIG_GENERATE_ACPI_TABLE
t->bios_characteristics_ext1 = BIOS_CHARACTERISTICS_EXT1_ACPI;
+#endif
t->bios_characteristics_ext2 = BIOS_CHARACTERISTICS_EXT2_TARGET;
t->bios_major_release = 0xff;
t->bios_minor_release = 0xff;
t->ec_major_release = 0xff;
t->ec_minor_release = 0xff;
len = t->length + smbios_string_table_len(t->eos);
*current += len;
return len;
+}
+static int smbios_write_type1(u32 *current, int handle) +{
struct smbios_type1 *t = (struct smbios_type1 *)*current;
int len = sizeof(struct smbios_type1);
memset(t, 0, sizeof(struct smbios_type1));
t->type = SMBIOS_SYSTEM_INFORMATION;
t->length = len - SMBIOS_STRUCT_EOS_BYTES;
t->handle = handle;
Can we have a common function that sets up this header given the length? This code seems the same in each function.
Sure.
t->manufacturer = smbios_add_string(t->eos, CONFIG_SYS_VENDOR);
t->product_name = smbios_add_string(t->eos, CONFIG_SYS_BOARD);
len = t->length + smbios_string_table_len(t->eos);
*current += len;
return len;
+}
+static int smbios_write_type3(u32 *current, int handle) +{
struct smbios_type3 *t = (struct smbios_type3 *)*current;
int len = sizeof(struct smbios_type3);
memset(t, 0, sizeof(struct smbios_type3));
t->type = SMBIOS_SYSTEM_ENCLOSURE;
t->length = len - SMBIOS_STRUCT_EOS_BYTES;
t->handle = handle;
t->manufacturer = smbios_add_string(t->eos, CONFIG_SYS_VENDOR);
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(t->eos);
*current += len;
return len;
+}
+static int smbios_write_type4(u32 *current, int handle) +{
struct smbios_type4 *t = (struct smbios_type4 *)*current;
int len = sizeof(struct smbios_type4);
const char *vendor;
char *name;
char processor_name[CPU_MAX_NAME_LEN];
struct cpuid_result res;
memset(t, 0, sizeof(struct smbios_type4));
t->type = SMBIOS_PROCESSOR_INFORMATION;
t->length = len - SMBIOS_STRUCT_EOS_BYTES;
t->handle = handle;
t->processor_type = SMBIOS_PROCESSOR_TYPE_CENTRAL;
t->processor_family = gd->arch.x86;
vendor = cpu_vendor_name(gd->arch.x86_vendor);
t->processor_manufacturer = smbios_add_string(t->eos, vendor);
res = cpuid(1);
t->processor_id[0] = res.eax;
t->processor_id[1] = res.edx;
name = cpu_get_name(processor_name);
t->processor_version = smbios_add_string(t->eos, name);
t->status = SMBIOS_PROCESSOR_STATUS_ENABLED;
t->processor_upgrade = SMBIOS_PROCESSOR_UPGRADE_NONE;
t->l1_cache_handle = 0xffff;
t->l2_cache_handle = 0xffff;
t->l3_cache_handle = 0xffff;
t->processor_family2 = t->processor_family;
len = t->length + smbios_string_table_len(t->eos);
*current += len;
return len;
+}
+static int smbios_write_type32(u32 *current, int handle) +{
struct smbios_type32 *t = (struct smbios_type32 *)*current;
int len = sizeof(struct smbios_type32);
memset(t, 0, sizeof(struct smbios_type32));
t->type = SMBIOS_SYSTEM_BOOT_INFORMATION;
t->length = len - SMBIOS_STRUCT_EOS_BYTES;
t->handle = handle;
*current += len;
return len;
+}
+static int smbios_write_type127(u32 *current, int handle) +{
struct smbios_type127 *t = (struct smbios_type127 *)*current;
int len = sizeof(struct smbios_type127);
memset(t, 0, sizeof(struct smbios_type127));
t->type = SMBIOS_END_OF_TABLE;
t->length = len - SMBIOS_STRUCT_EOS_BYTES;
t->handle = handle;
*current += len;
return len;
+}
+#define update_max(len, max_len, stmt) \
do { \
int tmp = stmt; \
max_len = max(max_len, tmp); \
len += tmp; \
} while (0)
+u32 write_smbios_table(u32 addr) +{
struct smbios_entry *se;
u32 tables;
int len = 0;
int max_struct_size = 0;
int handle = 0;
char *istart;
int isize;
/* 16 byte align the table address */
addr = ALIGN(addr, 16);
se = (struct smbios_entry *)addr;
memset(se, 0, sizeof(struct smbios_entry));
addr += sizeof(struct smbios_entry);
addr = ALIGN(addr, 16);
tables = addr;
/* populate minimum required tables */
update_max(len, max_struct_size, smbios_write_type0(&addr, handle++));
update_max(len, max_struct_size, smbios_write_type1(&addr, handle++));
update_max(len, max_struct_size, smbios_write_type3(&addr, handle++));
update_max(len, max_struct_size, smbios_write_type4(&addr, handle++));
update_max(len, max_struct_size, smbios_write_type32(&addr, handle++));
update_max(len, max_struct_size, smbios_write_type127(&addr, handle++));
I'm not keen on this #define approach. Perhaps this would be better as a table of functions to call, and a loop that calls them in turn, updating 'max_struct_size'?
I will have a try.
memcpy(se->anchor, "_SM_", 4);
se->length = sizeof(struct smbios_entry);
se->major_ver = SMBIOS_MAJOR_VER;
se->minor_ver = SMBIOS_MINOR_VER;
se->max_struct_size = max_struct_size;
memcpy(se->intermediate_anchor, "_DMI_", 5);
se->struct_table_length = len;
se->struct_table_address = tables;
se->struct_count = handle;
/* calculate checksums */
istart = (char *)se + SMBIOS_INTERMEDIATE_OFFSET;
isize = sizeof(struct smbios_entry) - SMBIOS_INTERMEDIATE_OFFSET;
se->intermediate_checksum = table_compute_checksum(istart, isize);
se->checksum = table_compute_checksum(se, sizeof(struct smbios_entry));
return addr;
+} diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c index f15b2e2..14b15cf 100644 --- a/arch/x86/lib/tables.c +++ b/arch/x86/lib/tables.c @@ -7,6 +7,7 @@ #include <common.h> #include <asm/sfi.h> #include <asm/mpspec.h> +#include <asm/smbios.h> #include <asm/tables.h> #include <asm/acpi_table.h>
@@ -56,4 +57,8 @@ void write_tables(void) rom_table_end = write_acpi_tables(rom_table_end); rom_table_end = ALIGN(rom_table_end, 1024); #endif +#ifdef CONFIG_GENERATE_SMBIOS_TABLE
rom_table_end = write_smbios_table(rom_table_end);
rom_table_end = ALIGN(rom_table_end, 1024);
+#endif } diff --git a/doc/README.x86 b/doc/README.x86 index a4f5321..18fed82 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -764,7 +764,6 @@ TODO List
- Audio
- Chrome OS verified boot
- SMI and ACPI support, to provide platform info and facilities to Linux
-- Desktop Management Interface (DMI) [15] support
References
@@ -782,4 +781,3 @@ References [12] http://events.linuxfoundation.org/sites/events/files/slides/chromeos_and_diy... [13] http://events.linuxfoundation.org/sites/events/files/slides/elce-2014.pdf [14] doc/device-tree-bindings/misc/intel,irq-router.txt
-[15] http://en.wikipedia.org/wiki/Desktop_Management_Interface
1.8.2.1
It might be worth adding docs to the README about what tables U-Boot now supports, how to enable each and what is recommended. There are quite a few now. My head is spinning!
Do you mean what tables in SMBIOS spec are supported by U-Boot, or what tables in PIRQ/MP/ACPI/SMBIOS tables are supported by U-Boot?
Regards, Bin

Hi Bin,
On 10 October 2015 at 04:38, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Fri, Oct 9, 2015 at 9:02 PM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 9 October 2015 at 11:17, Bin Meng bmeng.cn@gmail.com wrote:
System Management BIOS (SMBIOS) is a specification for how motherboard and system vendors present management information about their products in a standard format by extending the BIOS interface on Intel architecture systems. As of today the latest spec is 3.0 and can be downloaded from DMTF website. This commit adds a simple and minimum required implementation.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
arch/x86/Kconfig | 11 ++ arch/x86/include/asm/smbios.h | 181 +++++++++++++++++++++++++++++++ arch/x86/lib/Makefile | 1 + arch/x86/lib/smbios.c | 242 ++++++++++++++++++++++++++++++++++++++++++ arch/x86/lib/tables.c | 5 + doc/README.x86 | 2 - 6 files changed, 440 insertions(+), 2 deletions(-) create mode 100644 arch/x86/include/asm/smbios.h create mode 100644 arch/x86/lib/smbios.c
[snip]
diff --git a/doc/README.x86 b/doc/README.x86 index a4f5321..18fed82 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -764,7 +764,6 @@ TODO List
- Audio
- Chrome OS verified boot
- SMI and ACPI support, to provide platform info and facilities to Linux
-- Desktop Management Interface (DMI) [15] support
References
@@ -782,4 +781,3 @@ References [12] http://events.linuxfoundation.org/sites/events/files/slides/chromeos_and_diy... [13] http://events.linuxfoundation.org/sites/events/files/slides/elce-2014.pdf [14] doc/device-tree-bindings/misc/intel,irq-router.txt
-[15] http://en.wikipedia.org/wiki/Desktop_Management_Interface
1.8.2.1
It might be worth adding docs to the README about what tables U-Boot now supports, how to enable each and what is recommended. There are quite a few now. My head is spinning!
Do you mean what tables in SMBIOS spec are supported by U-Boot, or what tables in PIRQ/MP/ACPI/SMBIOS tables are supported by U-Boot?
I mean the latter. There are quite a few tables and it's not clear what should be used/enabled, what tables conflict, what Linux does with them, why it needs them, etc.
Regards, Simon

Hi Simon,
On Sat, Oct 10, 2015 at 1:20 PM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 10 October 2015 at 04:38, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Fri, Oct 9, 2015 at 9:02 PM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 9 October 2015 at 11:17, Bin Meng bmeng.cn@gmail.com wrote:
System Management BIOS (SMBIOS) is a specification for how motherboard and system vendors present management information about their products in a standard format by extending the BIOS interface on Intel architecture systems. As of today the latest spec is 3.0 and can be downloaded from DMTF website. This commit adds a simple and minimum required implementation.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
arch/x86/Kconfig | 11 ++ arch/x86/include/asm/smbios.h | 181 +++++++++++++++++++++++++++++++ arch/x86/lib/Makefile | 1 + arch/x86/lib/smbios.c | 242 ++++++++++++++++++++++++++++++++++++++++++ arch/x86/lib/tables.c | 5 + doc/README.x86 | 2 - 6 files changed, 440 insertions(+), 2 deletions(-) create mode 100644 arch/x86/include/asm/smbios.h create mode 100644 arch/x86/lib/smbios.c
[snip]
diff --git a/doc/README.x86 b/doc/README.x86 index a4f5321..18fed82 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -764,7 +764,6 @@ TODO List
- Audio
- Chrome OS verified boot
- SMI and ACPI support, to provide platform info and facilities to Linux
-- Desktop Management Interface (DMI) [15] support
References
@@ -782,4 +781,3 @@ References [12] http://events.linuxfoundation.org/sites/events/files/slides/chromeos_and_diy... [13] http://events.linuxfoundation.org/sites/events/files/slides/elce-2014.pdf [14] doc/device-tree-bindings/misc/intel,irq-router.txt
-[15] http://en.wikipedia.org/wiki/Desktop_Management_Interface
1.8.2.1
It might be worth adding docs to the README about what tables U-Boot now supports, how to enable each and what is recommended. There are quite a few now. My head is spinning!
Do you mean what tables in SMBIOS spec are supported by U-Boot, or what tables in PIRQ/MP/ACPI/SMBIOS tables are supported by U-Boot?
I mean the latter. There are quite a few tables and it's not clear what should be used/enabled, what tables conflict, what Linux does with them, why it needs them, etc.
OK, maybe we can document this when ACPI support is ready?
Regards, Bin

Hi Bin,
On 10 October 2015 at 08:13, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Sat, Oct 10, 2015 at 1:20 PM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 10 October 2015 at 04:38, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Fri, Oct 9, 2015 at 9:02 PM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 9 October 2015 at 11:17, Bin Meng bmeng.cn@gmail.com wrote:
System Management BIOS (SMBIOS) is a specification for how motherboard and system vendors present management information about their products in a standard format by extending the BIOS interface on Intel architecture systems. As of today the latest spec is 3.0 and can be downloaded from DMTF website. This commit adds a simple and minimum required implementation.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
arch/x86/Kconfig | 11 ++ arch/x86/include/asm/smbios.h | 181 +++++++++++++++++++++++++++++++ arch/x86/lib/Makefile | 1 + arch/x86/lib/smbios.c | 242 ++++++++++++++++++++++++++++++++++++++++++ arch/x86/lib/tables.c | 5 + doc/README.x86 | 2 - 6 files changed, 440 insertions(+), 2 deletions(-) create mode 100644 arch/x86/include/asm/smbios.h create mode 100644 arch/x86/lib/smbios.c
[snip]
diff --git a/doc/README.x86 b/doc/README.x86 index a4f5321..18fed82 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -764,7 +764,6 @@ TODO List
- Audio
- Chrome OS verified boot
- SMI and ACPI support, to provide platform info and facilities to Linux
-- Desktop Management Interface (DMI) [15] support
References
@@ -782,4 +781,3 @@ References [12] http://events.linuxfoundation.org/sites/events/files/slides/chromeos_and_diy... [13] http://events.linuxfoundation.org/sites/events/files/slides/elce-2014.pdf [14] doc/device-tree-bindings/misc/intel,irq-router.txt
-[15] http://en.wikipedia.org/wiki/Desktop_Management_Interface
1.8.2.1
It might be worth adding docs to the README about what tables U-Boot now supports, how to enable each and what is recommended. There are quite a few now. My head is spinning!
Do you mean what tables in SMBIOS spec are supported by U-Boot, or what tables in PIRQ/MP/ACPI/SMBIOS tables are supported by U-Boot?
I mean the latter. There are quite a few tables and it's not clear what should be used/enabled, what tables conflict, what Linux does with them, why it needs them, etc.
OK, maybe we can document this when ACPI support is ready?
Anytime is fine with me.
Regards, Simon

On 9 October 2015 at 11:17, Bin Meng bmeng.cn@gmail.com wrote:
Add U_BOOT_DMI_DATE (format mm/dd/yyyy) generation to be used by SMBIOS tables, as required by SMBIOS spec 3.0 [1]. See chapter 7.1, BIOS information structure offset 08h for details.
[1] http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.0.0.pd...
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Makefile | 2 ++ 1 file changed, 2 insertions(+)
Acked-by: Simon Glass sjg@chromium.org
participants (2)
-
Bin Meng
-
Simon Glass