Since version 3.0.0 of the SMBIOS specification, there can be multiple entry points in memory, pointing to one or two DMI tables. If both a 32-bit ("_SM_") entry point and a 64-bit ("_SM3_") entry point are present, the specification requires that the latter points to a table which is a super-set of the table pointed to by the former. Therefore we should give preference to the 64-bit ("_SM3_") entry point.
However, currently the code is picking the first valid entry point it finds. Per specification, we should look for a 64-bit ("_SM3_") entry point first, and if we can't find any, look for a 32-bit ("_SM_" or "_DMI_") entry point. Modify the code to do that. Signed-off-by: Jean Delvare <jdelv...@suse.de> --- * Note 1: I can't test the 64-bit ("_SM3_") entry point case. I would appreciate if someone with access to a machine supporting legacy (non-UEFI) mode and implementing a 64-bit table could test and report. * Note 2: I'm not particularly happy with this change as it will make the entry point scan 3 times slower on average for legacy machines, but I couldn't come up with anything smarter. If anyone can think of a better implementation, please let me know. drivers/firmware/dmi_scan.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) --- linux-4.10-rc4.orig/drivers/firmware/dmi_scan.c 2017-01-04 14:05:09.392301072 +0100 +++ linux-4.10-rc4/drivers/firmware/dmi_scan.c 2017-01-16 11:55:24.500984728 +0100 @@ -649,6 +649,21 @@ void __init dmi_scan_machine(void) goto error; /* + * Same logic as above, look for a 64-bit entry point + * first, and if not found, fall back to 32-bit entry point. + */ + memcpy_fromio(buf, p, 16); + for (q = p + 16; q < p + 0x10000; q += 16) { + memcpy_fromio(buf + 16, q, 16); + if (!dmi_smbios3_present(buf)) { + dmi_available = 1; + dmi_early_unmap(p, 0x10000); + goto out; + } + memcpy(buf, buf + 16, 16); + } + + /* * Iterate over all possible DMI header addresses q. * Maintain the 32 bytes around q in buf. On the * first iteration, substitute zero for the @@ -658,7 +673,7 @@ void __init dmi_scan_machine(void) memset(buf, 0, 16); for (q = p; q < p + 0x10000; q += 16) { memcpy_fromio(buf + 16, q, 16); - if (!dmi_smbios3_present(buf) || !dmi_present(buf)) { + if (!dmi_present(buf)) { dmi_available = 1; dmi_early_unmap(p, 0x10000); goto out; -- Jean Delvare SUSE L3 Support