summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean Delvare <jdelvare@suse.de>2021-01-15 17:20:16 +0100
committerJean Delvare <jdelvare@suse.de>2021-01-15 17:20:16 +0100
commit89efc6b9563a70da9f2a91c05455ba9e7b37e126 (patch)
tree5f399b6ed6aef438d3c5d84f510192ea9f6c0838
parent1117390ccd9cea139638db6f460bb6de70e28f94 (diff)
downloaddmidecode-git-89efc6b9563a70da9f2a91c05455ba9e7b37e126.tar.gz
dmidecode: Set vendor early
If OEM type entries come before the type 1 entry (System Information), we aren't able to decode them because we don't know the vendor yet. To fix this, figure out the vendor during a first pass, and walk the table again once we have the information. Signed-off-by: Jean Delvare <jdelvare@suse.de> Reported-by: Erwan Velu <e.velu@criteo.com>
-rw-r--r--dmidecode.c50
1 files changed, 45 insertions, 5 deletions
diff --git a/dmidecode.c b/dmidecode.c
index 864a193..344dce7 100644
--- a/dmidecode.c
+++ b/dmidecode.c
@@ -5182,6 +5182,51 @@ static void dmi_table_decode(u8 *buf, u32 len, u16 num, u16 ver, u32 flags)
u8 *data;
int i = 0;
+ /* First pass: Save the vendor so that so that we can decode OEM types */
+ data = buf;
+ while ((i < num || !num)
+ && data + 4 <= buf + len) /* 4 is the length of an SMBIOS structure header */
+ {
+ u8 *next;
+ struct dmi_header h;
+
+ to_dmi_header(&h, data);
+
+ /*
+ * If a short entry is found (less than 4 bytes), not only it
+ * is invalid, but we cannot reliably locate the next entry.
+ * Also stop at end-of-table marker if so instructed.
+ */
+ if (h.length < 4 ||
+ (h.type == 127 &&
+ (opt.flags & (FLAG_QUIET | FLAG_STOP_AT_EOT))))
+ break;
+ i++;
+
+ /* Look for the next handle */
+ next = data + h.length;
+ while ((unsigned long)(next - buf + 1) < len
+ && (next[0] != 0 || next[1] != 0))
+ next++;
+ next += 2;
+
+ /* Make sure the whole structure fits in the table */
+ if ((unsigned long)(next - buf) > len)
+ break;
+
+ /* Assign vendor for vendor-specific decodes later */
+ if (h.type == 1 && h.length >= 6)
+ {
+ dmi_set_vendor(_dmi_string(&h, data[0x04], 0),
+ _dmi_string(&h, data[0x05], 0));
+ break;
+ }
+
+ data = next;
+ }
+
+ /* Second pass: Actually decode the data */
+ i = 0;
data = buf;
while ((i < num || !num)
&& data + 4 <= buf + len) /* 4 is the length of an SMBIOS structure header */
@@ -5241,11 +5286,6 @@ static void dmi_table_decode(u8 *buf, u32 len, u16 num, u16 ver, u32 flags)
break;
}
- /* assign vendor for vendor-specific decodes later */
- if (h.type == 1 && h.length >= 6)
- dmi_set_vendor(_dmi_string(&h, data[0x04], 0),
- _dmi_string(&h, data[0x05], 0));
-
/* Fixup a common mistake */
if (h.type == 34)
dmi_fixup_type_34(&h, display);