From patchwork Tue Feb 9 23:12:56 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Stone X-Patchwork-Id: 61606 Delivered-To: patches@linaro.org Received: by 10.112.43.199 with SMTP id y7csp2323843lbl; Tue, 9 Feb 2016 15:13:24 -0800 (PST) X-Received: by 10.60.232.99 with SMTP id tn3mr31780143oec.8.1455059604821; Tue, 09 Feb 2016 15:13:24 -0800 (PST) Return-Path: Received: from mail-ob0-x229.google.com (mail-ob0-x229.google.com. [2607:f8b0:4003:c01::229]) by mx.google.com with ESMTPS id o132si193238oih.96.2016.02.09.15.13.24 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 09 Feb 2016 15:13:24 -0800 (PST) Received-SPF: pass (google.com: domain of al.stone@linaro.org designates 2607:f8b0:4003:c01::229 as permitted sender) client-ip=2607:f8b0:4003:c01::229; Authentication-Results: mx.google.com; spf=pass (google.com: domain of al.stone@linaro.org designates 2607:f8b0:4003:c01::229 as permitted sender) smtp.mailfrom=al.stone@linaro.org; dkim=pass header.i=@linaro.org Received: by mail-ob0-x229.google.com with SMTP id is5so3893313obc.0 for ; Tue, 09 Feb 2016 15:13:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ETjhrfOYTkXnpOp13NGlbAI25vHSQoLMEo/m6YJDQF4=; b=KhtWM+FDb43sx9eIlO/hx4GLWd9w8gWuf3JHtT+wo/bPUXSQtSRhQHISI4ZFPrTjBq Fyq7rrf+7IIx2v7IXw5N1QFZyjXRCPzJi+OSupLmj+3N5ph9mPk1BUuqhadmFWjEsJtv lHnVu2psdyNkeUh80jwhzac+Ndsn1iTm8YFuU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ETjhrfOYTkXnpOp13NGlbAI25vHSQoLMEo/m6YJDQF4=; b=huHI1NXORUv7HnSzrX4330UChnU1ddnft3pgTU6zLicPC+gv5A6a8IP/D798kr3zed 7Gae6vxNqKgIsKPOy8NzUHDAzyZ/MHcQG1gfw3JuosjgLtpwk/T5jclg3Aqk+RK1taqx +XrneOJ9ZyJCoaY4RrTcG4LWsDhB5hAr8y6HlOxHWeXCTXgEEPe+L3xaI10Z5uJHdx1q FTCt8LQqiYfJrOmW8ZX0oEIbrZT5jBZxnHLyO6x4iejh0W/8pbEVsk/GQHQAZGjg1koY gAuhXMw+qqbJbNQ0EwTlplCq00BfGdPefiIbd3bA0Pb6n12nxAt0Y7iBhIPoyZZF72d/ RR3w== X-Gm-Message-State: AG10YOTgk5kzViqoOKBflr5KfHyg57LOqqSfO8B/k711KFJtuGsnmzzFCUu1qMoaMmqUfLY4Qmc= X-Received: by 10.60.42.10 with SMTP id j10mr34143644oel.29.1455059604393; Tue, 09 Feb 2016 15:13:24 -0800 (PST) Return-Path: Received: from fidelio.ahs3 (c-50-134-239-249.hsd1.co.comcast.net. [50.134.239.249]) by smtp.googlemail.com with ESMTPSA id q8sm203282oep.2.2016.02.09.15.13.22 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 09 Feb 2016 15:13:22 -0800 (PST) From: Al Stone To: fwts-devel@lists.ubuntu.com Cc: linaro-acpi@lists.linaro.org, patches@linaro.org, Al Stone Subject: [PATCH v2 4/5] ACPI RSDP: flesh out the tests to check for full spec compliance. Date: Tue, 9 Feb 2016 16:12:56 -0700 Message-Id: <1455059577-7100-5-git-send-email-al.stone@linaro.org> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1455059577-7100-1-git-send-email-al.stone@linaro.org> References: <1455059577-7100-1-git-send-email-al.stone@linaro.org> Add in several more tests to the RSDP code that check for spec details that had not been checked for previously. This then allows us to tag the RSDP tests so that they will also be executed when running FWTS to check ACPI specification compliance (i.e., using the --acpicompliance parameter). Signed-off-by: Al Stone --- src/acpi/rsdp/rsdp.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 142 insertions(+), 9 deletions(-) -- 2.5.0 diff --git a/src/acpi/rsdp/rsdp.c b/src/acpi/rsdp/rsdp.c index 5bc0215..bf830f0 100644 --- a/src/acpi/rsdp/rsdp.c +++ b/src/acpi/rsdp/rsdp.c @@ -31,9 +31,28 @@ static int rsdp_init(fwts_framework *fw) fwts_log_error(fw, "Cannot read ACPI tables."); return FWTS_ERROR; } - if (table == NULL || (table && table->length == 0)) { - fwts_log_error(fw, "ACPI RSDP table does not exist, skipping test"); - return FWTS_SKIP; + if (!table) { + /* + * Really old x86 machines may not have an RSDP, but + * ia64 and arm64 are both required to be UEFI, so + * therefore must have an RSDP. + */ + if (fw->target_arch == FWTS_ARCH_X86) + return FWTS_SKIP; + else { + fwts_log_error(fw, + "ACPI RSDP is required for the " + "%s target architecture.", + fwts_arch_get_name(fw->target_arch)); + return FWTS_ERROR; + } + } + + /* We know there is an RSDP now, so do a quick sanity check */ + if (table->length == 0) { + fwts_log_error(fw, + "ACPI RSDP table has zero length"); + return FWTS_ERROR; } return FWTS_OK; } @@ -46,6 +65,18 @@ static int rsdp_test1(fwts_framework *fw) fwts_acpi_table_rsdp *rsdp = (fwts_acpi_table_rsdp *)table->data; bool passed = true; size_t i; + int value; + uint8_t *ptr; + uint8_t checksum; + + /* verify first checksum */ + checksum = fwts_checksum(table->data, 20); + if (checksum == 0) + fwts_passed(fw, "RSDP first checksum is correct"); + else + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "RSDPBadFirstChecksum", + "RSDP first checksum is incorrect: 0x%x", checksum); for (i = 0; i < 6; i++) { if (!isprint(rsdp->oem_id[i])) { @@ -53,7 +84,11 @@ static int rsdp_test1(fwts_framework *fw) break; } } - if (!passed) { + if (passed) + fwts_passed(fw, + "RSDP: oem_id contains only printable " + "characters."); + else { fwts_failed(fw, LOG_LEVEL_LOW, "RSDPBadOEMId", "RSDP: oem_id contains non-printable " @@ -64,16 +99,114 @@ static int rsdp_test1(fwts_framework *fw) "this should be fixed if possible to make the " "firmware ACPI complaint."); } - if (rsdp->revision > 2) { - passed = false; + + if (rsdp->revision <= 2) + fwts_passed(fw, + "RSDP: revision is %" PRIu8 ".", rsdp->revision); + else fwts_failed(fw, LOG_LEVEL_MEDIUM, "RSDPBadRevisionId", "RSDP: revision is %" PRIu8 ", expected " "value less than 2.", rsdp->revision); - } + /* whether RSDT or XSDT depends arch */ + if (rsdp->rsdt_address == 0 && rsdp->xsdt_address == 0) + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "RSDPNoAddressesFound", + "RSDP: either the RsdtAddress must be non-zero " + "or the XsdtAddress must be non-zero. Both " + "fields are zero."); + else + fwts_passed(fw, + "RSDP: at least one of RsdtAddress or XsdtAddress " + "is non-zero."); + + if (rsdp->rsdt_address != 0 && rsdp->xsdt_address != 0) + if ((uint64_t)rsdp->rsdt_address == rsdp->xsdt_address) { + fwts_warning(fw, + "Both RSDT and XSDT addresses are set. " + "Since they are the same address, this " + "is unambiguous to the OS."); + fwts_advice(fw, + "Set only one of the 32-bit RSDT or the " + "64-bit XSDT addresses. Recent versions " + "of the spec require that only one of " + "these be used but as a practical matter, " + "many vendors do use both. If both " + "fields must be used, make sure they at " + "least contain the same value so that " + "the OS can unambiguously determine " + "which address is the correct one."); + } else { + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "RSDPBothAddressesFound", + "RSDP: only one of RsdtAddress or " + "XsdtAddress should be non-zero. Both " + "fields are non-zero."); + } + else + fwts_passed(fw, + "RSDP: only one of RsdtAddress or XsdtAddress " + "is non-zero."); + + passed = false; + switch (fw->target_arch) { + case FWTS_ARCH_X86: + if (rsdp->rsdt_address != 0 || rsdp->xsdt_address != 0) + passed = true; + break; + + case FWTS_ARCH_ARM64: + if (rsdp->xsdt_address != 0) + passed = true; + break; + + default: + passed = true; + fwts_log_advice(fw, + "No clear rule for RSDT/XSDT address usage " + "is provided for the %s architecture.", + fwts_arch_get_name(fw->target_arch)); + } if (passed) - fwts_passed(fw, "No issues found in RSDP table."); + fwts_passed(fw, + "RSDP: the correct RSDT/XSDT address is being " + "used."); + else + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "RSDPBadAddresses", + "RSDP: the wrong RSDT/XSDT address is being " + "used for the %s architecture.", + fwts_arch_get_name(fw->target_arch)); + + /* check the length field */ + if (rsdp->length == 36) + fwts_passed(fw, "RSDP: the table is the correct length."); + else + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "RSDPBadLength", + "RSDP: length is %d bytes but should be 36.", + rsdp->length); + + /* verify the extended checksum */ + checksum = fwts_checksum(table->data, 36); + if (checksum == 0) + fwts_passed(fw, "RSDP second checksum is correct"); + else + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "RSDPBadSecondChecksum", + "RSDP second checksum incorrect: 0x%x", checksum); + + /* the reserved field should be zero */ + value = 0; + for (ptr = (uint8_t *)rsdp->reserved, i = 0; i < 3; i++) + value += *ptr++; + if (value) + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "RSDPReserved", + "RSDP: reserved field is non-zero."); + else + fwts_passed(fw, "RSDP: the reserved field is zero."); return FWTS_OK; } @@ -90,4 +223,4 @@ static fwts_framework_ops rsdp_ops = { }; FWTS_REGISTER("rsdp", &rsdp_ops, FWTS_TEST_ANYTIME, FWTS_FLAG_BATCH | - FWTS_FLAG_TEST_ACPI) + FWTS_FLAG_TEST_ACPI | FWTS_FLAG_TEST_COMPLIANCE_ACPI)