From patchwork Wed Jul 3 12:51:54 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Hung X-Patchwork-Id: 256624 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) by ozlabs.org (Postfix) with ESMTP id DABDA2C008F for ; Wed, 3 Jul 2013 22:52:14 +1000 (EST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.76) (envelope-from ) id 1UuMXd-0008HK-MZ; Wed, 03 Jul 2013 12:52:13 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtp (Exim 4.76) (envelope-from ) id 1UuMXX-0008H1-VG for fwts-devel@lists.ubuntu.com; Wed, 03 Jul 2013 12:52:07 +0000 Received: from [175.182.138.101] (helo=canonical.com) by youngberry.canonical.com with esmtpsa (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1UuMXW-0000Yl-C0; Wed, 03 Jul 2013 12:52:07 +0000 From: Alex Hung To: fwts-devel@lists.ubuntu.com Subject: [PATCH 1/2] dmi: dmi_decode: merge smbios test as they both check dmi/smbios Date: Wed, 3 Jul 2013 20:51:54 +0800 Message-Id: <1372855915-9058-2-git-send-email-alex.hung@canonical.com> X-Mailer: git-send-email 1.8.1.2 In-Reply-To: <1372855915-9058-1-git-send-email-alex.hung@canonical.com> References: <1372855915-9058-1-git-send-email-alex.hung@canonical.com> X-BeenThere: fwts-devel@lists.ubuntu.com X-Mailman-Version: 2.1.14 Precedence: list List-Id: Firmware Test Suite Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: fwts-devel-bounces@lists.ubuntu.com Sender: fwts-devel-bounces@lists.ubuntu.com Signed-off-by: Alex Hung Acked-by: Colin Ian King Acked-by: Ivan Hu --- src/Makefile.am | 1 - src/bios/smbios/smbios.c | 225 ---------------------------------------- src/dmi/dmi_decode/dmi_decode.c | 192 +++++++++++++++++++++++++++++++++- 3 files changed, 190 insertions(+), 228 deletions(-) delete mode 100644 src/bios/smbios/smbios.c diff --git a/src/Makefile.am b/src/Makefile.am index 4f419dd..1516639 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -58,7 +58,6 @@ fwts_SOURCES = main.c \ bios/pciirq/pciirq.c \ bios/pnp/pnp.c \ bios/romdump/romdump.c \ - bios/smbios/smbios.c \ cmos/cmosdump/cmosdump.c \ cpu/virt/virt.c \ cpu/virt/virt_svm.c \ diff --git a/src/bios/smbios/smbios.c b/src/bios/smbios/smbios.c deleted file mode 100644 index 022447a..0000000 --- a/src/bios/smbios/smbios.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (C) 2010-2013 Canonical - * - * 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 the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ -#include -#include - -#include "fwts.h" - -#ifdef FWTS_ARCH_INTEL - -static void smbios_dump_entry(fwts_framework *fw, fwts_smbios_entry *entry, fwts_smbios_type type) -{ - if (type == FWTS_SMBIOS) { - fwts_log_info_verbatum(fw, "SMBIOS Entry Point Structure:"); - fwts_log_info_verbatum(fw, " Anchor String : %4.4s", entry->signature); - fwts_log_info_verbatum(fw, " Checksum : 0x%2.2x", entry->checksum); - fwts_log_info_verbatum(fw, " Entry Point Length : 0x%2.2x", entry->length); - fwts_log_info_verbatum(fw, " Major Version : 0x%2.2x", entry->major_version); - fwts_log_info_verbatum(fw, " Minor Version : 0x%2.2x", entry->minor_version); - fwts_log_info_verbatum(fw, " Maximum Struct Size : 0x%2.2x", entry->max_struct_size); - fwts_log_info_verbatum(fw, " Entry Point Revision : 0x%2.2x", entry->revision); - fwts_log_info_verbatum(fw, " Formatted Area : 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x", - entry->formatted_area[0], entry->formatted_area[1], - entry->formatted_area[2], entry->formatted_area[3], - entry->formatted_area[4]); - } - if (type == FWTS_SMBIOS_DMI_LEGACY) - fwts_log_info_verbatum(fw, "Legacy DMI Entry Point Structure:"); - - /* Common to SMBIOS and SMBIOS_DMI_LEGACY */ - fwts_log_info_verbatum(fw, " Intermediate Anchor : %5.5s", (char *)entry->anchor_string); - fwts_log_info_verbatum(fw, " Intermediate Checksum : 0x%2.2x", entry->intermediate_checksum); - fwts_log_info_verbatum(fw, " Structure Table Length : 0x%4.4x", entry->struct_table_length); - fwts_log_info_verbatum(fw, " Structure Table Address: 0x%8.8x", entry->struct_table_address); - fwts_log_info_verbatum(fw, " # of SMBIOS Structures : 0x%4.4x", entry->number_smbios_structures); - fwts_log_info_verbatum(fw, " SBMIOS BCD Revision : %2.2x", entry->smbios_bcd_revision); - if (entry->smbios_bcd_revision == 0) - fwts_log_info_verbatum(fw, " BCD Revision 00 indicates compliance with specification stated in Major/Minor Version."); -} - -static int smbios_dmi_sane(fwts_framework *fw, fwts_smbios_entry *entry) -{ - uint8_t *table, *ptr; - uint8_t dmi_entry_length; - uint8_t dmi_entry_type = 0; - uint16_t i = 0; - uint16_t table_length = entry->struct_table_length; - 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, - "SMBIOSTableAddressNotMapped", - "Cannot mmap SMBIOS tables from " - "%8.8" PRIx32 "..%8.8" PRIx32 ".", - entry->struct_table_address, - entry->struct_table_address + table_length); - return FWTS_ERROR; - } - - for (i = 0; i < entry->number_smbios_structures; i++) { - if (ptr > table + table_length) { - fwts_failed(fw, LOG_LEVEL_MEDIUM, - "SMBIOSTableLengthTooSmall", - "The size indicated by the SMBIOS table length is " - "smaller than the DMI data."); - ret = FWTS_ERROR; - break; - } - - dmi_entry_type = ptr[0]; - dmi_entry_length = ptr[1]; - - if (dmi_entry_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 += dmi_entry_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, are number of entries correct? */ - if ((dmi_entry_type == 127) && (i != entry->number_smbios_structures)) { - fwts_failed(fw, LOG_LEVEL_MEDIUM, - "SMBIOSNumberOfStructures", - "The end of DMI table marker structure was found " - "but only %d DMI structures were found. The SMBIOS " - "entry table reported that there were %" PRIu16 - " DMI structures in the DMI table.", - i, entry->number_smbios_structures); - /* And table length can't be correct either */ - ret = FWTS_ERROR; - } - - (void)fwts_munmap(table, (size_t)entry->struct_table_length); - - return ret; -} - -static int smbios_test1(fwts_framework *fw) -{ - void *addr = 0; - fwts_smbios_entry entry; - fwts_smbios_type type; - uint16_t version; - uint8_t checksum; - static char warning[] = - "This field is not checked by the kernel, and so will not affect the system, " - "however it should be fixed to conform to the latest version of the " - "System Management BIOS (SMBIOS) Reference Specification. "; - - fwts_log_info(fw, - "This test tries to find and sanity check the SMBIOS " - "data structures."); - - if ((addr = fwts_smbios_find_entry(fw, &entry, &type, &version)) == NULL) { - fwts_failed(fw, LOG_LEVEL_MEDIUM, - "SMBIOSNoEntryPoint", - "Could not find SMBIOS Table Entry Point."); - return FWTS_OK; - } - - fwts_passed(fw, "Found SMBIOS Table Entry Point at %p", addr); - smbios_dump_entry(fw, &entry, type); - fwts_log_nl(fw); - - if (type == FWTS_SMBIOS) { - checksum = fwts_checksum((uint8_t*)&entry, sizeof(fwts_smbios_entry)); - if (checksum != 0) - fwts_failed(fw, LOG_LEVEL_HIGH, - "SMBIOSBadChecksum", - "SMBIOS Table Entry Point Checksum is 0x%2.2x, should be 0x%2.2x", - entry.checksum, (uint8_t)(entry.checksum - checksum)); - else - fwts_passed(fw, "SMBIOS Table Entry Point Checksum is valid."); - - if (entry.length != 0x1f) { - fwts_failed(fw, LOG_LEVEL_LOW, - "SMBIOSBadEntryLength", - "SMBIOS Table Entry Point Length is 0x%2.2x, should be 0x1f", entry.length); - fwts_advice(fw, "%s Note that version 2.1 of the specification incorrectly stated that the " - "Entry Point Length should be 0x1e when it should be 0x1f.", warning); - } else - fwts_passed(fw, "SMBIOS Table Entry Point Length is valid."); - } - - if (memcmp(entry.anchor_string, "_DMI_", 5) != 0) { - fwts_failed(fw, LOG_LEVEL_HIGH, - "SMBIOSBadIntermediateAnchor", - "SMBIOS Table Entry Intermediate Anchor String was '%5.5s' and should be '_DMI_'.", - entry.anchor_string); - fwts_advice(fw, "%s", warning); - } else - fwts_passed(fw, "SMBIOS Table Entry Intermediate Anchor String _DMI_ is valid."); - - /* Intermediate checksum for legacy DMI */ - checksum = fwts_checksum(((uint8_t*)&entry)+16, 15); - if (checksum != 0) - fwts_failed(fw, LOG_LEVEL_HIGH, - "SMBIOSBadChecksum", - "SMBIOS Table Entry Point Intermediate Checksum is 0x%2.2x, should be 0x%2.2x", - entry.intermediate_checksum, - (uint8_t)(entry.intermediate_checksum - checksum)); - else - fwts_passed(fw, "SMBIOS Table Entry Point Intermediate Checksum is valid."); - - if ((entry.struct_table_length > 0) && (entry.struct_table_address == 0)) { - fwts_failed(fw, LOG_LEVEL_HIGH, - "SMBIOSBadTableAddress", - "SMBIOS Table Entry Structure Table Address is NULL and should be defined."); - fwts_advice(fw, - "The address of the SMBIOS Structure Tables must be defined if the " - "length of these tables is defined."); - } else { - /* - * Now does the DMI table look sane? If not, - * the SMBIOS Structure Table could be bad - */ - if (smbios_dmi_sane(fw, &entry) == FWTS_OK) - fwts_passed(fw, "SMBIOS Table Entry Structure Table Address and Length looks valid."); - } - - return FWTS_OK; -} - -static fwts_framework_minor_test smbios_tests[] = { - { smbios_test1, "Find and Check SMBIOS Table Entry Point." }, - { NULL, NULL } -}; - -static fwts_framework_ops smbios_ops = { - .description = "Check SMBIOS.", - .minor_tests = smbios_tests -}; - -FWTS_REGISTER("smbios", &smbios_ops, FWTS_TEST_ANYTIME, FWTS_FLAG_BATCH | FWTS_FLAG_ROOT_PRIV); - -#endif diff --git a/src/dmi/dmi_decode/dmi_decode.c b/src/dmi/dmi_decode/dmi_decode.c index acdf333..80704fe 100644 --- a/src/dmi/dmi_decode/dmi_decode.c +++ b/src/dmi/dmi_decode/dmi_decode.c @@ -199,6 +199,193 @@ static fwts_dmi_used_by_kernel dmi_used_by_kernel_table[] = { { TYPE_EOD, 0xff }, }; +static void dmi_dump_entry(fwts_framework *fw, fwts_smbios_entry *entry, fwts_smbios_type type) +{ + if (type == FWTS_SMBIOS) { + fwts_log_info_verbatum(fw, "SMBIOS Entry Point Structure:"); + fwts_log_info_verbatum(fw, " Anchor String : %4.4s", entry->signature); + fwts_log_info_verbatum(fw, " Checksum : 0x%2.2x", entry->checksum); + fwts_log_info_verbatum(fw, " Entry Point Length : 0x%2.2x", entry->length); + fwts_log_info_verbatum(fw, " Major Version : 0x%2.2x", entry->major_version); + fwts_log_info_verbatum(fw, " Minor Version : 0x%2.2x", entry->minor_version); + fwts_log_info_verbatum(fw, " Maximum Struct Size : 0x%2.2x", entry->max_struct_size); + fwts_log_info_verbatum(fw, " Entry Point Revision : 0x%2.2x", entry->revision); + fwts_log_info_verbatum(fw, " Formatted Area : 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x", + entry->formatted_area[0], entry->formatted_area[1], + entry->formatted_area[2], entry->formatted_area[3], + entry->formatted_area[4]); + } + if (type == FWTS_SMBIOS_DMI_LEGACY) + fwts_log_info_verbatum(fw, "Legacy DMI Entry Point Structure:"); + + /* Common to SMBIOS and SMBIOS_DMI_LEGACY */ + fwts_log_info_verbatum(fw, " Intermediate Anchor : %5.5s", (char *)entry->anchor_string); + fwts_log_info_verbatum(fw, " Intermediate Checksum : 0x%2.2x", entry->intermediate_checksum); + fwts_log_info_verbatum(fw, " Structure Table Length : 0x%4.4x", entry->struct_table_length); + fwts_log_info_verbatum(fw, " Structure Table Address: 0x%8.8x", entry->struct_table_address); + fwts_log_info_verbatum(fw, " # of SMBIOS Structures : 0x%4.4x", entry->number_smbios_structures); + fwts_log_info_verbatum(fw, " SBMIOS BCD Revision : %2.2x", entry->smbios_bcd_revision); + if (entry->smbios_bcd_revision == 0) + fwts_log_info_verbatum(fw, " BCD Revision 00 indicates compliance with specification stated in Major/Minor Version."); +} + +static int dmi_sane(fwts_framework *fw, fwts_smbios_entry *entry) +{ + uint8_t *table, *ptr; + uint8_t dmi_entry_length; + uint8_t dmi_entry_type = 0; + uint16_t i = 0; + uint16_t table_length = entry->struct_table_length; + 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, + "SMBIOSTableAddressNotMapped", + "Cannot mmap SMBIOS tables from " + "%8.8" PRIx32 "..%8.8" PRIx32 ".", + entry->struct_table_address, + entry->struct_table_address + table_length); + return FWTS_ERROR; + } + + for (i = 0; i < entry->number_smbios_structures; i++) { + if (ptr > table + table_length) { + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "SMBIOSTableLengthTooSmall", + "The size indicated by the SMBIOS table length is " + "smaller than the DMI data."); + ret = FWTS_ERROR; + break; + } + + dmi_entry_type = ptr[0]; + dmi_entry_length = ptr[1]; + + if (dmi_entry_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 += dmi_entry_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, are number of entries correct? */ + if ((dmi_entry_type == 127) && (i != entry->number_smbios_structures)) { + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "SMBIOSNumberOfStructures", + "The end of DMI table marker structure was found " + "but only %d DMI structures were found. The SMBIOS " + "entry table reported that there were %" PRIu16 + " DMI structures in the DMI table.", + i, entry->number_smbios_structures); + /* And table length can't be correct either */ + ret = FWTS_ERROR; + } + + (void)fwts_munmap(table, (size_t)entry->struct_table_length); + + return ret; +} + +static int dmi_decode_test1(fwts_framework *fw) +{ + void *addr = 0; + fwts_smbios_entry entry; + fwts_smbios_type type; + uint16_t version; + uint8_t checksum; + static char warning[] = + "This field is not checked by the kernel, and so will not affect the system, " + "however it should be fixed to conform to the latest version of the " + "System Management BIOS (SMBIOS) Reference Specification. "; + + fwts_log_info(fw, + "This test tries to find and sanity check the SMBIOS " + "data structures."); + + if ((addr = fwts_smbios_find_entry(fw, &entry, &type, &version)) == NULL) { + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "SMBIOSNoEntryPoint", + "Could not find SMBIOS Table Entry Point."); + return FWTS_OK; + } + + fwts_passed(fw, "Found SMBIOS Table Entry Point at %p", addr); + dmi_dump_entry(fw, &entry, type); + fwts_log_nl(fw); + + if (type == FWTS_SMBIOS) { + checksum = fwts_checksum((uint8_t*)&entry, sizeof(fwts_smbios_entry)); + if (checksum != 0) + fwts_failed(fw, LOG_LEVEL_HIGH, + "SMBIOSBadChecksum", + "SMBIOS Table Entry Point Checksum is 0x%2.2x, should be 0x%2.2x", + entry.checksum, (uint8_t)(entry.checksum - checksum)); + else + fwts_passed(fw, "SMBIOS Table Entry Point Checksum is valid."); + + if (entry.length != 0x1f) { + fwts_failed(fw, LOG_LEVEL_LOW, + "SMBIOSBadEntryLength", + "SMBIOS Table Entry Point Length is 0x%2.2x, should be 0x1f", entry.length); + fwts_advice(fw, "%s Note that version 2.1 of the specification incorrectly stated that the " + "Entry Point Length should be 0x1e when it should be 0x1f.", warning); + } else + fwts_passed(fw, "SMBIOS Table Entry Point Length is valid."); + } + + if (memcmp(entry.anchor_string, "_DMI_", 5) != 0) { + fwts_failed(fw, LOG_LEVEL_HIGH, + "SMBIOSBadIntermediateAnchor", + "SMBIOS Table Entry Intermediate Anchor String was '%5.5s' and should be '_DMI_'.", + entry.anchor_string); + fwts_advice(fw, "%s", warning); + } else + fwts_passed(fw, "SMBIOS Table Entry Intermediate Anchor String _DMI_ is valid."); + + /* Intermediate checksum for legacy DMI */ + checksum = fwts_checksum(((uint8_t*)&entry)+16, 15); + if (checksum != 0) + fwts_failed(fw, LOG_LEVEL_HIGH, + "SMBIOSBadChecksum", + "SMBIOS Table Entry Point Intermediate Checksum is 0x%2.2x, should be 0x%2.2x", + entry.intermediate_checksum, + (uint8_t)(entry.intermediate_checksum - checksum)); + else + fwts_passed(fw, "SMBIOS Table Entry Point Intermediate Checksum is valid."); + + if ((entry.struct_table_length > 0) && (entry.struct_table_address == 0)) { + fwts_failed(fw, LOG_LEVEL_HIGH, + "SMBIOSBadTableAddress", + "SMBIOS Table Entry Structure Table Address is NULL and should be defined."); + fwts_advice(fw, + "The address of the SMBIOS Structure Tables must be defined if the " + "length of these tables is defined."); + } else { + /* + * Now does the DMI table look sane? If not, + * the SMBIOS Structure Table could be bad + */ + if (dmi_sane(fw, &entry) == FWTS_OK) + fwts_passed(fw, "SMBIOS Table Entry Structure Table Address and Length looks valid."); + } + + return FWTS_OK; +} + static bool dmi_used_by_kernel(uint8_t type, uint8_t offset) { int i; @@ -1247,7 +1434,7 @@ static void dmi_scan_tables(fwts_framework *fw, struct_count, i); } -static int dmi_decode_test1(fwts_framework *fw) +static int dmi_decode_test2(fwts_framework *fw) { void *addr; fwts_smbios_entry entry; @@ -1290,7 +1477,8 @@ static int dmi_decode_test1(fwts_framework *fw) } static fwts_framework_minor_test dmi_decode_tests[] = { - { dmi_decode_test1, "Test DMI/SMBIOS tables for errors." }, + { dmi_decode_test1, "Find and Check SMBIOS Table Entry Point." }, + { dmi_decode_test2, "Test DMI/SMBIOS tables for errors." }, { NULL, NULL } };