From patchwork Thu Apr 21 12:34:10 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Hung X-Patchwork-Id: 613090 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 3qrJ9H3rVKz9ryQ; Thu, 21 Apr 2016 22:34:28 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.76) (envelope-from ) id 1atDoN-0007Ul-OZ; Thu, 21 Apr 2016 12:34:23 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.76) (envelope-from ) id 1atDoI-0007Ug-Ts for fwts-devel@lists.ubuntu.com; Thu, 21 Apr 2016 12:34:18 +0000 Received: from [175.181.254.82] (helo=canonical.com) by youngberry.canonical.com with esmtpsa (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1atDoI-0000oW-12; Thu, 21 Apr 2016 12:34:18 +0000 From: Alex Hung To: fwts-devel@lists.ubuntu.com Subject: [PATCH][v3] acpi: add EINJ table sanity check Date: Thu, 21 Apr 2016 20:34:10 +0800 Message-Id: <1461242050-19663-1-git-send-email-alex.hung@canonical.com> X-Mailer: git-send-email 2.5.0 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/acpi/einj/einj.c | 167 ++++++++++++++++++++++++++++++++++++++++++++ src/lib/include/fwts_acpi.h | 11 +++ 3 files changed, 179 insertions(+) create mode 100644 src/acpi/einj/einj.c diff --git a/src/Makefile.am b/src/Makefile.am index bf415fd..3369568 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -53,6 +53,7 @@ fwts_SOURCES = main.c \ acpi/dbg2/dbg2.c \ acpi/dmar/dmar.c \ acpi/ecdt/ecdt.c \ + acpi/einj/einj.c \ acpi/erst/erst.c \ acpi/facs/facs.c \ acpi/fadt/fadt.c \ diff --git a/src/acpi/einj/einj.c b/src/acpi/einj/einj.c new file mode 100644 index 0000000..4efd71a --- /dev/null +++ b/src/acpi/einj/einj.c @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2016 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. + * + */ +#include "fwts.h" +#include "fwts_acpi_object_eval.h" + +#include +#include +#include +#include +#include +#include + +static fwts_acpi_table_info *table; + +static int einj_init(fwts_framework *fw) +{ + if (fwts_acpi_find_table(fw, "EINJ", 0, &table) != FWTS_OK) { + fwts_log_error(fw, "Cannot read ACPI tables."); + return FWTS_ERROR; + } + if (table == NULL || (table && table->length == 0)) { + fwts_log_error(fw, "ACPI EINJ table does not exist, skipping test"); + return FWTS_SKIP; + } + return FWTS_OK; +} + +/* + * EINJ Error Injection Table + */ +static int einj_test1(fwts_framework *fw) +{ + fwts_acpi_table_einj *einj = (fwts_acpi_table_einj *) table->data; + fwts_acpi_serialization_instruction_entries *entry; + uint32_t reserved, i; + bool passed = true; + + reserved = einj->reserved[0] + (einj->reserved[1] << 4) + + (einj->reserved[2] << 8); + + fwts_log_info_verbatum(fw, "EINJ Error Injection Table:"); + fwts_log_info_verbatum(fw, " Injection Header Size: 0x%8.8" PRIx32, + einj->header_size); + fwts_log_info_verbatum(fw, " Injection Flags: 0x%8.8" PRIx32, + einj->flags); + fwts_log_info_verbatum(fw, " Reserved: 0x%8.8" PRIx32, + reserved); + fwts_log_info_verbatum(fw, " Injection Entry Count: 0x%8.8" PRIx32, + einj->count); + + if (einj->flags) { + fwts_failed(fw, LOG_LEVEL_LOW, + "EINJFlagNonZero", + "EINJ Injection Flags field must be zero, got 0x%" + PRIx8 " instead", einj->flags); + passed = false; + } + + if (reserved) { + fwts_failed(fw, LOG_LEVEL_LOW, + "EINJReservedNonZero", + "EINJ Reserved field must be zero, got 0x%" + PRIx32 " instead", reserved); + passed = false; + } + + fwts_log_nl(fw); + + entry = (fwts_acpi_serialization_instruction_entries *) + (char *) einj + 48; + for (i = 0; i < einj->count; i++, entry++) { + fwts_acpi_gas gas = entry->register_region; + fwts_log_info_verbatum(fw, " Injection Instruction Entry %2.2" + PRId8, i); + fwts_log_info_verbatum(fw, " Injection Action : 0x%2.2" + PRIx8, entry->serialization_action); + fwts_log_info_verbatum(fw, " Instruction : 0x%2.2" + PRIx8, entry->instruction); + fwts_log_info_verbatum(fw, " Flags : 0x%2.2" + PRIx8, entry->flags); + fwts_log_info_verbatum(fw, " Reserved : 0x%2.2" + PRIx8, entry->reserved); + fwts_log_info_verbatum(fw, " Address Space ID : 0x%2.2" + PRIx8, gas.address_space_id); + fwts_log_info_verbatum(fw, " Register Bit Width : 0x%2.2" + PRIx8, gas.register_bit_width); + fwts_log_info_verbatum(fw, " Register Bit Offset : 0x%2.2" + PRIx8, gas.register_bit_offset); + fwts_log_info_verbatum(fw, " Access Size : 0x%2.2" + PRIx8, gas.access_width); + fwts_log_info_verbatum(fw, " Address : 0x%16.16" + PRIx64, gas.address); + fwts_log_info_verbatum(fw, " Value : 0x%16.16" + PRIx64, entry->value); + fwts_log_info_verbatum(fw, " Mask : 0x%16.16" + PRIx64, entry->mask); + + if (entry->serialization_action > 0x8 && + entry->serialization_action != 0xFF) { + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "EINJBadInjectionAction", + "EINJ Injection Action must be within 0~8 " + "or 0xFF got 0x%" PRIx8 " instead", + entry->serialization_action); + passed = false; + } + + if (entry->instruction > 0x4) { + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "EINJBadInstruction", + "EINJ Instruction must be within 0~4, got " + "0x%" PRIx8 " instead", entry->instruction); + passed = false; + } + + if (entry->reserved != 0) { + fwts_failed(fw, LOG_LEVEL_LOW, + "EINJReservedNonZero", + "EINJ Reserved field must be zero, got 0x%" + PRIx32 " instead", entry->reserved); + passed = false; + } + + if (gas.address_space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY && + gas.address_space_id != ACPI_ADR_SPACE_SYSTEM_IO) { + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "EINJBadSpaceId", + "EINJ Address_Space_ID must be within 0 or " + "1, got 0x%" PRIx8 " instead", + gas.address_space_id); + passed = false; + } + + fwts_log_nl(fw); + } + + if (passed) + fwts_passed(fw, "No issues found in EINJ table."); + + return FWTS_OK; +} + +static fwts_framework_minor_test einj_tests[] = { + { einj_test1, "EINJ Error Injection Table test." }, + { NULL, NULL } +}; + +static fwts_framework_ops einj_ops = { + .description = "EINJ Error Injection Table test.", + .init = einj_init, + .minor_tests = einj_tests +}; + +FWTS_REGISTER("einj", &einj_ops, FWTS_TEST_ANYTIME, FWTS_FLAG_BATCH | + FWTS_FLAG_TEST_ACPI) diff --git a/src/lib/include/fwts_acpi.h b/src/lib/include/fwts_acpi.h index 666b6cd..8b50517 100644 --- a/src/lib/include/fwts_acpi.h +++ b/src/lib/include/fwts_acpi.h @@ -445,6 +445,17 @@ typedef struct { fwts_acpi_serialization_instruction_entries entries[0]; } __attribute__ ((packed)) fwts_acpi_table_erst; +/* + * ACPI EINJ (Error Injection Table), 18.6 + */ +typedef struct { + fwts_acpi_table_header header; + uint32_t header_size; + uint8_t flags; + uint8_t reserved[3]; + uint32_t count; + fwts_acpi_serialization_instruction_entries entries[0]; +} __attribute__ ((packed)) fwts_acpi_table_einj; /* * ACPI MADT (Multiple APIC Description Table), 5.2.12