summaryrefslogtreecommitdiffstats
path: root/dmidecode.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-08-26 10:28:19 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-08-26 10:28:19 +0000
commit624faf9194e73e0913ccb67bc7154c1b6a2c0aed (patch)
treeb6540eac4774f6fd2a4c52a2ee2a85209e8cd312 /dmidecode.c
parentReleasing progress-linux version 3.5-3~progress7.99u1. (diff)
downloaddmidecode-624faf9194e73e0913ccb67bc7154c1b6a2c0aed.tar.xz
dmidecode-624faf9194e73e0913ccb67bc7154c1b6a2c0aed.zip
Merging upstream version 3.6.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dmidecode.c')
-rw-r--r--dmidecode.c387
1 files changed, 296 insertions, 91 deletions
diff --git a/dmidecode.c b/dmidecode.c
index 54f59c1..45a6c06 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-2020 Jean Delvare <jdelvare@suse.de>
+ * Copyright (C) 2002-2024 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
@@ -57,7 +57,9 @@
* Family "2.0", Level 00, Revision 00.43, January 26, 2015
* https://trustedcomputinggroup.org/pc-client-platform-tpm-profile-ptp-specification/
* - "RedFish Host Interface Specification" (DMTF DSP0270)
- * https://www.dmtf.org/sites/default/files/DSP0270_1.0.1.pdf
+ * https://www.dmtf.org/sites/default/files/standards/documents/DSP0270_1.3.0.pdf
+ * - LoongArch Reference Manual, volume 1
+ * https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_cpucfg
*/
#include <fcntl.h>
@@ -69,7 +71,7 @@
#include <arpa/inet.h>
#include <sys/socket.h>
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__DragonFly__)
#include <errno.h>
#include <kenv.h>
#endif
@@ -88,7 +90,7 @@ static const char *bad_index = "<BAD INDEX>";
enum cpuid_type cpuid_type = cpuid_none;
-#define SUPPORTED_SMBIOS_VER 0x030500
+#define SUPPORTED_SMBIOS_VER 0x030700
#define FLAG_NO_FILE_OFFSET (1 << 0)
#define FLAG_STOP_AT_EOT (1 << 1)
@@ -781,6 +783,7 @@ static const char *dmi_processor_family(const struct dmi_header *h, u16 ver)
{ 0x13, "M2" },
{ 0x14, "Celeron M" },
{ 0x15, "Pentium 4 HT" },
+ { 0x16, "Intel" },
{ 0x18, "Duron" },
{ 0x19, "K5" },
@@ -974,6 +977,8 @@ static const char *dmi_processor_family(const struct dmi_header *h, u16 ver)
{ 0x100, "ARMv7" },
{ 0x101, "ARMv8" },
+ { 0x102, "ARMv9" },
+ { 0x103, "ARM" },
{ 0x104, "SH-3" },
{ 0x105, "SH-4" },
{ 0x118, "ARM" },
@@ -988,6 +993,24 @@ static const char *dmi_processor_family(const struct dmi_header *h, u16 ver)
{ 0x200, "RV32" },
{ 0x201, "RV64" },
{ 0x202, "RV128" },
+
+ { 0x258, "LoongArch" },
+ { 0x259, "Loongson 1" },
+ { 0x25A, "Loongson 2" },
+ { 0x25B, "Loongson 3" },
+ { 0x25C, "Loongson 2K" },
+ { 0x25D, "Loongson 3A" },
+ { 0x25E, "Loongson 3B" },
+ { 0x25F, "Loongson 3C" },
+ { 0x260, "Loongson 3D" },
+ { 0x261, "Loongson 3E" },
+ { 0x262, "Dual-Core Loongson 2K 2xxx" },
+ { 0x26C, "Quad-Core Loongson 3A 5xxx" },
+ { 0x26D, "Multi-Core Loongson 3A 5xxx" },
+ { 0x26E, "Quad-Core Loongson 3B 5xxx" },
+ { 0x26F, "Multi-Core Loongson 3B 5xxx" },
+ { 0x270, "Multi-Core Loongson 3C 5xxx" },
+ { 0x271, "Multi-Core Loongson 3D 5xxx" },
};
/*
* Note to developers: when adding entries to this list, check if
@@ -1073,7 +1096,7 @@ static enum cpuid_type dmi_get_cpuid_type(const struct dmi_header *h)
else
return cpuid_80486;
}
- else if ((type >= 0x100 && type <= 0x101) /* ARM */
+ else if ((type >= 0x100 && type <= 0x102) /* ARM */
|| (type >= 0x118 && type <= 0x119)) /* ARM */
{
/*
@@ -1106,6 +1129,9 @@ static enum cpuid_type dmi_get_cpuid_type(const struct dmi_header *h)
|| (type >= 0xB6 && type <= 0xB7) /* AMD */
|| (type >= 0xE4 && type <= 0xEF)) /* AMD */
return cpuid_x86_amd;
+ else if ((type >= 0x258 && type <= 0x262) /* Loongarch */
+ || (type >= 0x26C && type <= 0x271)) /* Loongarch */
+ return cpuid_loongarch;
/* neither X86 nor ARM */
return cpuid_none;
@@ -1203,6 +1229,11 @@ void dmi_print_cpuid(void (*print_cb)(const char *name, const char *format, ...)
((eax >> 4) & 0xF) | (((eax >> 8) & 0xF) == 0xF ? (eax >> 12) & 0xF0 : 0),
eax & 0xF);
break;
+
+ case cpuid_loongarch: /* LoongArch Reference Manual, volume 1 */
+ eax = DWORD(p);
+ print_cb(label, "Processor Identity 0x%08x\n", eax);
+ break;
default:
return;
}
@@ -1415,10 +1446,27 @@ static const char *dmi_processor_upgrade(u8 code)
"Socket BGA1528",
"Socket LGA4189",
"Socket LGA1200",
- "Socket LGA4677" /* 0x3F */
+ "Socket LGA4677",
+ "Socket LGA1700",
+ "Socket BGA1744",
+ "Socket BGA1781",
+ "Socket BGA1211",
+ "Socket BGA2422",
+ "Socket LGA1211",
+ "Socket LGA2422",
+ "Socket LGA5773",
+ "Socket BGA5773",
+ "Socket AM5",
+ "Socket SP5",
+ "Socket SP6",
+ "Socket BGA883",
+ "Socket BGA1190",
+ "Socket BGA4129",
+ "Socket LGA4710",
+ "Socket LGA7529" /* 0x50 */
};
- if (code >= 0x01 && code <= 0x3F)
+ if (code >= 0x01 && code <= 0x50)
return upgrade[code - 0x01];
return out_of_spec;
}
@@ -1939,14 +1987,16 @@ static const char *dmi_port_type(u8 code)
"Modem Port",
"Network Port",
"SATA",
- "SAS" /* 0x21 */
+ "SAS",
+ "MFDP (Multi-Function Display Port)",
+ "Thunderbolt" /* 0x23 */
};
static const char *type_0xA0[] = {
"8251 Compatible", /* 0xA0 */
"8251 FIFO Compatible" /* 0xA1 */
};
- if (code <= 0x21)
+ if (code <= 0x23)
return type[code];
if (code >= 0xA0 && code <= 0xA1)
return type_0xA0[code - 0xA0];
@@ -2062,49 +2112,31 @@ static const char *dmi_slot_type(u8 code)
return out_of_spec;
}
-/* If hide_unknown is set, return NULL instead of "Other" or "Unknown" */
-static const char *dmi_slot_bus_width(u8 code, int hide_unknown)
+static const char *dmi_slot_bus_width(u8 code)
{
/* 7.10.2 */
static const char *width[] = {
"Other", /* 0x01 */
"Unknown",
- "8-bit",
- "16-bit",
- "32-bit",
- "64-bit",
- "128-bit",
- "x1",
- "x2",
- "x4",
- "x8",
- "x12",
- "x16",
- "x32" /* 0x0E */
+ "8 bit",
+ "16 bit",
+ "32 bit",
+ "64 bit",
+ "128 bit",
+ "1x or x1",
+ "2x or x2",
+ "4x or x4",
+ "8x or x8",
+ "12x or x12",
+ "16x or x16",
+ "32x or x32" /* 0x0E */
};
if (code >= 0x01 && code <= 0x0E)
- {
- if (code <= 0x02 && hide_unknown)
- return NULL;
return width[code - 0x01];
- }
return out_of_spec;
}
-static void dmi_slot_type_with_width(u8 type, u8 width)
-{
- const char *type_str, *width_str;
-
- type_str = dmi_slot_type(type);
- width_str = dmi_slot_bus_width(width, 1);
-
- if (width_str)
- pr_attr("Type", "%s %s", width_str, type_str);
- else
- pr_attr("Type", "%s", type_str);
-}
-
static const char *dmi_slot_current_usage(u8 code)
{
/* 7.10.3 */
@@ -2220,12 +2252,13 @@ static void dmi_slot_characteristics(const char *attr, u8 code1, u8 code2)
"PCIe slot bifurcation is supported",
"Async/surprise removal is supported",
"Flexbus slot, CXL 1.0 capable",
- "Flexbus slot, CXL 2.0 capable" /* 6 */
+ "Flexbus slot, CXL 2.0 capable",
+ "Flexbus slot, CXL 3.0 capable" /* 7 */
};
if (code1 & (1 << 0))
pr_attr(attr, "Unknown");
- else if ((code1 & 0xFE) == 0 && (code2 & 0x07) == 0)
+ else if ((code1 & 0xFE) == 0 && code2 == 0)
pr_attr(attr, "None");
else
{
@@ -2235,7 +2268,7 @@ static void dmi_slot_characteristics(const char *attr, u8 code1, u8 code2)
for (i = 1; i <= 7; i++)
if (code1 & (1 << i))
pr_list_item("%s", characteristics1[i - 1]);
- for (i = 0; i <= 6; i++)
+ for (i = 0; i <= 7; i++)
if (code2 & (1 << i))
pr_list_item("%s", characteristics2[i]);
pr_list_end();
@@ -2314,7 +2347,7 @@ static void dmi_slot_physical_width(u8 code)
{
if (code)
pr_attr("Slot Physical Width", "%s",
- dmi_slot_bus_width(code, 0));
+ dmi_slot_bus_width(code));
}
static void dmi_slot_pitch(u16 code)
@@ -2640,7 +2673,7 @@ static const char *dmi_memory_array_location(u8 code)
"PC-98/C24 Add-on Card",
"PC-98/E Add-on Card",
"PC-98/Local Bus Add-on Card",
- "CXL Flexbus 1.0" /* 0xA4 */
+ "CXL Add-on Card" /* 0xA4 */
};
if (code >= 0x01 && code <= 0x0A)
@@ -2826,10 +2859,11 @@ static const char *dmi_memory_device_type(u8 code)
"HBM",
"HBM2",
"DDR5",
- "LPDDR5" /* 0x23 */
+ "LPDDR5",
+ "HBM3" /* 0x24 */
};
- if (code >= 0x01 && code <= 0x23)
+ if (code >= 0x01 && code <= 0x24)
return type[code - 0x01];
return out_of_spec;
}
@@ -2937,6 +2971,8 @@ static void dmi_memory_manufacturer_id(const char *attr, u16 code)
{
/* 7.18.8 */
/* 7.18.10 */
+ /* 7.18.15 */
+ /* 7.17.17 */
/* LSB is 7-bit Odd Parity number of continuation codes */
if (code == 0)
pr_attr(attr, "Unknown");
@@ -2967,6 +3003,45 @@ static void dmi_memory_size(const char *attr, u64 code)
dmi_print_memory_size(attr, code, 0);
}
+static void dmi_memory_revision(const char *attr_type, u16 code, u8 mem_type)
+{
+ /* 7.18.16 */
+ /* 7.18.18 */
+ char attr[22];
+
+ if (code == 0xFF00)
+ {
+ snprintf(attr, sizeof(attr), "%s Revision Number", attr_type);
+ pr_attr(attr, "Unknown");
+ }
+ else if (mem_type == 0x22 || mem_type == 0x23) /* DDR5 */
+ {
+ u8 dev_type = (code >> 8) & 0x0F;
+ u8 dev_rev = code & 0xFF;
+
+ if (code & 0x8000) /* Installed */
+ {
+ snprintf(attr, sizeof(attr), "%s Device Type",
+ attr_type);
+ pr_attr(attr, "%hu", dev_type);
+ snprintf(attr, sizeof(attr), "%s Device Revision",
+ attr_type);
+ pr_attr(attr, "%hu.%hu", dev_rev >> 4, dev_rev & 0x0F);
+ }
+ else
+ {
+ snprintf(attr, sizeof(attr), "%s Device Type",
+ attr_type);
+ pr_attr(attr, "Not Installed");
+ }
+ }
+ else /* Generic fallback */
+ {
+ snprintf(attr, sizeof(attr), "%s Revision Number", attr_type);
+ pr_attr(attr, "0x%04x", code);
+ }
+}
+
/*
* 7.19 32-bit Memory Error Information (Type 18)
*/
@@ -3813,7 +3888,7 @@ static const char *dmi_protocol_record_type(u8 type)
}
/*
- * DSP0270: 8.6: Protocol IP Assignment types
+ * DSP0270: 8.4.2: Protocol IP Assignment types
*/
static const char *dmi_protocol_assignment_type(u8 type)
{
@@ -3831,7 +3906,7 @@ static const char *dmi_protocol_assignment_type(u8 type)
}
/*
- * DSP0270: 8.6: Protocol IP Address type
+ * DSP0270: 8.4.3: Protocol IP Address type
*/
static const char *dmi_address_type(u8 type)
{
@@ -3847,7 +3922,7 @@ static const char *dmi_address_type(u8 type)
}
/*
- * DSP0270: 8.6 Protocol Address decode
+ * DSP0270: 8.4.3 Protocol Address decode
*/
static const char *dmi_address_decode(u8 *data, char *storage, u8 addrtype)
{
@@ -3859,7 +3934,7 @@ static const char *dmi_address_decode(u8 *data, char *storage, u8 addrtype)
}
/*
- * DSP0270: 8.5: Parse the protocol record format
+ * DSP0270: 8.4: Parse the protocol record format
*/
static void dmi_parse_protocol_record(u8 *rec)
{
@@ -3874,11 +3949,11 @@ static void dmi_parse_protocol_record(u8 *rec)
const char *hname;
char attr[38];
- /* DSP0270: 8.5: Protocol Identifier */
+ /* DSP0270: 8.4: Protocol Identifier */
rid = rec[0x0];
- /* DSP0270: 8.5: Protocol Record Length */
+ /* DSP0270: 8.4: Protocol Record Length */
rlen = rec[0x1];
- /* DSP0270: 8.5: Protocol Record Data */
+ /* DSP0270: 8.4: Protocol Record Data */
rdata = &rec[0x2];
pr_attr("Protocol ID", "%02x (%s)", rid,
@@ -3887,7 +3962,7 @@ static void dmi_parse_protocol_record(u8 *rec)
/*
* Don't decode anything other than Redfish for now
* Note 0x4 is Redfish over IP in 7.43.2
- * and DSP0270: 8.5
+ * and DSP0270: 8.4
*/
if (rid != 0x4)
return;
@@ -3901,7 +3976,7 @@ static void dmi_parse_protocol_record(u8 *rec)
return;
/*
- * DSP0270: 8.6: Redfish Over IP Service UUID
+ * DSP0270: 8.4.1: Redfish Over IP Service UUID
* Note: ver is hardcoded to 0x311 here just for
* convenience. It could get passed from the SMBIOS
* header, but that's a lot of passing of pointers just
@@ -3914,7 +3989,7 @@ static void dmi_parse_protocol_record(u8 *rec)
dmi_system_uuid(pr_subattr, "Service UUID", &rdata[0], 0x311);
/*
- * DSP0270: 8.6: Redfish Over IP Host IP Assignment Type
+ * DSP0270: 8.4.1: Redfish Over IP Host IP Assignment Type
* Note, using decimal indices here, as the DSP0270
* uses decimal, so as to make it more comparable
*/
@@ -3922,34 +3997,34 @@ static void dmi_parse_protocol_record(u8 *rec)
pr_subattr("Host IP Assignment Type", "%s",
dmi_protocol_assignment_type(assign_val));
- /* DSP0270: 8.6: Redfish Over IP Host Address format */
+ /* DSP0270: 8.4.1: Redfish Over IP Host Address format */
addrtype = rdata[17];
addrstr = dmi_address_type(addrtype);
pr_subattr("Host IP Address Format", "%s",
addrstr);
- /* DSP0270: 8.6 IP Assignment types */
+ /* DSP0270: 8.4.1 IP Assignment types */
/* We only use the Host IP Address and Mask if the assignment type is static */
if (assign_val == 0x1 || assign_val == 0x3)
{
- /* DSP0270: 8.6: the Host IPv[4|6] Address */
+ /* DSP0270: 8.4.1: the Host IPv[4|6] Address */
sprintf(attr, "%s Address", addrstr);
pr_subattr(attr, "%s",
dmi_address_decode(&rdata[18], buf, addrtype));
- /* DSP0270: 8.6: Prints the Host IPv[4|6] Mask */
+ /* DSP0270: 8.4.1: Prints the Host IPv[4|6] Mask */
sprintf(attr, "%s Mask", addrstr);
pr_subattr(attr, "%s",
dmi_address_decode(&rdata[34], buf, addrtype));
}
- /* DSP0270: 8.6: Get the Redfish Service IP Discovery Type */
+ /* DSP0270: 8.4.1: Get the Redfish Service IP Discovery Type */
assign_val = rdata[50];
/* Redfish Service IP Discovery type mirrors Host IP Assignment type */
pr_subattr("Redfish Service IP Discovery Type", "%s",
dmi_protocol_assignment_type(assign_val));
- /* DSP0270: 8.6: Get the Redfish Service IP Address Format */
+ /* DSP0270: 8.4.1: Get the Redfish Service IP Address Format */
addrtype = rdata[51];
addrstr = dmi_address_type(addrtype);
pr_subattr("Redfish Service IP Address Format", "%s",
@@ -3960,30 +4035,30 @@ static void dmi_parse_protocol_record(u8 *rec)
u16 port;
u32 vlan;
- /* DSP0270: 8.6: Prints the Redfish IPv[4|6] Service Address */
+ /* DSP0270: 8.4.1: Prints the Redfish IPv[4|6] Service Address */
sprintf(attr, "%s Redfish Service Address", addrstr);
pr_subattr(attr, "%s",
dmi_address_decode(&rdata[52], buf,
addrtype));
- /* DSP0270: 8.6: Prints the Redfish IPv[4|6] Service Mask */
+ /* DSP0270: 8.4.1: Prints the Redfish IPv[4|6] Service Mask */
sprintf(attr, "%s Redfish Service Mask", addrstr);
pr_subattr(attr, "%s",
dmi_address_decode(&rdata[68], buf,
addrtype));
- /* DSP0270: 8.6: Redfish vlan and port info */
+ /* DSP0270: 8.4.1: Redfish vlan and port info */
port = WORD(&rdata[84]);
vlan = DWORD(&rdata[86]);
pr_subattr("Redfish Service Port", "%hu", port);
pr_subattr("Redfish Service Vlan", "%u", vlan);
}
- /* DSP0270: 8.6: Redfish host length and name */
+ /* DSP0270: 8.4.1: Redfish host length and name */
hlen = rdata[90];
/*
- * DSP0270: 8.6: The length of the host string + 91 (the minimum
+ * DSP0270: 8.4.1: The length of the host string + 91 (the minimum
* size of a protocol record) cannot exceed the record length
* (rec[0x1])
*/
@@ -4004,15 +4079,39 @@ static const char *dmi_parse_device_type(u8 type)
const char *devname[] = {
"USB", /* 0x2 */
"PCI/PCIe", /* 0x3 */
+ "USB v2", /* 0x4 */
+ "PCI/PCIe v2", /* 0x5 */
};
- if (type >= 0x2 && type <= 0x3)
+ if (type >= 0x2 && type <= 0x5)
return devname[type - 0x2];
if (type >= 0x80)
return "OEM";
return out_of_spec;
}
+/*
+ * DSP0270: 8.3.7: Device Characteristics
+ */
+static void dmi_device_characteristics(u16 code)
+{
+ const char *characteristics[] = {
+ "Credential bootstrapping via IPMI is supported", /* 0 */
+ /* Reserved */
+ };
+
+ if ((code & 0x1) == 0)
+ pr_list_item("None");
+ else
+ {
+ int i;
+
+ for (i = 0; i < 1; i++)
+ if (code & (1 << i))
+ pr_list_item("%s", characteristics[i]);
+ }
+}
+
static void dmi_parse_controller_structure(const struct dmi_header *h)
{
int i;
@@ -4055,7 +4154,7 @@ static void dmi_parse_controller_structure(const struct dmi_header *h)
if (len != 0)
{
- /* DSP0270: 8.3 Table 2: Device Type */
+ /* DSP0270: 8.3.1 Table 3: Device Type values */
type = data[0x6];
pr_attr("Device Type", "%s",
@@ -4092,7 +4191,84 @@ static void dmi_parse_controller_structure(const struct dmi_header *h)
pr_attr("SubDeviceID", "0x%04x",
WORD(&pcidata[0x6]));
}
- else if (type == 0x4 && len >= 5)
+ else if (type == 0x4 && len >= 0x0d)
+ {
+ /* USB Device Type v2 - need at least 12 bytes */
+ u8 *usbdata = &data[7];
+ /* USB Device Descriptor v2: idVendor */
+ pr_attr("idVendor", "0x%04x",
+ WORD(&usbdata[0x1]));
+ /* USB Device Descriptor v2: idProduct */
+ pr_attr("idProduct", "0x%04x",
+ WORD(&usbdata[0x3]));
+
+ /*
+ * USB Serial number is here, but its useless, don't
+ * bother decoding it
+ */
+
+ /* USB Device Descriptor v2: MAC Address */
+ pr_attr("MAC Address", "%02x:%02x:%02x:%02x:%02x:%02x",
+ usbdata[0x6], usbdata[0x7], usbdata[0x8],
+ usbdata[0x9], usbdata[0xa], usbdata[0xb]);
+
+ /* DSP0270 v1.3.0 support */
+ if (len >= 0x11)
+ {
+ /* USB Device Descriptor v2: Device Characteristics */
+ pr_list_start("Device Characteristics", NULL);
+ dmi_device_characteristics(WORD(&usbdata[0xc]));
+ pr_list_end();
+
+ /* USB Device Descriptor v2: Credential Bootstrapping Handle */
+ if (WORD(&usbdata[0x0c]) & 0x1)
+ {
+ pr_attr("Credential Bootstrapping Handle", "0x%04x",
+ WORD(&usbdata[0xe]));
+ }
+ }
+ }
+ else if (type == 0x5 && len >= 0x14)
+ {
+ /* PCI Device Type v2 - Need at least 19 bytes */
+ u8 *pcidata = &data[0x7];
+ /* PCI Device Descriptor v2: VendorID */
+ pr_attr("VendorID", "0x%04x",
+ WORD(&pcidata[0x1]));
+ /* PCI Device Descriptor v2: DeviceID */
+ pr_attr("DeviceID", "0x%04x",
+ WORD(&pcidata[0x3]));
+ /* PCI Device Descriptor v2: PCI SubvendorID */
+ pr_attr("SubVendorID", "0x%04x",
+ WORD(&pcidata[0x5]));
+ /* PCI Device Descriptor v2: PCI SubdeviceID */
+ pr_attr("SubDeviceID", "0x%04x",
+ WORD(&pcidata[0x7]));
+ /* PCI Device Descriptor v2: MAC Address */
+ pr_attr("MAC Address", "%02x:%02x:%02x:%02x:%02x:%02x",
+ pcidata[0x9], pcidata[0xa], pcidata[0xb],
+ pcidata[0xc], pcidata[0xd], pcidata[0xe]);
+ /* PCI Device Descriptor v2:
+ * Segment Group Number, Bus Number, Device/Function Number
+ */
+ dmi_slot_segment_bus_func(WORD(&pcidata[0xf]), pcidata[0x11], pcidata[0x12]);
+
+ /* DSP0270 v1.3.0 support */
+ if (len >= 0x18)
+ {
+ /* PCI Device Descriptor v2: Device Characteristics */
+ pr_list_start("Device Characteristics", NULL);
+ dmi_device_characteristics(WORD(&pcidata[0x13]) );
+ pr_list_end();
+ /* PCI Device Descriptor v2: Credential Bootstrapping Handle */
+ if (WORD(&pcidata[0x13]) & 0x1)
+ {
+ pr_attr("Credential Bootstrapping Handle", "0x%04x",
+ WORD(&pcidata[0x15]));
+ }
+ }
+ }
+ else if (type >= 0x80 && len >= 5)
{
/* OEM Device Type - Need at least 4 bytes */
u8 *oemdata = &data[0x7];
@@ -4105,7 +4281,7 @@ static void dmi_parse_controller_structure(const struct dmi_header *h)
}
/*
- * DSP0270: 8.2 and 8.5: Protocol record count and protocol records
+ * DSP0270: 8.2 and 8.4: Protocol record count and protocol records
* Move to the Protocol Count.
*/
data = &data[total_read];
@@ -4148,7 +4324,7 @@ static void dmi_parse_controller_structure(const struct dmi_header *h)
dmi_parse_protocol_record(rec);
/*
- * DSP0270: 8.6
+ * DSP0270: 8.4.1
* Each record is rec[1] bytes long, starting at the
* data byte immediately following the length field.
* That means we need to add the byte for the rec id,
@@ -4451,6 +4627,9 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
pr_attr("Thread Count", "%u",
h->length >= 0x30 && data[0x25] == 0xFF ?
WORD(data + 0x2E) : data[0x25]);
+ if (h->length >= 0x32 && WORD(data + 0x30) != 0)
+ pr_attr("Thread Enabled", "%u",
+ WORD(data + 0x30));
dmi_processor_characteristics("Characteristics",
WORD(data + 0x26));
break;
@@ -4548,7 +4727,8 @@ 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]));
- dmi_slot_type_with_width(data[0x05], data[0x06]);
+ pr_attr("Type", "%s", dmi_slot_type(data[0x05]));
+ pr_attr("Data Bus Width", "%s", dmi_slot_bus_width(data[0x06]));
pr_attr("Current Usage", "%s",
dmi_slot_current_usage(data[0x07]));
pr_attr("Length", "%s",
@@ -4561,7 +4741,7 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
if (h->length < 0x11) break;
dmi_slot_segment_bus_func(WORD(data + 0x0D), data[0x0F], data[0x10]);
if (h->length < 0x13) break;
- pr_attr("Data Bus Width", "%u", data[0x11]);
+ pr_attr("Data Bus Width (Base)", "%u", data[0x11]);
pr_attr("Peer Devices", "%u", data[0x12]);
if (h->length < 0x13 + data[0x12] * 5) break;
dmi_slot_peers(data[0x12], data + 0x13);
@@ -4755,6 +4935,15 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
dmi_memory_size("Cache Size", QWORD(data + 0x44));
if (h->length < 0x54) break;
dmi_memory_size("Logical Size", QWORD(data + 0x4C));
+ if (h->length < 0x64) break;
+ dmi_memory_manufacturer_id("PMIC0 Manufacturer ID",
+ WORD(data + 0x5C));
+ dmi_memory_revision("PMIC0", WORD(data + 0x5E),
+ data[0x12]);
+ dmi_memory_manufacturer_id("RCD Manufacturer ID",
+ WORD(data + 0x60));
+ dmi_memory_revision("RCD", WORD(data + 0x62),
+ data[0x12]);
break;
case 18: /* 7.19 32-bit Memory Error Information */
@@ -5718,14 +5907,14 @@ static void overwrite_smbios3_address(u8 *buf)
buf[0x17] = 0;
}
-static int smbios3_decode(u8 *buf, const char *devmem, u32 flags)
+static int smbios3_decode(u8 *buf, size_t buf_len, const char *devmem, u32 flags)
{
u32 ver, len;
u64 offset;
u8 *table;
/* Don't let checksum run beyond the buffer */
- if (buf[0x06] > 0x20)
+ if (buf[0x06] > buf_len)
{
fprintf(stderr,
"Entry point length too large (%u bytes, expected %u).\n",
@@ -5799,14 +5988,14 @@ static void dmi_fixup_version(u16 *ver)
}
}
-static int smbios_decode(u8 *buf, const char *devmem, u32 flags)
+static int smbios_decode(u8 *buf, size_t buf_len, const char *devmem, u32 flags)
{
u16 ver, num;
u32 len;
u8 *table;
/* Don't let checksum run beyond the buffer */
- if (buf[0x05] > 0x20)
+ if (buf[0x05] > buf_len)
{
fprintf(stderr,
"Entry point length too large (%u bytes, expected %u).\n",
@@ -5910,7 +6099,7 @@ static int address_from_efi(off_t *address)
FILE *efi_systab;
const char *filename;
char linebuf[64];
-#elif defined(__FreeBSD__)
+#elif defined(__FreeBSD__) || defined(__DragonFly__)
char addrstr[KENV_MVALLEN + 1];
#endif
const char *eptype;
@@ -5948,11 +6137,14 @@ static int address_from_efi(off_t *address)
if (ret == EFI_NO_SMBIOS)
fprintf(stderr, "%s: SMBIOS entry point missing\n", filename);
-#elif defined(__FreeBSD__)
+#elif defined(__FreeBSD__) || defined(__DragonFly__)
/*
* On FreeBSD, SMBIOS anchor base address in UEFI mode is exposed
* via kernel environment:
* https://svnweb.freebsd.org/base?view=revision&revision=307326
+ *
+ * DragonFly BSD adopted the same method as FreeBSD, see commit
+ * 5e488df32cb01056a5b714a522e51c69ab7b4612
*/
ret = kenv(KENV_GET, "hint.smbios.0.mem", addrstr, sizeof(addrstr));
if (ret == -1)
@@ -6009,6 +6201,12 @@ int main(int argc, char * const argv[])
goto exit_free;
}
+ if (opt.flags & FLAG_LIST)
+ {
+ /* Already handled in parse_command_line() */
+ goto exit_free;
+ }
+
if (opt.flags & FLAG_HELP)
{
print_help();
@@ -6025,25 +6223,33 @@ int main(int argc, char * const argv[])
pr_comment("dmidecode %s", VERSION);
/* Read from dump if so instructed */
+ size = 0x20;
if (opt.flags & FLAG_FROM_DUMP)
{
if (!(opt.flags & FLAG_QUIET))
pr_info("Reading SMBIOS/DMI data from file %s.",
opt.dumpfile);
- if ((buf = mem_chunk(0, 0x20, opt.dumpfile)) == NULL)
+ if ((buf = read_file(0, &size, opt.dumpfile)) == NULL)
{
ret = 1;
goto exit_free;
}
+ /* Truncated entry point can't be processed */
+ if (size < 0x20)
+ {
+ ret = 1;
+ goto done;
+ }
+
if (memcmp(buf, "_SM3_", 5) == 0)
{
- if (smbios3_decode(buf, opt.dumpfile, 0))
+ if (smbios3_decode(buf, size, opt.dumpfile, 0))
found++;
}
else if (memcmp(buf, "_SM_", 4) == 0)
{
- if (smbios_decode(buf, opt.dumpfile, 0))
+ if (smbios_decode(buf, size, opt.dumpfile, 0))
found++;
}
else if (memcmp(buf, "_DMI_", 5) == 0)
@@ -6059,7 +6265,6 @@ int main(int argc, char * const argv[])
* contain one of several types of entry points, so read enough for
* the largest one, then determine what type it contains.
*/
- size = 0x20;
if (!(opt.flags & FLAG_NO_SYSFS)
&& (buf = read_file(0, &size, SYS_ENTRY_FILE)) != NULL)
{
@@ -6067,12 +6272,12 @@ int main(int argc, char * const argv[])
pr_info("Getting SMBIOS data from sysfs.");
if (size >= 24 && memcmp(buf, "_SM3_", 5) == 0)
{
- if (smbios3_decode(buf, SYS_TABLE_FILE, FLAG_NO_FILE_OFFSET))
+ if (smbios3_decode(buf, size, SYS_TABLE_FILE, FLAG_NO_FILE_OFFSET))
found++;
}
else if (size >= 31 && memcmp(buf, "_SM_", 4) == 0)
{
- if (smbios_decode(buf, SYS_TABLE_FILE, FLAG_NO_FILE_OFFSET))
+ if (smbios_decode(buf, size, SYS_TABLE_FILE, FLAG_NO_FILE_OFFSET))
found++;
}
else if (size >= 15 && memcmp(buf, "_DMI_", 5) == 0)
@@ -6109,12 +6314,12 @@ int main(int argc, char * const argv[])
if (memcmp(buf, "_SM3_", 5) == 0)
{
- if (smbios3_decode(buf, opt.devmem, 0))
+ if (smbios3_decode(buf, 0x20, opt.devmem, 0))
found++;
}
else if (memcmp(buf, "_SM_", 4) == 0)
{
- if (smbios_decode(buf, opt.devmem, 0))
+ if (smbios_decode(buf, 0x20, opt.devmem, 0))
found++;
}
goto done;
@@ -6135,7 +6340,7 @@ memory_scan:
{
if (memcmp(buf + fp, "_SM3_", 5) == 0)
{
- if (smbios3_decode(buf + fp, opt.devmem, 0))
+ if (smbios3_decode(buf + fp, 0x20, opt.devmem, 0))
{
found++;
goto done;
@@ -6148,7 +6353,7 @@ memory_scan:
{
if (memcmp(buf + fp, "_SM_", 4) == 0 && fp <= 0xFFE0)
{
- if (smbios_decode(buf + fp, opt.devmem, 0))
+ if (smbios_decode(buf + fp, 0x20, opt.devmem, 0))
{
found++;
goto done;