mirror of
https://git.jff.email/cgit/dmidecode.git
synced 2026-08-07 01:28:12 +00:00
Merge branch 'feature/upstream' into develop
This commit is contained in:
commit
c38426c9a9
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +0,0 @@
|
||||
.pc
|
||||
debian/files
|
||||
18
Makefile
18
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
|
||||
|
||||
19
NEWS
19
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.
|
||||
|
||||
40
completion/biosdecode.bash
Normal file
40
completion/biosdecode.bash
Normal file
@ -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
|
||||
60
completion/dmidecode.bash
Normal file
60
completion/dmidecode.bash
Normal file
@ -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
|
||||
33
completion/ownership.bash
Normal file
33
completion/ownership.bash
Normal file
@ -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
|
||||
43
completion/vpddecode.bash
Normal file
43
completion/vpddecode.bash
Normal file
@ -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
|
||||
2
config.h
2
config.h
@ -22,7 +22,7 @@
|
||||
#endif
|
||||
|
||||
/* Use memory alignment workaround or not */
|
||||
#ifdef __ia64__
|
||||
#if defined(__ia64__) || defined(__arm__)
|
||||
#define ALIGNMENT_WORKAROUND
|
||||
#endif
|
||||
|
||||
|
||||
387
dmidecode.c
387
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;
|
||||
|
||||
@ -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;
|
||||
|
||||
349
dmioem.c
349
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;
|
||||
}
|
||||
|
||||
17
dmiopt.c
17
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"
|
||||
|
||||
3
dmiopt.h
3
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);
|
||||
|
||||
@ -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.
|
||||
|
||||
2
util.c
2
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
|
||||
|
||||
2
util.h
2
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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user