summaryrefslogtreecommitdiff
path: root/dmidecode.c
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff.email>2026-03-10 09:31:17 +0100
committerJörg Frings-Fürst <debian@jff.email>2026-03-10 09:31:17 +0100
commit22f77b46ab555f57523990094a3e40a55f2c492a (patch)
tree0b2dad175ecf9514c5c9d8fb9473010c2337a3b3 /dmidecode.c
parentc9aac994d65f7bcc3659e3219d6729a24c803fcf (diff)
New upstream version 3.7upstream/3.7upstream
Diffstat (limited to 'dmidecode.c')
-rw-r--r--dmidecode.c377
1 files changed, 240 insertions, 137 deletions
diff --git a/dmidecode.c b/dmidecode.c
index 45a6c06..463f12b 100644
--- a/dmidecode.c
+++ b/dmidecode.c
@@ -2,7 +2,7 @@
* DMI Decode
*
* Copyright (C) 2000-2002 Alan Cox <alan@redhat.com>
- * Copyright (C) 2002-2024 Jean Delvare <jdelvare@suse.de>
+ * Copyright (C) 2002-2025 Jean Delvare <jdelvare@suse.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -85,12 +85,11 @@
#include "dmioem.h"
#include "dmioutput.h"
-#define out_of_spec "<OUT OF SPEC>"
static const char *bad_index = "<BAD INDEX>";
enum cpuid_type cpuid_type = cpuid_none;
-#define SUPPORTED_SMBIOS_VER 0x030700
+#define SUPPORTED_SMBIOS_VER 0x030900
#define FLAG_NO_FILE_OFFSET (1 << 0)
#define FLAG_STOP_AT_EOT (1 << 1)
@@ -163,7 +162,7 @@ const char *dmi_string(const struct dmi_header *dm, u8 s)
static const char *dmi_smbios_structure_type(u8 code)
{
static const char *type[] = {
- "BIOS", /* 0 */
+ "Platform Firmware", /* 0 */
"System",
"Base Board",
"Chassis",
@@ -176,7 +175,7 @@ static const char *dmi_smbios_structure_type(u8 code)
"On Board Devices",
"OEM Strings",
"System Configuration Options",
- "BIOS Language",
+ "Firmware Language",
"Group Associations",
"System Event Log",
"Physical Memory Array",
@@ -274,28 +273,29 @@ static void dmi_dump(const struct dmi_header *h)
}
}
-/* shift is 0 if the value is in bytes, 1 if it is in kilobytes */
-void dmi_print_memory_size(const char *attr, u64 code, int shift)
+/* shift is 0 if the value is in bytes, 1 if it is in kibibytes */
+void dmi_print_memory_size(void (*print_cb)(const char *name, const char *format, ...),
+ const char *attr, u64 code, int shift)
{
unsigned long capacity;
u16 split[7];
static const char *unit[8] = {
- "bytes", "kB", "MB", "GB", "TB", "PB", "EB", "ZB"
+ "bytes", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB"
};
int i;
/*
- * We split the overall size in powers of thousand: EB, PB, TB, GB,
- * MB, kB and B. In practice, it is expected that only one or two
+ * We split the overall size in powers of 1024: EiB, PiB, TiB, GiB,
+ * MiB, KiB and B. In practice, it is expected that only one or two
* (consecutive) of these will be non-zero.
*/
- split[0] = code.l & 0x3FFUL;
- split[1] = (code.l >> 10) & 0x3FFUL;
- split[2] = (code.l >> 20) & 0x3FFUL;
- split[3] = ((code.h << 2) & 0x3FCUL) | (code.l >> 30);
- split[4] = (code.h >> 8) & 0x3FFUL;
- split[5] = (code.h >> 18) & 0x3FFUL;
- split[6] = code.h >> 28;
+ split[0] = code & 0x3FFULL;
+ split[1] = (code >> 10) & 0x3FFULL;
+ split[2] = (code >> 20) & 0x3FFULL;
+ split[3] = (code >> 30) & 0x3FFULL;
+ split[4] = (code >> 40) & 0x3FFULL;
+ split[5] = (code >> 50) & 0x3FFULL;
+ split[6] = (code >> 60) & 0x3FFULL;
/*
* Now we find the highest unit with a non-zero value. If the following
@@ -315,11 +315,33 @@ void dmi_print_memory_size(const char *attr, u64 code, int shift)
else
capacity = split[i];
- pr_attr(attr, "%lu %s", capacity, unit[i + shift]);
+ print_cb(attr, "%lu %s", capacity, unit[i + shift]);
+}
+
+/* shift is 0 if the value is in bytes, 1 if it is in kB, 2 if it is in MB */
+void dmi_print_storage_size(const char *attr, u64 code, unsigned int shift)
+{
+ u64 divisor;
+ static const char *unit[8] = {
+ "bytes", "kB", "MB", "GB", "TB", "PB", "EB", "ZB"
+ };
+
+ /*
+ * We want to choose the unit which will let us display a number
+ * between 1.0 and 999.9.
+ */
+ divisor = 1;
+ while (code / divisor >= 1000 && shift + 1 < ARRAY_SIZE(unit))
+ {
+ shift++;
+ divisor *= 1000;
+ }
+
+ pr_attr(attr, "%.1f %s", (float)code / divisor, unit[shift]);
}
/*
- * 7.1 BIOS Information (Type 0)
+ * 7.1 Platform Firmware Information (Type 0)
*/
static void dmi_bios_runtime_size(u32 code)
@@ -332,7 +354,7 @@ static void dmi_bios_runtime_size(u32 code)
}
else
{
- format = "%u kB";
+ format = "%u KiB";
code >>= 10;
}
@@ -342,13 +364,12 @@ static void dmi_bios_runtime_size(u32 code)
static void dmi_bios_rom_size(u8 code1, u16 code2)
{
static const char *unit[4] = {
- "MB", "GB", out_of_spec, out_of_spec
+ "MiB", "GiB", out_of_spec, out_of_spec
};
if (code1 != 0xFF)
{
- u64 s = { .l = (code1 + 1) << 6 };
- dmi_print_memory_size("ROM Size", s, 1);
+ dmi_print_memory_size(pr_attr, "ROM Size", (u64)(code1 + 1) << 6, 1);
}
else
pr_attr("ROM Size", "%u %s", code2 & 0x3FFF, unit[code2 >> 14]);
@@ -358,7 +379,7 @@ static void dmi_bios_characteristics(u64 code)
{
/* 7.1.1 */
static const char *characteristics[] = {
- "BIOS characteristics not supported", /* 3 */
+ "Firmware characteristics not supported", /* 3 */
"ISA is supported",
"MCA is supported",
"EISA is supported",
@@ -366,13 +387,13 @@ static void dmi_bios_characteristics(u64 code)
"PC Card (PCMCIA) is supported",
"PNP is supported",
"APM is supported",
- "BIOS is upgradeable",
- "BIOS shadowing is allowed",
+ "Firmware is upgradeable",
+ "Firmware shadowing is allowed",
"VLB is supported",
"ESCD support is available",
"Boot from CD is supported",
"Selectable boot is supported",
- "BIOS ROM is socketed",
+ "Firmware ROM is socketed",
"Boot from PC Card (PCMCIA) is supported",
"EDD is supported",
"Japanese floppy for NEC 9800 1.2 MB is supported (int 13h)",
@@ -393,14 +414,14 @@ static void dmi_bios_characteristics(u64 code)
/*
* This isn't very clear what this bit is supposed to mean
*/
- if (code.l & (1 << 3))
+ if (code & (1ULL << 3))
{
pr_list_item("%s", characteristics[0]);
return;
}
for (i = 4; i <= 31; i++)
- if (code.l & (1 << i))
+ if (code & (1ULL << i))
pr_list_item("%s", characteristics[i - 3]);
}
@@ -447,8 +468,8 @@ static void dmi_bios_characteristics_x2(u8 code)
* 7.2 System Information (Type 1)
*/
-static void dmi_system_uuid(void (*print_cb)(const char *name, const char *format, ...),
- const char *attr, const u8 *p, u16 ver)
+void dmi_system_uuid(void (*print_cb)(const char *name, const char *format, ...),
+ const char *attr, const u8 *p, u16 ver)
{
int only0xFF = 1, only0x00 = 1;
int i;
@@ -626,10 +647,10 @@ static const char *dmi_chassis_type(u8 code)
"Rack Mount Chassis",
"Sealed-case PC",
"Multi-system",
- "CompactPCI",
- "AdvancedTCA",
+ "Compact PCI",
+ "Advanced TCA",
"Blade",
- "Blade Enclosing",
+ "Blade Enclosure",
"Tablet",
"Convertible",
"Detachable",
@@ -730,6 +751,18 @@ static void dmi_chassis_elements(u8 count, u8 len, const u8 *p)
pr_list_end();
}
+static const char *dmi_chassis_rack_type(u8 code)
+{
+ static const char *type[] = {
+ "Unspecified", /* 0x00 */
+ "OU" /* 0x01 */
+ };
+
+ if (code <= 0x01)
+ return type[code];
+ return out_of_spec;
+}
+
/*
* 7.5 Processor Information (Type 4)
*/
@@ -942,6 +975,7 @@ static const char *dmi_processor_family(const struct dmi_header *h, u16 ver)
{ 0xCD, "Core i5" },
{ 0xCE, "Core i3" },
{ 0xCF, "Core i9" },
+ { 0xD0, "Xeon D" },
{ 0xD2, "C7-M" },
{ 0xD3, "C7-D" },
@@ -1011,6 +1045,15 @@ static const char *dmi_processor_family(const struct dmi_header *h, u16 ver)
{ 0x26F, "Multi-Core Loongson 3B 5xxx" },
{ 0x270, "Multi-Core Loongson 3C 5xxx" },
{ 0x271, "Multi-Core Loongson 3D 5xxx" },
+
+ { 0x300, "Core 3" },
+ { 0x301, "Core 5" },
+ { 0x302, "Core 7" },
+ { 0x303, "Core 9" },
+ { 0x304, "Core Ultra 3" },
+ { 0x305, "Core Ultra 5" },
+ { 0x306, "Core Ultra 7" },
+ { 0x307, "Core Ultra 9" },
};
/*
* Note to developers: when adding entries to this list, check if
@@ -1140,8 +1183,9 @@ static enum cpuid_type dmi_get_cpuid_type(const struct dmi_header *h)
void dmi_print_cpuid(void (*print_cb)(const char *name, const char *format, ...),
const char *label, enum cpuid_type sig, const u8 *p)
{
- u32 eax, midr, jep106, soc_revision;
- u16 dx;
+ u32 eax, midr, soc_revision;
+ u16 dx, soc_id;
+ u8 jep106_code, jep106_bank;
switch (sig)
{
@@ -1181,12 +1225,12 @@ void dmi_print_cpuid(void (*print_cb)(const char *name, const char *format, ...)
case cpuid_arm_soc_id: /* ARM with SOC ID */
/*
- * If Soc ID is supported, the first DWORD is the JEP-106 code;
- * the second DWORD is the SoC revision value.
- */
- jep106 = DWORD(p);
- soc_revision = DWORD(p + 4);
- /*
+ * If SoC ID is supported, the first WORD is a SiP
+ * defined SoC ID; the next BYTE is the JEP-106
+ * identification code of the SiP; the next BYTE is
+ * its bank index; lastly, the next DWORD is the SoC
+ * revision value.
+ *
* According to SMC Calling Convention (SMCCC) v1.3 specification
* (https://developer.arm.com/documentation/den0028/d/), the format
* of the values returned by the SMCCC_ARCH_SOC_ID call is as follows:
@@ -1201,9 +1245,14 @@ void dmi_print_cpuid(void (*print_cb)(const char *name, const char *format, ...)
* Bit[31] must be zero
* Bits[30:0] SoC revision
*/
+ soc_id = WORD(p);
+ jep106_code = p[2] & 0x7F;
+ jep106_bank = p[3] & 0x7F;
+ soc_revision = DWORD(p + 4);
+
pr_attr("Signature",
"JEP-106 Bank 0x%02x Manufacturer 0x%02x, SoC ID 0x%04x, SoC Revision 0x%08x",
- (jep106 >> 24) & 0x7F, (jep106 >> 16) & 0x7F, jep106 & 0xFFFF, soc_revision);
+ jep106_bank, jep106_code, soc_id, soc_revision);
return;
case cpuid_x86_intel: /* Intel */
@@ -1369,8 +1418,8 @@ static const char *dmi_processor_status(u8 code)
static const char *status[] = {
"Unknown", /* 0x00 */
"Enabled",
- "Disabled By User",
- "Disabled By BIOS",
+ "Disabled by user",
+ "Disabled by firmware",
"Idle", /* 0x04 */
out_of_spec,
out_of_spec,
@@ -1463,10 +1512,17 @@ static const char *dmi_processor_upgrade(u8 code)
"Socket BGA1190",
"Socket BGA4129",
"Socket LGA4710",
- "Socket LGA7529" /* 0x50 */
+ "Socket LGA7529",
+ "Socket BGA1964",
+ "Socket BGA1792",
+ "Socket BGA2049",
+ "Socket BGA2551",
+ "Socket LGA1851",
+ "Socket BGA2114",
+ "Socket BGA2833" /* 0x57 */
};
- if (code >= 0x01 && code <= 0x50)
+ if (code >= 0x01 && code <= 0x57)
return upgrade[code - 0x01];
return out_of_spec;
}
@@ -1710,7 +1766,7 @@ static void dmi_memory_module_size(const char *attr, u8 code)
pr_attr(attr, "Not Installed");
return;
default:
- pr_attr(attr, "%u MB%s", 1 << (code & 0x7F),
+ pr_attr(attr, "%u MiB%s", 1 << (code & 0x7F),
connection);
}
}
@@ -1765,18 +1821,16 @@ static void dmi_cache_size_2(const char *attr, u32 code)
if (code & 0x80000000)
{
- code &= 0x7FFFFFFFLU;
- size.l = code << 6;
- size.h = code >> 26;
+ code &= 0x7FFFFFFFULL;
+ size = (u64)code << 6;
}
else
{
- size.l = code;
- size.h = 0;
+ size = code;
}
/* Use a more convenient unit for large cache size */
- dmi_print_memory_size(attr, size, 1);
+ dmi_print_memory_size(pr_attr, attr, size, 1);
}
static void dmi_cache_size(const char *attr, u16 code)
@@ -2009,7 +2063,7 @@ static const char *dmi_port_type(u8 code)
* 7.10 System Slots (Type 9)
*/
-static const char *dmi_slot_type(u8 code)
+static void dmi_slot_type(u8 code, u8 length)
{
/* 7.10.1 */
static const char *type[] = {
@@ -2102,14 +2156,35 @@ static const char *dmi_slot_type(u8 code)
* Note to developers: when adding entries to these lists, check if
* function dmi_slot_id below needs updating too.
*/
+ const char *t, *suffix = "";
if (code >= 0x01 && code <= 0x28)
- return type[code - 0x01];
- if (code == 0x30)
- return type_0x30[code - 0x30];
- if (code >= 0xA0 && code <= 0xC6)
- return type_0xA0[code - 0xA0];
- return out_of_spec;
+ t = type[code - 0x01];
+ else if (code == 0x30)
+ t = type_0x30[code - 0x30];
+ else if (code >= 0xA0 && code <= 0xC6)
+ t = type_0xA0[code - 0xA0];
+ else
+ t = out_of_spec;
+
+ /* For EDSFF slots, add the length suffix */
+ switch (code)
+ {
+ case 0xC5: /* EDSFF E1 */
+ case 0xC6: /* EDSFF E3 */
+ switch (length)
+ {
+ case 0x03: /* Short */
+ suffix = ".S";
+ break;
+ case 0x04: /* Long */
+ suffix = ".L";
+ break;
+ }
+ break;
+ }
+
+ pr_attr("Type", "%s%s", t, suffix);
}
static const char *dmi_slot_bus_width(u8 code)
@@ -2188,11 +2263,20 @@ static void dmi_slot_id(u8 code1, u8 code2, u8 type)
case 0x11: /* AGP */
case 0x12: /* PCI-X */
case 0x13: /* AGP */
- case 0x1F: /* PCI Express 2 */
- case 0x20: /* PCI Express 3 */
+ case 0x14: /* M.2 */
+ case 0x15: /* M.2 */
+ case 0x16: /* M.2 */
+ case 0x17: /* M.2 */
+ case 0x1F: /* PCI Express 2 (U.2) */
+ case 0x20: /* PCI Express 3 (U.2) */
case 0x21: /* PCI Express Mini */
case 0x22: /* PCI Express Mini */
case 0x23: /* PCI Express Mini */
+ case 0x24: /* PCI Express 4 (U.2) */
+ case 0x25: /* PCI Express 5 (U.2) */
+ case 0x26: /* OCP */
+ case 0x27: /* OCP */
+ case 0x28: /* OCP */
case 0xA5: /* PCI Express */
case 0xA6: /* PCI Express */
case 0xA7: /* PCI Express */
@@ -2224,6 +2308,8 @@ static void dmi_slot_id(u8 code1, u8 code2, u8 type)
case 0xC2: /* PCI Express 5 */
case 0xC3: /* PCI Express 5 */
case 0xC4: /* PCI Express 6+ */
+ case 0xC5: /* EDSFF */
+ case 0xC6: /* EDSFF */
pr_attr("ID", "%u", code1);
break;
case 0x07: /* PCMCIA */
@@ -2461,7 +2547,7 @@ static void dmi_system_configuration_options(const struct dmi_header *h)
}
/*
- * 7.14 BIOS Language Information (Type 13)
+ * 7.14 Firmware Language Information (Type 13)
*/
static void dmi_bios_languages(const struct dmi_header *h)
@@ -2752,10 +2838,10 @@ static void dmi_memory_device_size(u16 code)
pr_attr("Size", "Unknown");
else
{
- u64 s = { .l = code & 0x7FFF };
+ u64 s = (u64)code & 0x7FFFULL;
if (!(code & 0x8000))
- s.l <<= 10;
- dmi_print_memory_size("Size", s, 1);
+ s <<= 10;
+ dmi_print_memory_size(pr_attr, "Size", s, 1);
}
}
@@ -2768,11 +2854,11 @@ static void dmi_memory_device_extended_size(u32 code)
* as an integer without rounding
*/
if (code & 0x3FFUL)
- pr_attr("Size", "%lu MB", (unsigned long)code);
+ pr_attr("Size", "%lu MiB", (unsigned long)code);
else if (code & 0xFFC00UL)
- pr_attr("Size", "%lu GB", (unsigned long)code >> 10);
+ pr_attr("Size", "%lu GiB", (unsigned long)code >> 10);
else
- pr_attr("Size", "%lu TB", (unsigned long)code >> 20);
+ pr_attr("Size", "%lu TiB", (unsigned long)code >> 20);
}
static void dmi_memory_voltage_value(const char *attr, u16 code)
@@ -2803,10 +2889,13 @@ static const char *dmi_memory_device_form_factor(u8 code)
"SODIMM",
"SRIMM",
"FB-DIMM",
- "Die" /* 0x10 */
+ "Die",
+ "CAMM",
+ "CUDIMM",
+ "CSODIMM" /* 0x13 */
};
- if (code >= 0x01 && code <= 0x10)
+ if (code >= 0x01 && code <= 0x13)
return form_factor[code - 0x01];
return out_of_spec;
}
@@ -2860,10 +2949,11 @@ static const char *dmi_memory_device_type(u8 code)
"HBM2",
"DDR5",
"LPDDR5",
- "HBM3" /* 0x24 */
+ "HBM3",
+ "MRDIMM" /* 0x25 */
};
- if (code >= 0x01 && code <= 0x24)
+ if (code >= 0x01 && code <= 0x25)
return type[code - 0x01];
return out_of_spec;
}
@@ -2923,7 +3013,7 @@ static void dmi_memory_device_speed(const char *attr, u16 code1, u32 code2)
}
}
-static void dmi_memory_technology(u8 code)
+static const char *dmi_memory_technology(u8 code)
{
/* 7.18.6 */
static const char * const technology[] = {
@@ -2933,12 +3023,12 @@ static void dmi_memory_technology(u8 code)
"NVDIMM-N",
"NVDIMM-F",
"NVDIMM-P",
- "Intel Optane DC persistent memory" /* 0x07 */
+ "Intel Optane persistent memory",
+ "MRDIMM" /* 0x08 */
};
- if (code >= 0x01 && code <= 0x07)
- pr_attr("Memory Technology", "%s", technology[code - 0x01]);
- else
- pr_attr("Memory Technology", "%s", out_of_spec);
+ if (code >= 0x01 && code <= 0x08)
+ return technology[code - 0x01];
+ return out_of_spec;
}
static void dmi_memory_operating_mode_capability(u16 code)
@@ -2967,7 +3057,7 @@ static void dmi_memory_operating_mode_capability(u16 code)
}
}
-static void dmi_memory_manufacturer_id(const char *attr, u16 code)
+void dmi_memory_manufacturer_id(const char *attr, u16 code)
{
/* 7.18.8 */
/* 7.18.10 */
@@ -2981,7 +3071,7 @@ static void dmi_memory_manufacturer_id(const char *attr, u16 code)
(code & 0x7F) + 1, code >> 8);
}
-static void dmi_memory_product_id(const char *attr, u16 code)
+void dmi_memory_product_id(const char *attr, u16 code)
{
/* 7.18.9 */
/* 7.18.11 */
@@ -2995,12 +3085,12 @@ static void dmi_memory_size(const char *attr, u64 code)
{
/* 7.18.12 */
/* 7.18.13 */
- if (code.h == 0xFFFFFFFF && code.l == 0xFFFFFFFF)
+ if (code == ~0ULL)
pr_attr(attr, "Unknown");
- else if (code.h == 0x0 && code.l == 0x0)
+ else if (code == 0ULL)
pr_attr(attr, "None");
else
- dmi_print_memory_size(attr, code, 0);
+ dmi_print_memory_size(pr_attr, attr, code, 0);
}
static void dmi_memory_revision(const char *attr_type, u16 code, u8 mem_type)
@@ -3127,21 +3217,15 @@ static void dmi_mapped_address_size(u32 code)
if (code == 0)
pr_attr("Range Size", "Invalid");
else
- {
- u64 size;
-
- size.h = 0;
- size.l = code;
- dmi_print_memory_size("Range Size", size, 1);
- }
+ dmi_print_memory_size(pr_attr, "Range Size", (u64)code, 1);
}
static void dmi_mapped_address_extended_size(u64 start, u64 end)
{
- if (start.h == end.h && start.l == end.l)
+ if (start == end)
pr_attr("Range Size", "Invalid");
else
- dmi_print_memory_size("Range Size", u64_range(start, end), 0);
+ dmi_print_memory_size(pr_attr, "Range Size", end - start + 1, 0);
}
/*
@@ -3566,10 +3650,10 @@ static const char *dmi_system_boot_status(u8 code)
static void dmi_64bit_memory_error_address(const char *attr, u64 code)
{
- if (code.h == 0x80000000 && code.l == 0x00000000)
+ if (code == 0x8000000000000000ULL)
pr_attr(attr, "Unknown");
else
- pr_attr(attr, "0x%08X%08X", code.h, code.l);
+ pr_attr(attr, "0x%016llX", code);
}
/*
@@ -3703,9 +3787,9 @@ static void dmi_ipmi_base_address(u8 type, const u8 *p, u8 lsb)
else
{
u64 address = QWORD(p);
- pr_attr("Base Address", "0x%08X%08X (%s)",
- address.h, (address.l & ~1) | lsb,
- address.l & 1 ? "I/O" : "Memory-mapped");
+ pr_attr("Base Address", "0x%016llX (%s)",
+ (address & ~1ULL) | lsb,
+ (address & 1ULL) ? "I/O" : "Memory-mapped");
}
}
@@ -4374,14 +4458,14 @@ static void dmi_tpm_characteristics(u64 code)
/*
* This isn't very clear what this bit is supposed to mean
*/
- if (code.l & (1 << 2))
+ if (code & (1ULL << 2))
{
pr_list_item("%s", characteristics[0]);
return;
}
for (i = 3; i <= 5; i++)
- if (code.l & (1 << i))
+ if (code & (1ULL << i))
pr_list_item("%s", characteristics[i - 2]);
}
@@ -4445,8 +4529,8 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
*/
switch (h->type)
{
- case 0: /* 7.1 BIOS Information */
- pr_handle_name("BIOS Information");
+ case 0: /* 7.1 Platform Firmware Information */
+ pr_handle_name("Platform Firmware Information");
if (h->length < 0x12) break;
pr_attr("Vendor", "%s",
dmi_string(h, data[0x04]));
@@ -4468,17 +4552,17 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
dmi_bios_rom_size(data[0x09], h->length < 0x1A ? 16 : WORD(data + 0x18));
pr_list_start("Characteristics", NULL);
dmi_bios_characteristics(QWORD(data + 0x0A));
+ if (h->length >= 0x13)
+ dmi_bios_characteristics_x1(data[0x12]);
+ if (h->length >= 0x14)
+ dmi_bios_characteristics_x2(data[0x13]);
pr_list_end();
- if (h->length < 0x13) break;
- dmi_bios_characteristics_x1(data[0x12]);
- if (h->length < 0x14) break;
- dmi_bios_characteristics_x2(data[0x13]);
if (h->length < 0x18) break;
if (data[0x14] != 0xFF && data[0x15] != 0xFF)
- pr_attr("BIOS Revision", "%u.%u",
+ pr_attr("Platform Firmware Revision", "%u.%u",
data[0x14], data[0x15]);
if (data[0x16] != 0xFF && data[0x17] != 0xFF)
- pr_attr("Firmware Revision", "%u.%u",
+ pr_attr("Embedded Controller Firmware Revision", "%u.%u",
data[0x16], data[0x17]);
break;
@@ -4562,14 +4646,32 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
pr_attr("OEM Information", "0x%08X",
DWORD(data + 0x0D));
if (h->length < 0x13) break;
- dmi_chassis_height(data[0x11]);
+ if (data[0x11] != 0xFF)
+ dmi_chassis_height(data[0x11]);
dmi_chassis_power_cords(data[0x12]);
if (h->length < 0x15) break;
if (h->length < 0x15 + data[0x13] * data[0x14]) break;
dmi_chassis_elements(data[0x13], data[0x14], data + 0x15);
if (h->length < 0x16 + data[0x13] * data[0x14]) break;
- pr_attr("SKU Number", "%s",
- dmi_string(h, data[0x15 + data[0x13] * data[0x14]]));
+ /*
+ * Many old implementations have stray zero bytes at
+ * the end of this record, probably due to some
+ * confusion regarding the preceding variable length
+ * section. Only decode the following fields if they
+ * are defined in the SMBIOS specification version
+ * which is implemented.
+ */
+ if (ver >= 0x0207)
+ pr_attr("SKU Number", "%s",
+ dmi_string(h, data[0x15 + data[0x13] * data[0x14]]));
+ if (h->length < 0x18 + data[0x13] * data[0x14]) break;
+ if (ver >= 0x0309)
+ {
+ pr_attr("Rack Type", "%s",
+ dmi_chassis_rack_type(data[0x16 + data[0x13] * data[0x14]]));
+ pr_attr("Rack Height", "%hhu",
+ data[0x17 + data[0x13] * data[0x14]]);
+ }
break;
case 4: /* 7.5 Processor Information */
@@ -4586,7 +4688,12 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
dmi_processor_id(h);
pr_attr("Version", "%s",
dmi_string(h, data[0x10]));
- dmi_processor_voltage("Voltage", data[0x11]);
+ /*
+ * Since SMBIOS 3.8.0, the processor voltage field
+ * is deprecated, so ignore it if no value is set.
+ */
+ if (data[0x11])
+ dmi_processor_voltage("Voltage", data[0x11]);
dmi_processor_frequency("External Clock", data + 0x12);
dmi_processor_frequency("Max Speed", data + 0x14);
dmi_processor_frequency("Current Speed", data + 0x16);
@@ -4645,9 +4752,9 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
dmi_memory_controller_interleave(data[0x06]));
pr_attr("Current Interleave", "%s",
dmi_memory_controller_interleave(data[0x07]));
- pr_attr("Maximum Memory Module Size", "%u MB",
+ pr_attr("Maximum Memory Module Size", "%u MiB",
1 << data[0x08]);
- pr_attr("Maximum Total Memory Size", "%u MB",
+ pr_attr("Maximum Total Memory Size", "%u MiB",
data[0x0E] * (1 << data[0x08]));
dmi_memory_controller_speeds("Supported Speeds",
WORD(data + 0x09));
@@ -4727,7 +4834,7 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
if (h->length < 0x0C) break;
pr_attr("Designation", "%s",
dmi_string(h, data[0x04]));
- pr_attr("Type", "%s", dmi_slot_type(data[0x05]));
+ dmi_slot_type(data[0x05], data[0x08]);
pr_attr("Data Bus Width", "%s", dmi_slot_bus_width(data[0x06]));
pr_attr("Current Usage", "%s",
dmi_slot_current_usage(data[0x07]));
@@ -4770,8 +4877,8 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
dmi_system_configuration_options(h);
break;
- case 13: /* 7.14 BIOS Language Information */
- pr_handle_name("BIOS Language Information");
+ case 13: /* 7.14 Firmware Language Information */
+ pr_handle_name("Firmware Language Information");
if (h->length < 0x16) break;
if (ver >= 0x0201)
{
@@ -4838,17 +4945,15 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
if (h->length < 0x17)
pr_attr("Maximum Capacity", "Unknown");
else
- dmi_print_memory_size("Maximum Capacity",
+ dmi_print_memory_size(pr_attr,
+ "Maximum Capacity",
QWORD(data + 0x0F), 0);
}
else
{
- u64 capacity;
-
- capacity.h = 0;
- capacity.l = DWORD(data + 0x07);
- dmi_print_memory_size("Maximum Capacity",
- capacity, 1);
+ dmi_print_memory_size(pr_attr,
+ "Maximum Capacity",
+ DWORD(data + 0x07), 1);
}
if (!(opt.flags & FLAG_QUIET))
dmi_memory_array_error_handle(WORD(data + 0x0B));
@@ -4915,7 +5020,8 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
dmi_memory_voltage_value("Configured Voltage",
WORD(data + 0x26));
if (h->length < 0x34) break;
- dmi_memory_technology(data[0x28]);
+ pr_attr("Memory Technology", "%s",
+ dmi_memory_technology(data[0x28]));
dmi_memory_operating_mode_capability(WORD(data + 0x29));
pr_attr("Firmware Version", "%s",
dmi_string(h, data[0x2B]));
@@ -4974,10 +5080,8 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
start = QWORD(data + 0x0F);
end = QWORD(data + 0x17);
- pr_attr("Starting Address", "0x%08X%08Xk",
- start.h, start.l);
- pr_attr("Ending Address", "0x%08X%08Xk",
- end.h, end.l);
+ pr_attr("Starting Address", "0x%016llX", start);
+ pr_attr("Ending Address", "0x%016llX", end);
dmi_mapped_address_extended_size(start, end);
}
else
@@ -5007,10 +5111,8 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
start = QWORD(data + 0x13);
end = QWORD(data + 0x1B);
- pr_attr("Starting Address", "0x%08X%08Xk",
- start.h, start.l);
- pr_attr("Ending Address", "0x%08X%08Xk",
- end.h, end.l);
+ pr_attr("Starting Address", "0x%016llX", start);
+ pr_attr("Ending Address", "0x%016llX", end);
dmi_mapped_address_extended_size(start, end);
}
else
@@ -5529,7 +5631,7 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
break;
default:
- if (dmi_decode_oem(h))
+ if (dmi_decode_oem(h, ver))
break;
if (opt.flags & FLAG_QUIET)
return;
@@ -5932,7 +6034,8 @@ static int smbios3_decode(u8 *buf, size_t buf_len, const char *devmem, u32 flags
buf[0x07], buf[0x08], buf[0x09]);
offset = QWORD(buf + 0x10);
- if (!(flags & FLAG_NO_FILE_OFFSET) && offset.h && sizeof(off_t) < 8)
+ if (!(flags & FLAG_NO_FILE_OFFSET) && (offset & 0xFFFFFFFF00000000ULL)
+ && sizeof(off_t) < 8)
{
fprintf(stderr, "64-bit addresses not supported, sorry.\n");
return 0;
@@ -5940,7 +6043,7 @@ static int smbios3_decode(u8 *buf, size_t buf_len, const char *devmem, u32 flags
/* Maximum length, may get trimmed */
len = DWORD(buf + 0x0C);
- table = dmi_table_get(((off_t)offset.h << 32) | offset.l, &len, 0, ver,
+ table = dmi_table_get(offset, &len, 0, ver,
devmem, flags | FLAG_STOP_AT_EOT);
if (table == NULL)
return 1;