summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff.email>2024-06-30 20:02:17 +0200
committerJörg Frings-Fürst <debian@jff.email>2024-06-30 20:02:17 +0200
commitc38426c9a9dd4efb236ef21d0c281d341445102a (patch)
tree45fa8b58371e9f40cd1fbd169cbd497eb300a2a1
parent25d9e648d730c649a9769b04dc0a246fbc9680cb (diff)
parente8704754ec72eb19159d167d79a1d89a899ea632 (diff)
Merge branch 'feature/upstream' into develop
-rw-r--r--.gitignore2
-rw-r--r--Makefile18
-rw-r--r--NEWS19
-rw-r--r--completion/biosdecode.bash40
-rw-r--r--completion/dmidecode.bash60
-rw-r--r--completion/ownership.bash33
-rw-r--r--completion/vpddecode.bash43
-rw-r--r--config.h2
-rw-r--r--dmidecode.c387
-rw-r--r--dmidecode.h3
-rw-r--r--dmioem.c349
-rw-r--r--dmiopt.c17
-rw-r--r--dmiopt.h3
-rw-r--r--man/dmidecode.88
-rw-r--r--util.c2
-rw-r--r--util.h2
-rw-r--r--version.h2
17 files changed, 864 insertions, 126 deletions
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 0ff0ae9..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-.pc
-debian/files
diff --git a/Makefile b/Makefile
index 7aa729d..6fc946b 100644
--- a/Makefile
+++ b/Makefile
@@ -36,6 +36,7 @@ sbindir = $(prefix)/sbin
mandir = $(prefix)/share/man
man8dir = $(mandir)/man8
docdir = $(prefix)/share/doc/dmidecode
+compdir = $(shell pkg-config --variable=completionsdir bash-completion 2>/dev/null || echo $(prefix)/etc/bash_completion.d)
INSTALL := install
INSTALL_DATA := $(INSTALL) -m 644
@@ -113,9 +114,9 @@ util.o : util.c types.h util.h config.h
strip : $(PROGRAMS)
strip $(PROGRAMS)
-install : install-bin install-man install-doc
+install : install-bin install-man install-doc install-completion
-uninstall : uninstall-bin uninstall-man uninstall-doc
+uninstall : uninstall-bin uninstall-man uninstall-doc uninstall-completion
install-bin : $(PROGRAMS)
$(INSTALL_DIR) $(DESTDIR)$(sbindir)
@@ -144,5 +145,18 @@ install-doc :
uninstall-doc :
$(RM) -r $(DESTDIR)$(docdir)
+install-completion :
+ if [ -d $(compdir) ] ; then \
+ $(INSTALL_DIR) $(DESTDIR)$(compdir) ; \
+ for program in $(PROGRAMS) ; do \
+ $(INSTALL_DATA) completion/$$program.bash $(DESTDIR)$(compdir)/$$program ; done ; \
+ fi
+
+uninstall-completion :
+ if [ -d $(DESTDIR)$(compdir) ]; then \
+ for program in $(PROGRAMS) ; do \
+ $(RM) $(DESTDIR)$(compdir)/$$program ; done ; \
+ fi
+
clean :
$(RM) *.o $(PROGRAMS) core
diff --git a/NEWS b/NEWS
index 504e3fb..8c4059e 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,22 @@
+Version 3.6 (Wed Apr 24 2024)
+ - [PORTABILITY] Use -DALIGNMENT_WORKAROUND on arm.
+ - [PORTABILITY] Read SMBIOS entry point via kenv on DragonFly BSD.
+ - Support for SMBIOS 3.6.0. This includes new memory device types, new
+ processor upgrades, and Loongarch support.
+ - Support for SMBIOS 3.7.0. This includes new port types, new processor
+ upgrades, new slot characteristics and new fields for memory modules.
+ - Add bash completion.
+ - Decode HPE OEM records 197, 239 and 245.
+ - Implement options --list-strings and --list-types.
+ - Update HPE OEM records 203, 212, 216, 221, 233, 236, 237, 238 and 242.
+ - Update Redfish support.
+ - Bug fixes:
+ Fix option --from-dump for user root
+ Fix enabled slot characteristics not being printed
+ - Minor improvements:
+ Print slot width on its own line
+ Use standard strings for slot width
+
Version 3.5 (Tue Mar 14 2023)
- Decode HPE OEM records 216, 224, 230, 238 and 242.
- Fortify entry point length checks.
diff --git a/completion/biosdecode.bash b/completion/biosdecode.bash
new file mode 100644
index 0000000..42e0fae
--- /dev/null
+++ b/completion/biosdecode.bash
@@ -0,0 +1,40 @@
+# bash completion for biosdecode -*- shell-script -*-
+
+_comp_cmd_biosdecode() {
+ local cur prev
+ COMPREPLY=()
+ cur=${COMP_WORDS[COMP_CWORD]}
+ prev=${COMP_WORDS[COMP_CWORD - 1]}
+
+ case $prev in
+ -d | --dev-mem)
+ : "${cur:=/dev/}"
+ local IFS=$'\n'
+ compopt -o filenames
+ COMPREPLY=($(compgen -f -- "$cur"))
+ return 0
+ ;;
+ --pir)
+ COMPREPLY=($(compgen -W '
+ full
+ ' -- "$cur"))
+ return 0
+ ;;
+ -[hV] | --help | --version)
+ return 0
+ ;;
+ esac
+
+ if [[ $cur == -* ]]; then
+ COMPREPLY=($(compgen -W '
+ --dev-mem
+ --pir
+ --help
+ --version
+ ' -- "$cur"))
+ return 0
+ fi
+
+} && complete -F _comp_cmd_biosdecode biosdecode
+
+# ex: filetype=sh
diff --git a/completion/dmidecode.bash b/completion/dmidecode.bash
new file mode 100644
index 0000000..200d6cd
--- /dev/null
+++ b/completion/dmidecode.bash
@@ -0,0 +1,60 @@
+# bash completion for dmidecode -*- shell-script -*-
+
+_comp_cmd_dmidecode() {
+ local cur prev
+ COMPREPLY=()
+ cur=${COMP_WORDS[COMP_CWORD]}
+ prev=${COMP_WORDS[COMP_CWORD - 1]}
+
+ case $prev in
+ -d | --dev-mem | --dump-bin | --from-dump)
+ if [[ $prev == -d || $prev == --dev-mem ]]; then
+ : "${cur:=/dev/}"
+ fi
+ local IFS=$'\n'
+ compopt -o filenames
+ COMPREPLY=($(compgen -f -- "$cur"))
+ return 0
+ ;;
+ -s | --string)
+ COMPREPLY=($(compgen -W '$("$1" --list-strings)' -- "$cur"))
+ return 0
+ ;;
+ -t | --type)
+ COMPREPLY=($(compgen -W '$("$1" --list-types)' -- "$cur"))
+ return 0
+ ;;
+ --dump-bin | --from-dump)
+ local IFS=$'\n'
+ compopt -o filenames
+ COMPREPLY=($(compgen -f -- "$cur"))
+ return 0
+ ;;
+ -[hVH] | --help | --version | --handle | --oem-string)
+ return 0
+ ;;
+ esac
+
+ if [[ $cur == -* ]]; then
+ COMPREPLY=($(compgen -W '
+ --dev-mem
+ --help
+ --quiet
+ --string
+ --list-strings
+ --type
+ --list-types
+ --handle
+ --dump
+ --dump-bin
+ --from-dump
+ --no-sysfs
+ --oem-string
+ --version
+ ' -- "$cur"))
+ return 0
+ fi
+
+} && complete -F _comp_cmd_dmidecode dmidecode
+
+# ex: filetype=sh
diff --git a/completion/ownership.bash b/completion/ownership.bash
new file mode 100644
index 0000000..6a25d29
--- /dev/null
+++ b/completion/ownership.bash
@@ -0,0 +1,33 @@
+# bash completion for ownership -*- shell-script -*-
+
+_comp_cmd_ownership() {
+ local cur prev
+ COMPREPLY=()
+ cur=${COMP_WORDS[COMP_CWORD]}
+ prev=${COMP_WORDS[COMP_CWORD - 1]}
+
+ case $prev in
+ -d | --dev-mem)
+ : "${cur:=/dev/}"
+ local IFS=$'\n'
+ compopt -o filenames
+ COMPREPLY=($(compgen -f -- "$cur"))
+ return 0
+ ;;
+ -[hV] | --help | --version)
+ return 0
+ ;;
+ esac
+
+ if [[ $cur == -* ]]; then
+ COMPREPLY=($(compgen -W '
+ --dev-mem
+ --help
+ --version
+ ' -- "$cur"))
+ return 0
+ fi
+
+} && complete -F _comp_cmd_ownership ownership
+
+# ex: filetype=sh
diff --git a/completion/vpddecode.bash b/completion/vpddecode.bash
new file mode 100644
index 0000000..0745127
--- /dev/null
+++ b/completion/vpddecode.bash
@@ -0,0 +1,43 @@
+# bash completion for vpddecode -*- shell-script -*-
+
+_comp_cmd_vpddecode() {
+ local cur prev
+ COMPREPLY=()
+ cur=${COMP_WORDS[COMP_CWORD]}
+ prev=${COMP_WORDS[COMP_CWORD - 1]}
+
+ case $prev in
+ -d | --dev-mem)
+ : "${cur:=/dev/}"
+ local IFS=$'\n'
+ compopt -o filenames
+ COMPREPLY=($(compgen -f -- "$cur"))
+ return 0
+ ;;
+ -s | --string)
+ COMPREPLY=($(compgen -W '$(
+ "$1" --string 2>&1 | while IFS=\$'\\n' read -r line ; do
+ [[ $line == " "* ]] && printf "%s\n" "$line"
+ done
+ ' -- "$cur"))
+ return 0
+ ;;
+ -[hV] | --help | --version)
+ return 0
+ ;;
+ esac
+
+ if [[ $cur == -* ]]; then
+ COMPREPLY=($(compgen -W '
+ --dev-mem
+ --help
+ --string
+ --dump
+ --version
+ ' -- "$cur"))
+ return 0
+ fi
+
+} && complete -F _comp_cmd_vpddecode vpddecode
+
+# ex: filetype=sh
diff --git a/config.h b/config.h
index 4237355..0a1af7d 100644
--- a/config.h
+++ b/config.h
@@ -22,7 +22,7 @@
#endif
/* Use memory alignment workaround or not */
-#ifdef __ia64__
+#if defined(__ia64__) || defined(__arm__)
#define ALIGNMENT_WORKAROUND
#endif
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;
diff --git a/dmidecode.h b/dmidecode.h
index 318cdc6..e03c957 100644
--- a/dmidecode.h
+++ b/dmidecode.h
@@ -1,7 +1,7 @@
/*
* This file is part of the dmidecode project.
*
- * Copyright (C) 2005-2020 Jean Delvare <jdelvare@suse.de>
+ * Copyright (C) 2005-2023 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
@@ -40,6 +40,7 @@ enum cpuid_type
cpuid_arm_soc_id,
cpuid_x86_intel,
cpuid_x86_amd,
+ cpuid_loongarch,
};
extern enum cpuid_type cpuid_type;
diff --git a/dmioem.c b/dmioem.c
index dc4b857..2f1f9f6 100644
--- a/dmioem.c
+++ b/dmioem.c
@@ -2,7 +2,8 @@
* Decoding of OEM-specific entries
* This file is part of the dmidecode project.
*
- * Copyright (C) 2007-2020 Jean Delvare <jdelvare@suse.de>
+ * Copyright (C) 2007-2024 Jean Delvare <jdelvare@suse.de>
+ * Copyright (C) 2017-2024 Jerry Hoemann <jerry.hoemann@hpe.com>
*
* 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
@@ -161,11 +162,12 @@ static void dmi_print_hp_net_iface_rec(u8 id, u8 bus, u8 dev, const u8 *mac)
}
}
-typedef enum { G6 = 6, G7, G8, G9, G10, G10P } dmi_hpegen_t;
+typedef enum { G6 = 6, G7, G8, G9, G10, G10P, G11 } dmi_hpegen_t;
static int dmi_hpegen(const char *s)
{
struct { const char *name; dmi_hpegen_t gen; } table[] = {
+ { "Gen11", G11 },
{ "Gen10 Plus", G10P },
{ "Gen10", G10 },
{ "Gen9", G9 },
@@ -187,25 +189,21 @@ static int dmi_hpegen(const char *s)
return (dmi_vendor == VENDOR_HPE) ? G10P : G6;
}
-static void dmi_hp_240_attr(u64 defined, u64 set)
+static void dmi_hp_197_qdf(const u8 *qdf)
{
- static const char *attributes[] = {
- "Updatable",
- "Reset Required",
- "Authentication Required",
- "In Use",
- "UEFI Image",
- };
- unsigned int i;
+ char str[7];
+ int i, j, len = 6;
- pr_list_start("Attributes Defined/Set", NULL);
- for (i = 0; i < ARRAY_SIZE(attributes); i++)
+ if (!is_printable(qdf, len))
+ return;
+
+ for (i = 0, j = 0; i < len; i++)
{
- if (!(defined.l & (1UL << i)))
- continue;
- pr_list_item("%s: %s", attributes[i], set.l & (1UL << i) ? "Yes" : "No");
+ if (qdf[i] != ' ')
+ str[j++] = qdf[i];
}
- pr_list_end();
+ str[j] = '\0';
+ pr_attr("QDF/S-SPEC", "%s", str);
}
static void dmi_hp_203_assoc_hndl(const char *fname, u16 num)
@@ -291,7 +289,13 @@ static void dmi_hp_203_devloc(const char *fname, unsigned int code)
"USB",
"Dynamic Smart Array Controller",
"URL",
- "NVMe Drive Bay" /* 0x0F */
+ "NVMe Drive Bay", /* 0x0F */
+ "NVDIMM Processor",
+ "NVDIMM Board",
+ "NVMe Riser",
+ "NVDIMM Name Space",
+ "VROC SATA",
+ "VROC NVMe", /* 0x15 */
};
if (code < ARRAY_SIZE(location))
@@ -361,8 +365,10 @@ static void dmi_hp_216_fw_type(u16 code)
"Secondary System Programmable Logic Device",
"CPU MEZZ Programmable Logic Device", /* 0x37 */
"Intel Artic Sound -M Accelerator Models Firmware",
- "Ampere System Control Processor (SCP – PMPro+SMPro)",
+ "Ampere System Control Processor (SCP - PMPro+SMPro)",
"Intel CFR information", /* 0x3A */
+ "OCP cards",
+ "DC-SCM CPLD",
};
if (code < ARRAY_SIZE(type))
@@ -384,8 +390,10 @@ static void dmi_hp_216_version(u8 format, u8 *data)
pr_attr(name, "No Version Data");
break;
case 1:
- pr_attr(name, "%c.%d.%d", data[0] & (1 << 7) ? 'B' : 'R',
- data[0] & 0x7, data[1] & 0x7);
+ if (data[0] >> 7)
+ pr_attr(name, "0x%02X B.0x%02X", data[1] & 0x7F, data[0] & 0x7F);
+ else
+ pr_attr(name, "0x%02X", data[1] & 0x7F);
break;
case 2:
pr_attr(name, "%d.%d", data[0] >> 4, data[0] & 0x0f);
@@ -580,6 +588,8 @@ static void dmi_hp_238_loc(const char *fname, unsigned int code)
"USB Hub for NAND Controller",
"Reserved",
"Debug Port", /* 0x07 */
+ "Reserved",
+ "OCP USB", /* 0x09 */
};
if (code < ARRAY_SIZE(location))
@@ -619,6 +629,106 @@ static void dmi_hp_238_speed(const char *fname, unsigned int code)
pr_attr(fname, "%s", str);
}
+static void dmi_hp_239_usb_device(u8 class, u8 subclass, u8 protocol)
+{
+ /* https://www.usb.org/defined-class-codes */
+ /* https://www.usb.org/sites/default/files/Mass_Storage_Specification_Overview_v1.4_2-19-2010.pdf */
+ const char *str = "Reserved";
+ if (class == 0x08)
+ {
+ static const char * const sub_class_name[] = {
+ "SCSI command set not reported", /* 0x00 */
+ "RBC",
+ "ATAPI",
+ "Obsolete",
+ "UFI",
+ "Obsolete",
+ "SCSI",
+ "LSD FS",
+ "IEEE 1667" /* 0x08 */
+ };
+ pr_attr("USB Class", "%s", "Mass Storage");
+ if (subclass == 0xFF)
+ {
+ str = "Vendor Specific";
+ }
+ else if (subclass < ARRAY_SIZE(sub_class_name))
+ {
+ str = sub_class_name[subclass];
+ }
+ pr_attr("USB SubClass", "%s", str);
+
+ switch (protocol) {
+ case 0x00:
+ str = "CBI w/ completion interrupt";
+ break;
+ case 0x01:
+ str = "CBI w/o completion interrupt";
+ break;
+ case 0x02:
+ str = "Obsolete";
+ break;
+ case 0x50:
+ str = "Bulk-Only";
+ break;
+ case 0x62:
+ str = "UAS";
+ break;
+ case 0xFF:
+ str = "Vendor Specific";
+ break;
+ default:
+ str = "Reserved";
+ }
+ pr_attr("USB Protocol", "%s", str);
+ }
+ else if (class == 0x09 && subclass == 0)
+ {
+ pr_attr("USB Class", "%s", "HUB");
+ switch (protocol) {
+ case 0:
+ str = "Full Speed";
+ break;
+ case 1:
+ str = "Hi-Speed w/ single TT";
+ break;
+ case 2:
+ str = "Hi-Speed w/ multiple TT";
+ break;
+ default:
+ str = "Reserved";
+ }
+ pr_attr("USB Protocol", str);
+ }
+ else
+ {
+ pr_attr("USB Class", "0x%02x", class);
+ pr_attr("USB SubClass", "0x%02x", subclass);
+ pr_attr("USB Protocol", "0x%02x", protocol);
+ }
+}
+
+static void dmi_hp_240_attr(u64 defined, u64 set)
+{
+ static const char *attributes[] = {
+ "Updatable",
+ "Reset Required",
+ "Authentication Required",
+ "In Use",
+ "UEFI Image",
+ };
+ unsigned int i;
+
+ pr_list_start("Attributes Defined/Set", NULL);
+ for (i = 0; i < ARRAY_SIZE(attributes); i++)
+ {
+ if (!(defined.l & (1UL << i)))
+ continue;
+ pr_list_item("%s: %s", attributes[i], set.l & (1UL << i) ? "Yes" : "No");
+ }
+ pr_list_end();
+}
+
static void dmi_hp_242_hdd_type(u8 code)
{
const char *str = "Reserved";
@@ -651,8 +761,17 @@ static void dmi_hp_242_form_factor(u8 code)
"MicroSSD",
"CFast", /* 0x09 */
};
+ static const char * const form2[] = {
+ "EDSFF Unknown", /* 0x20 */
+ "EDSFF 1U Short",
+ "EDSFF 1U Long",
+ "EDSFF E3 Short",
+ "EDSFF E3 Long", /* 0x24 */
+ };
if (code < ARRAY_SIZE(form))
str = form[code];
+ else if (code >= 0x20 && code < 0x20 + ARRAY_SIZE(form2))
+ str = form2[code - 0x20];
pr_attr("Form Factor", "%s", str);
}
@@ -665,6 +784,31 @@ static void dmi_hp_242_speed(const char *attr, u16 speed)
pr_attr(attr, "%s", "Unknown");
}
+static void dmi_hp_245_pcie_riser(const struct dmi_header *h)
+{
+ const char *str = "Reserved";
+ u8 *data = h->data;
+
+ pr_attr("Board Type", "PCIe Riser");
+ if (h->length < 0x09) return;
+ switch (data[0x05])
+ {
+ case 1: str = "Primary"; break;
+ case 2: str = "Secondary"; break;
+ case 3: str = "Tertiary"; break;
+ case 4: str = "Quaternary"; break;
+ case 10: str = "Front"; break;
+ }
+ pr_attr("Riser Position", "%s", str);
+ pr_attr("Riser ID", "%d", data[0x06]);
+ if (data[0x07])
+ {
+ str = (data[0x07] >> 7) ? "B." : "";
+ pr_attr("CPLD Version", "%s0x%02X", str, (data[0x07] & 0x7F));
+ }
+ pr_attr("Riser Name", dmi_string(h, data[0x08]));
+}
+
static int dmi_decode_hp(const struct dmi_header *h)
{
u8 *data = h->data;
@@ -700,6 +844,69 @@ static int dmi_decode_hp(const struct dmi_header *h)
pr_attr("Virtual Serial Port", "%s", feat & (1 << 4) ? "Enabled" : "Disabled");
break;
+ case 197:
+ /*
+ * Vendor Specific: HPE Processor Specific Information
+ *
+ * Processor Information structure (Type 197) for each possibly installed
+ * physical processor to go along with each standard Processor Info
+ * Record (Type 4). The Type 197 record will be ignored for Processor
+ * slots that are empty (specified in the Type 4 records).
+ *
+ * Processor Wattage value will be filled in with information gotten from
+ * the CPUID instruction or possibly estimated based on CPU Family/Type.
+ *
+ * Designator bytes will be 0FFh if the location of the processor does not
+ * use it. If a system has processor slots, but no sockets, then the value
+ * in the Socket Designator will be 0FFh. A system would have one or the
+ * other, or both.
+ *
+ * Offset | Name | Width | Description
+ * -------+------------+-------+-------------
+ * 0x00 | Type | BYTE | 0xC5, Processor Information
+ * 0x01 | Length | BYTE | Length of structure
+ * 0x02 | Handle | WORD | Unique handle
+ * 0x04 | Assoc Dev | WORD | Handle of Associated Type 4 Record
+ * 0x06 | APIC ID | BYTE | Processor local APIC ID
+ * 0x07 | OEM Status | BYTE | Bits: 0: BSP, 1: x2APIC, 2: Therm Margining
+ * 0x08 | Phys Slot | BYTE | Matches silk screen
+ * 0x09 | Phys Socket| BYTE | Matches silk screen
+ * 0x0A | Max Wattage| WORD | Rated max wattage of the processor
+ * 0x0C | x2APIC ID | DWORD | Processor x2APIC (if OEM Status -> x2APIC)
+ * 0x10 | Proc UUID | QWORD | Processor Unique Identifier
+ * 0x18 | Conn Speed | WORD | Interconnect speed in MT/s
+ * 0x1A | QDF/S-SPEC |6 BYTES| Processor QDF/S-SPEC Numbers (Intel only)
+ * 0x20 | Reserved | DWORD | Gen11 Reserved
+ */
+ pr_handle_name("%s Processor Specific Information", company);
+ if (h->length < 0x0A) break;
+ if (!(opt.flags & FLAG_QUIET))
+ pr_attr("Associated Handle", "0x%04X", WORD(data + 0x04));
+ pr_attr("APIC ID", "%u", data[0x06]);
+ feat = data[0x07];
+ pr_attr("BSP", "%s", feat & 0x01 ? "Yes" : "No");
+ pr_attr("x2APIC", "%s", feat & 0x02 ? "Yes" : "No");
+ pr_attr("Advanced Thermal Margining", "%s", feat & 0x04 ? "Yes" : "No");
+ if (data[0x08] != 0xFF)
+ pr_attr("Physical Slot", "%d", data[0x08]);
+ if (data[0x09] != 0xFF)
+ pr_attr("Physical Socket", "%d", data[0x09]);
+ if (h->length < 0x0C) break;
+ if (WORD(data + 0x0A))
+ pr_attr("Maximum Power", "%d W", WORD(data + 0x0A));
+ if (h->length < 0x10) break;
+ if (feat & 0x02)
+ pr_attr("x2APIC ID", "0x%08x", DWORD(data + 0x0C));
+ if (h->length < 0x18) break;
+ if (DWORD(data + 0x10) || DWORD(data + 0x14))
+ pr_attr("UUID", "0x%08x%08x", DWORD(data + 0x14), DWORD(data + 0x10));
+ if (h->length < 0x1A) break;
+ if (WORD(data + 0x18))
+ pr_attr("Interconnect Speed", "%d MT/s", WORD(data + 0x18));
+ if (h->length < 0x20) break;
+ dmi_hp_197_qdf(data + 0x1A);
+ break;
+
case 199:
/*
* Vendor Specific: CPU Microcode Patch
@@ -789,6 +996,10 @@ static int dmi_decode_hp(const struct dmi_header *h)
}
dmi_hp_203_assoc_hndl("Parent Handle", WORD(data + 0x12));
pr_attr("Flags", "0x%04X", WORD(data + 0x14));
+ if (WORD(data + 0x14) & 0x01)
+ pr_subattr("Peer Bifurcated Device", "Yes");
+ if (WORD(data + 0x14) & 0x02)
+ pr_subattr("Upstream Device", "Yes");
dmi_hp_203_devtyp("Device Type", data[0x16]);
dmi_hp_203_devloc("Device Location", data[0x17]);
pr_attr("Device Instance", "%d", data[0x18]);
@@ -853,6 +1064,7 @@ static int dmi_decode_hp(const struct dmi_header *h)
*
* Type 221: is deprecated in the latest docs
*/
+ if (gen >= G8 && h->type == 221) return 0;
pr_handle_name("%s %s", company, h->type == 221 ?
"BIOS iSCSI NIC PCI and MAC Information" :
"BIOS PXE NIC PCI and MAC Information");
@@ -875,6 +1087,7 @@ static int dmi_decode_hp(const struct dmi_header *h)
*
* Source: hpwdt kernel driver
*/
+ if (gen >= G9) return 0;
pr_handle_name("%s 64-bit CRU Information", company);
if (h->length < 0x18) break;
if (is_printable(data + 0x04, 4))
@@ -1034,6 +1247,7 @@ static int dmi_decode_hp(const struct dmi_header *h)
* 0x07 | Dev No | BYTE | PCI Device/Function No
* 0x08 | MAC | 32B | MAC addr padded w/ 0s
* 0x28 | Port No| BYTE | Each NIC maps to a Port
+ * 0x29 | DevPath| STRING| UEFI Device Path of network port
*/
pr_handle_name("%s BIOS PXE NIC PCI and MAC Information",
company);
@@ -1044,6 +1258,8 @@ static int dmi_decode_hp(const struct dmi_header *h)
nic = h->length > 0x28 ? data[0x28] : 0xFF;
dmi_print_hp_net_iface_rec(nic, data[0x06], data[0x07],
&data[0x08]);
+ if (h->length < 0x2A) break;
+ pr_attr("UEFI Device Path", "%s", dmi_string(h, data[0x29]));
break;
case 236:
@@ -1064,6 +1280,7 @@ static int dmi_decode_hp(const struct dmi_header *h)
* 0x13 | A2 Bays | BYTE | (deprecated) Number of SAS drive bays behind port 0xA2
* 0x14 | Name | STRING| (deprecated) Backplane Name
*/
+ if (gen >= G11) return 0;
pr_handle_name("%s HDD Backplane FRU Information", company);
if (h->length < 0x08) break;
pr_attr("FRU I2C Address", "0x%X raw(0x%X)", data[0x4] >> 1, data[0x4]);
@@ -1094,7 +1311,8 @@ static int dmi_decode_hp(const struct dmi_header *h)
* 0x06 | Manufacture|STRING | DIMM Manufacturer
* 0x07 | Part Number|STRING | DIMM Manufacturer's Part Number
* 0x08 | Serial Num |STRING | DIMM Vendor Serial Number
- * 0x09 | Spare Part |STRING | DIMM Spare Part Number
+ * 0x09 | Man Date | BYTE | DIMM Manufacture Date (YEAR) in BCD
+ * 0x0A | Man Date | BYTE | DIMM Manufacture Date (WEEK) in BCD
*/
if (gen < G9) return 0;
pr_handle_name("%s DIMM Vendor Information", company);
@@ -1105,8 +1323,9 @@ static int dmi_decode_hp(const struct dmi_header *h)
pr_attr("DIMM Manufacturer Part Number", "%s", dmi_string(h, data[0x07]));
if (h->length < 0x09) break;
pr_attr("DIMM Vendor Serial Number", "%s", dmi_string(h, data[0x08]));
- if (h->length < 0x0A) break;
- pr_attr("DIMM Spare Part Number", "%s", dmi_string(h, data[0x09]));
+ if (h->length < 0x0B) break;
+ if (WORD(data + 0x09))
+ pr_attr("DIMM Manufacture Date", "20%02x-W%02x", data[0x09], data[0x0A]);
break;
case 238:
@@ -1146,6 +1365,54 @@ static int dmi_decode_hp(const struct dmi_header *h)
pr_attr("Device Path", "%s", dmi_string(h, data[0xE]));
break;
+ case 239:
+ /*
+ * Vendor Specific: HPE USB Device Correlation Record
+ *
+ * This record provides a mechanism for software to correlate USB device
+ * information provided in SMBIOS record Type 8 and Type 238. It
+ * additionally provides device specific data that is typically not
+ * available in SMBIOS to allow HP tools to understand how these device
+ * entries correlate to both UEFI and Legacy USB Boot entries. This record
+ * will only contain information for a device detected by the BIOS during
+ * POST and does not comprehend a hot plug event after the system has
+ * booted. This record will only be supported on UEFI Based systems.
+ *
+ * Offset | Name | Width | Description
+ * -------+------------+-------+------------
+ * 0x00 | Type | BYTE | 0xEF, HP Device Correlation Record
+ * 0x01 | Length | BYTE | Length of structure
+ * 0x02 | Handle | WORD | Unique handle
+ * 0x04 | Hand Assoc | WORD | Handle to map to Type 238
+ * 0x06 | Vendor ID | WORD | Vendor ID of detected USB Device
+ * 0x08 | Flags | WORD | Bit[0] - Indicates presence of SD card
+ * 0x0A | Class | BYTE | USB Device Class per USB HID Dev Spec
+ * 0x0B | Sub Class | BYTE | USB Device SubClass per USB HID Dev Spec
+ * 0x0C | Protocol | BYTE | Device Protocol per USB HID Dev Spec
+ * 0x0D | Product ID | WORD | USB Product ID
+ * 0x0F | Capacity | DWORD | USB Device Capacity (if apropos) in Mbytes
+ * 0x13 | Device Path| STRING| UEFI Device Path
+ * 0x14 | Device Name| STRING| UEFI Device Structured Name
+ * 0x15 | UEFI Name | STRING| Device Name
+ * 0x16 | Location | STRING| USB Device Location
+ */
+ if (gen < G9) return 0;
+ pr_handle_name("%s USB Device Correlation Record", company);
+ if (h->length < 0x17) break;
+ if (!(opt.flags & FLAG_QUIET))
+ pr_attr("Associated Handle", "0x%04X", WORD(data + 0x04));
+ pr_attr("USB Vendor ID", "0x%04x", WORD(data + 0x06));
+ pr_attr("Embedded SD Card", "%s", data[0x08] & 0x01 ? "Present" : "Empty");
+ dmi_hp_239_usb_device(data[0x0A], data[0x0B], data[0x0C]);
+ pr_attr("USB Product ID", "0x%04x", WORD(data + 0x0D));
+ if (DWORD(data + 0x0F))
+ pr_attr("USB Capacity", "%u MB", DWORD(data + 0x0F));
+ pr_attr("UEFI Device Path", "%s", dmi_string(h, data[0x13]));
+ pr_attr("UEFI Device Name", "%s", dmi_string(h, data[0x14]));
+ pr_attr("Device Name", "%s", dmi_string(h, data[0x15]));
+ pr_attr("Device Location", "%s", dmi_string(h, data[0x16]));
+ break;
+
case 240:
/*
* Vendor Specific: HPE Proliant Inventory Record
@@ -1264,6 +1531,40 @@ static int dmi_decode_hp(const struct dmi_header *h)
dmi_hp_242_speed("Negotiated Speed", WORD(data + 0x3A));
dmi_hp_242_speed("Capable Speed", WORD(data + 0x3C));
break;
+
+ case 245:
+ /*
+ * Vendor Specific: HPE Extension Board Inventory Record
+ *
+ * This record provides a mechanism for software to retrieve installed
+ * Extension Boards in system, such as Riser Cards, etc. Each extension
+ * board discovered at system boot time has a corresponding record
+ * produced in SMBIOS Type 245. This record is currently applicable
+ * for ML, DL and Alletra series servers in Gen11 and will be backward
+ * compatible with next generations
+ *
+ * This is a variant record. Definition of fields 0x05 ... vary based
+ * upon field 0x04 Board Type.
+ *
+ * Offset | Name | Width | Description
+ * ---------------------------------------
+ * 0x00 | Type | BYTE | 0xF5, Extension Board Inventory Record
+ * 0x01 | Length | BYTE | Length of structure
+ * 0x02 | Handle | WORD | Unique handle
+ * 0x04 | Board Type | WORD | 0: PCIe Riser, Other Reserved
+ *
+ * If Board Type == 0
+ * 0x05 | Riser Pos | WORD |
+ * 0x06 | Riser ID | BYTE |
+ * 0x07 | CPLD Vers | BTYE | 0-> No CPLD. Bits [7][6:0] Release:Vers
+ * 0x08 | Riser Name | STRING|
+ */
+ pr_handle_name("%s ProLiant Extension Board Inventory Record", company);
+ if (h->length < 0x05) break;
+ if (data[0x04] == 0)
+ dmi_hp_245_pcie_riser(h);
+ break;
+
default:
return 0;
}
diff --git a/dmiopt.c b/dmiopt.c
index fa84f22..0db14e0 100644
--- a/dmiopt.c
+++ b/dmiopt.c
@@ -2,7 +2,7 @@
* Command line handling of dmidecode
* This file is part of the dmidecode project.
*
- * Copyright (C) 2005-2008 Jean Delvare <jdelvare@suse.de>
+ * Copyright (C) 2005-2023 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
@@ -265,6 +265,7 @@ static u32 parse_opt_handle(const char *arg)
int parse_command_line(int argc, char * const argv[])
{
int option;
+ unsigned int i;
const char *optstring = "d:hqs:t:uH:V";
struct option longopts[] = {
{ "dev-mem", required_argument, NULL, 'd' },
@@ -279,6 +280,8 @@ int parse_command_line(int argc, char * const argv[])
{ "handle", required_argument, NULL, 'H' },
{ "oem-string", required_argument, NULL, 'O' },
{ "no-sysfs", no_argument, NULL, 'S' },
+ { "list-strings", no_argument, NULL, 'L' },
+ { "list-types", no_argument, NULL, 'T' },
{ "version", no_argument, NULL, 'V' },
{ NULL, 0, NULL, 0 }
};
@@ -332,6 +335,16 @@ int parse_command_line(int argc, char * const argv[])
case 'S':
opt.flags |= FLAG_NO_SYSFS;
break;
+ case 'L':
+ for (i = 0; i < ARRAY_SIZE(opt_string_keyword); i++)
+ fprintf(stdout, "%s\n", opt_string_keyword[i].keyword);
+ opt.flags |= FLAG_LIST;
+ return 0;
+ case 'T':
+ for (i = 0; i < ARRAY_SIZE(opt_type_keyword); i++)
+ fprintf(stdout, "%s\n", opt_type_keyword[i].keyword);
+ opt.flags |= FLAG_LIST;
+ return 0;
case 'V':
opt.flags |= FLAG_VERSION;
break;
@@ -377,7 +390,9 @@ void print_help(void)
" -q, --quiet Less verbose output\n"
" --no-quirks Decode everything without quirks\n"
" -s, --string KEYWORD Only display the value of the given DMI string\n"
+ " --list-strings List available string keywords and exit\n"
" -t, --type TYPE Only display the entries of given type\n"
+ " --list-types List available type keywords and exit\n"
" -H, --handle HANDLE Only display the entry of given handle\n"
" -u, --dump Do not decode the entries\n"
" --dump-bin FILE Dump the DMI data to a binary file\n"
diff --git a/dmiopt.h b/dmiopt.h
index 62ffcbb..ae04778 100644
--- a/dmiopt.h
+++ b/dmiopt.h
@@ -2,7 +2,7 @@
* Command line handling of dmidecode
* This file is part of the dmidecode project.
*
- * Copyright (C) 2005-2008 Jean Delvare <jdelvare@suse.de>
+ * Copyright (C) 2005-2023 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
@@ -47,6 +47,7 @@ extern struct opt opt;
#define FLAG_FROM_DUMP (1 << 5)
#define FLAG_NO_SYSFS (1 << 6)
#define FLAG_NO_QUIRKS (1 << 7)
+#define FLAG_LIST (1 << 8)
int parse_command_line(int argc, char * const argv[]);
void print_help(void);
diff --git a/man/dmidecode.8 b/man/dmidecode.8
index 83affc2..77c89a5 100644
--- a/man/dmidecode.8
+++ b/man/dmidecode.8
@@ -127,6 +127,10 @@ typically from files under
.IR /sys/devices/virtual/dmi/id .
Most of these files are even readable by regular users.
.TP
+.BR " " " " "--list-strings"
+List available string keywords, which can then be passed to the \fB--string\fP
+option.
+.TP
.BR "-t" ", " "--type \fITYPE\fP"
Only display the entries of type \fITYPE\fP. It can be either a
\s-1DMI\s0 type number, or a comma-separated list of type numbers, or a
@@ -150,6 +154,10 @@ is printed and
.B dmidecode
exits with an error.
.TP
+.BR " " " " "--list-types"
+List available type keywords, which can then be passed to the \fB--type\fP
+option.
+.TP
.BR "-H" ", " "--handle \fIHANDLE\fP"
Only display the entry whose handle matches \fIHANDLE\fP.
\fIHANDLE\fP is a 16-bit integer.
diff --git a/util.c b/util.c
index 2770b1d..dce84ff 100644
--- a/util.c
+++ b/util.c
@@ -2,7 +2,7 @@
* Common "util" functions
* This file is part of the dmidecode project.
*
- * Copyright (C) 2002-2018 Jean Delvare <jdelvare@suse.de>
+ * Copyright (C) 2002-2023 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
diff --git a/util.h b/util.h
index ef24eb9..0d37f35 100644
--- a/util.h
+++ b/util.h
@@ -1,7 +1,7 @@
/*
* This file is part of the dmidecode project.
*
- * Copyright (C) 2003-2017 Jean Delvare <jdelvare@suse.de>
+ * Copyright (C) 2003-2023 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
diff --git a/version.h b/version.h
index 179ab30..dc5afe3 100644
--- a/version.h
+++ b/version.h
@@ -1 +1 @@
-#define VERSION "3.5"
+#define VERSION "3.6"