From patchwork Fri Jan 22 01:14:19 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Stone X-Patchwork-Id: 60117 Delivered-To: patches@linaro.org Received: by 10.112.130.2 with SMTP id oa2csp336177lbb; Thu, 21 Jan 2016 17:14:54 -0800 (PST) X-Received: by 10.60.146.237 with SMTP id tf13mr246509oeb.70.1453425292384; Thu, 21 Jan 2016 17:14:52 -0800 (PST) Return-Path: Received: from mail-ob0-x231.google.com (mail-ob0-x231.google.com. [2607:f8b0:4003:c01::231]) by mx.google.com with ESMTPS id l10si3432775oeu.78.2016.01.21.17.14.52 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 21 Jan 2016 17:14:52 -0800 (PST) Received-SPF: pass (google.com: domain of al.stone@linaro.org designates 2607:f8b0:4003:c01::231 as permitted sender) client-ip=2607:f8b0:4003:c01::231; Authentication-Results: mx.google.com; spf=pass (google.com: domain of al.stone@linaro.org designates 2607:f8b0:4003:c01::231 as permitted sender) smtp.mailfrom=al.stone@linaro.org; dkim=pass header.i=@linaro.org Received: by mail-ob0-x231.google.com with SMTP id yo10so25572589obb.2 for ; Thu, 21 Jan 2016 17:14:52 -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=02aZH6ulRK9mUYibADUY2dAoZ5+ha9FMVMdeY5sxF7Y=; b=h2/QCou+X94gSjbDvioYTDTtkjoLuNTRF1dfTuWDlUDX2ePRHfTKY687IAZ8OhePrG duVRYBUu5sk69QDx6JCNDBh68OV7L0TWAvE2l2hKPU7rpeyNvzsiKhL2h5lMPQBM60/V cI1yqIq2nYGu8n2wkY0ZkJiEL18PwKNLZuQ+s= 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=02aZH6ulRK9mUYibADUY2dAoZ5+ha9FMVMdeY5sxF7Y=; b=LToxTJnG1ZmjMm/AwOGrsxVSuzHxIwMuBUrQhRXw/IiT24tS6HVCAkA1o8X46oCGsb ovfzoIz1tOjpOGHuSOcbH0+0a+EtLrUskx51JIL5Cet60pJXI1D3nIR9qxw5s6O3R+6M y9bVDCqEVc7h/dMMPS6gvZbAJqc15qtIVJYwGhGaZksUXTY19DhREdDBc7GbBCSHllQ7 vmsPxxVBuxfiWWNRC84RYAAagm0e+G+uctLKINdTDHbmuwCRUcrIUcu0ecu+MUCHARoi NAqmr6LtGOkgCiTL3040cYmElYEfnbbxgewVPsh7b0gvUi0iGS4YKVD4hSl3obC0neGI 0vuQ== X-Gm-Message-State: AG10YOR/akFbIS9xSUeS12hwYNvH6kxN114QHebs4y60SUDsHLbj20K+angorxMtt789wmqo9kE= X-Received: by 10.60.73.170 with SMTP id m10mr242169oev.51.1453425292059; Thu, 21 Jan 2016 17:14:52 -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 mj1sm1921252oeb.17.2016.01.21.17.14.50 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 21 Jan 2016 17:14:50 -0800 (PST) From: Al Stone To: fwts-devel@lists.ubuntu.com Cc: linaro-acpi@lists.linaro.org, patches@linaro.org, Al Stone Subject: [PATCH 4/5] ACPI RSDP: flesh out the tests to check for full spec compliance. Date: Thu, 21 Jan 2016 18:14:19 -0700 Message-Id: <1453425260-21576-5-git-send-email-al.stone@linaro.org> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1453425260-21576-1-git-send-email-al.stone@linaro.org> References: <1453425260-21576-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 | 132 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 123 insertions(+), 9 deletions(-) -- 2.5.0 diff --git a/src/acpi/rsdp/rsdp.c b/src/acpi/rsdp/rsdp.c index 5bc0215..0593a47 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, + "RSDPFirstChecksum", + "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,95 @@ 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, + "RSDPNoAddresses", + "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) + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "RSDPBothAddresses", + "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, + "RSDPGoodAddresses", + "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, + "RSDPSecondChecksum", + "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 +204,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)