firmware: dmi_scan: Look for SMBIOS 3 entry point first
PATCH 1/1 firmware: dmi_scan: Look for SMBIOS 3 entry point first
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.
---
* 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(-)
drivers/firmware/dmi_scan.c +16 -1
@@ -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;
Signature · 2 lines
Jean Delvare SUSE L3 Support