[PATCH 4/6] dmicheck: add test for smbios 3.0.0 entry point

Ivan Hu ivan.hu at canonical.com
Wed Sep 2 07:36:53 UTC 2015


Signed-off-by: Ivan Hu <ivan.hu at canonical.com>
---
 src/dmi/dmicheck/dmicheck.c | 157 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 154 insertions(+), 3 deletions(-)

diff --git a/src/dmi/dmicheck/dmicheck.c b/src/dmi/dmicheck/dmicheck.c
index 02bca98..57a7475 100644
--- a/src/dmi/dmicheck/dmicheck.c
+++ b/src/dmi/dmicheck/dmicheck.c
@@ -85,6 +85,7 @@ typedef struct {
 } fwts_dmi_used_by_kernel;
 
 static bool smbios_found = false;
+static bool smbios30_found = false;
 
 /*
  *  Table derived by scanning thousands of DMI table dumps from bug reports
@@ -337,6 +338,23 @@ static void dmi_dump_entry(fwts_framework *fw, fwts_smbios_entry *entry, fwts_sm
 		fwts_log_info_verbatum(fw, "    BCD Revision 00 indicates compliance with specification stated in Major/Minor Version.");
 }
 
+static void dmi_dump_entry30(fwts_framework *fw, fwts_smbios30_entry *entry)
+{
+
+	fwts_log_info_verbatum(fw, "SMBIOS30 Entry Point Structure:");
+	fwts_log_info_verbatum(fw, "  Anchor String          : %5.5s", entry->signature);
+	fwts_log_info_verbatum(fw, "  Checksum               : 0x%2.2" PRIx8, entry->checksum);
+	fwts_log_info_verbatum(fw, "  Entry Point Length     : 0x%2.2" PRIx8, entry->length);
+	fwts_log_info_verbatum(fw, "  Major Version          : 0x%2.2" PRIx8, entry->major_version);
+	fwts_log_info_verbatum(fw, "  Minor Version          : 0x%2.2" PRIx8, entry->minor_version);
+	fwts_log_info_verbatum(fw, "  Docrev                 : 0x%2.2" PRIx8, entry->docrev);
+	fwts_log_info_verbatum(fw, "  Entry Point Revision   : 0x%2.2" PRIx8, entry->revision);
+	fwts_log_info_verbatum(fw, "  Reserved               : 0x%2.2" PRIx8, entry->reserved);
+	fwts_log_info_verbatum(fw, "  Table maximum size     : 0x%8.8" PRIx32, entry->struct_table_max_size);
+	fwts_log_info_verbatum(fw, "  Table address          : 0x%16.16" PRIx64, entry->struct_table_address);
+
+}
+
 static int dmi_sane(fwts_framework *fw, fwts_smbios_entry *entry)
 {
 	uint8_t	*table, *ptr;
@@ -492,6 +510,135 @@ static int smbios_entry_check(fwts_framework *fw)
 
 }
 
+static int dmi_smbios30_sane(fwts_framework *fw, fwts_smbios30_entry *entry)
+{
+	uint8_t	*table, *ptr;
+	uint8_t struct_length;
+	uint8_t struct_type = 0;
+	uint16_t i = 0;
+	uint32_t table_length = entry->struct_table_max_size;
+	int ret = FWTS_OK;
+
+	ptr = table = fwts_mmap((off_t)entry->struct_table_address,
+			  (size_t)table_length);
+	if (table == FWTS_MAP_FAILED) {
+		fwts_failed(fw, LOG_LEVEL_MEDIUM,
+			"SMBIOS30TableAddressNotMapped",
+			"Cannot mmap SMBIOS 3.0 tables from "
+			"%16.16" PRIx64 "..%16.16" PRIx64 ".",
+			entry->struct_table_address,
+			entry->struct_table_address + table_length);
+			return FWTS_ERROR;
+	}
+
+	while (1)
+	{
+		if (ptr > table + table_length) {
+			fwts_failed(fw, LOG_LEVEL_MEDIUM,
+				"SMBIOS30TableLengthTooSmall",
+				"The maximum size indicated by the SMBIOS 3.0 table length is "
+				"smaller than the dmi data or the DMI end of table not found.");
+			ret = FWTS_ERROR;
+			break;
+		}
+
+		struct_type = ptr[0];
+		struct_length = ptr[1];
+
+		if (struct_length < 4) {
+			fwts_failed(fw, LOG_LEVEL_MEDIUM,
+				"SMBIOSIllegalTableEntry",
+				"The size of a DMI entry %" PRIu16 " is illegal, "
+				"DMI data is either wrong or the SMBIOS Table "
+				"Pointer is pointing to the wrong memory region.", i);
+			ret = FWTS_ERROR;
+			break;
+		}
+		ptr += struct_length;
+
+		/* Scan for end of DMI entry, must be 2 zero bytes */
+		while (((ptr - table + 1) < table_length) &&
+		       ((ptr[0] != 0) || (ptr[1] != 0)))
+				ptr++;
+		/* Skip over the two zero bytes */
+		ptr += 2;
+
+		/* We found DMI end of table and inside the maximum length? */
+		if (struct_type == 127) {
+			if (ptr <= table + table_length)
+				break;
+			else {
+				fwts_failed(fw, LOG_LEVEL_HIGH,
+					"SMBIOS30TableLengthTooSmall",
+					"The end of DMI table marker structure was found "
+					"but outside the structure table maximum size");
+				ret = FWTS_ERROR;
+				break;
+			}
+		}
+	}
+
+	(void)fwts_munmap(table, (size_t)entry->struct_table_max_size);
+
+	return ret;
+}
+
+static int smbios30_entry_check(fwts_framework *fw)
+{
+	void *addr = 0;
+
+	fwts_smbios30_entry entry;
+	uint16_t version;
+	uint8_t checksum;
+
+	if ((addr = fwts_smbios30_find_entry(fw, &entry, &version)) == NULL)
+		return FWTS_ERROR;
+
+	fwts_passed(fw, "Found SMBIOS30 Table Entry Point at %p", addr);
+	dmi_dump_entry30(fw, &entry);
+	fwts_log_nl(fw);
+
+	checksum = fwts_checksum((uint8_t *)&entry, sizeof(fwts_smbios30_entry));
+	if (checksum != 0)
+		fwts_failed(fw, LOG_LEVEL_HIGH,
+			"SMBIOS30BadChecksum",
+			"SMBIOS30 Table Entry Point Checksum is 0x%2.2" PRIx8
+			", should be 0x%2.2" PRIx8,
+			entry.checksum, (uint8_t)(entry.checksum - checksum));
+	else
+		fwts_passed(fw, "SMBIOS30 Table Entry Point Checksum is valid.");
+
+	if (entry.length != 0x18) {
+		fwts_failed(fw, LOG_LEVEL_MEDIUM,
+			"SMBIOS30BadEntryLength",
+			"SMBIOS30 Table Entry Point Length is 0x%2.2"  PRIx8
+			", should be 0x18", entry.length);
+	} else
+		fwts_passed(fw, "SMBIOS30 Table Entry Point Length is valid.");
+
+	if (entry.reserved)
+		fwts_failed(fw, LOG_LEVEL_MEDIUM,
+			"SMBIOSBadReserved",
+			"SMBIOS30 Table Entry Point Reserved is 0x%2.2" PRIx8
+			", should be 0", entry.reserved);
+
+	if ((entry.revision == 1) && (entry.struct_table_address == 0)) {
+		fwts_failed(fw, LOG_LEVEL_HIGH,
+			"SMBIOS30BadTableAddress",
+			"SMBIOS Table Entry Structure Table Address is NULL and should be defined.");
+	} else {
+		/*
+		 * Now does the SMBIOS 3.0.0 table look sane? If not,
+		 * the SMBIOS Structure Table could be bad
+		 */
+		if (dmi_smbios30_sane(fw, &entry) == FWTS_OK)
+			fwts_passed(fw, "SMBIOS 3.0 Table Entry Structure Table Address and Length looks valid.");
+	}
+
+	return FWTS_OK;
+
+}
+
 static int dmicheck_test1(fwts_framework *fw)
 {
 
@@ -499,10 +646,14 @@ static int dmicheck_test1(fwts_framework *fw)
 		smbios_found = true;
 	}
 
-	if (!smbios_found) {
+	if (smbios30_entry_check(fw) != FWTS_ERROR) {
+		smbios30_found = true;
+	}
+
+	if (!smbios_found && !smbios30_found) {
 		fwts_failed(fw, LOG_LEVEL_HIGH,
 			"SMBIOSNoEntryPoint",
-			"Could not find SMBIOS Table Entry Point.");
+			"Could not find any SMBIOS Table Entry Points.");
 		return FWTS_ERROR;
 	}
 
@@ -1605,7 +1756,7 @@ static int dmicheck_test2(fwts_framework *fw)
 }
 
 static fwts_framework_minor_test dmicheck_tests[] = {
-	{ dmicheck_test1, "Find and test SMBIOS Table Entry Point." },
+	{ dmicheck_test1, "Find and test SMBIOS Table Entry Points." },
 	{ dmicheck_test2, "Test DMI/SMBIOS tables for errors." },
 	{ NULL, NULL }
 };
-- 
1.9.1




More information about the fwts-devel mailing list