From patchwork Wed Apr 1 16:12:01 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Colin Ian King X-Patchwork-Id: 457308 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 1A2C31400B7; Thu, 2 Apr 2015 03:13:57 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.76) (envelope-from ) id 1YdLH9-000431-P9; Wed, 01 Apr 2015 16:13:55 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtp (Exim 4.76) (envelope-from ) id 1YdLH1-00041y-7k for fwts-devel@lists.ubuntu.com; Wed, 01 Apr 2015 16:13:47 +0000 Received: from cpc3-craw6-2-0-cust180.croy.cable.virginm.net ([77.100.248.181] helo=localhost) by youngberry.canonical.com with esmtpsa (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1YdLH1-0000vr-42 for fwts-devel@lists.ubuntu.com; Wed, 01 Apr 2015 16:13:47 +0000 From: Colin King To: fwts-devel@lists.ubuntu.com Subject: [PATCH 1/2] acpi: Add SPCR ACPI table check (LP: #1433604) Date: Wed, 1 Apr 2015 17:12:01 +0100 Message-Id: <1427904722-28083-2-git-send-email-colin.king@canonical.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1427904722-28083-1-git-send-email-colin.king@canonical.com> References: <1427904722-28083-1-git-send-email-colin.king@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 From: Colin Ian King Signed-off-by: Colin Ian King --- src/Makefile.am | 1 + src/acpi/spcr/spcr.c | 292 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 293 insertions(+) create mode 100644 src/acpi/spcr/spcr.c diff --git a/src/Makefile.am b/src/Makefile.am index 875b91f..62c63ef 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -51,6 +51,7 @@ fwts_SOURCES = main.c \ acpi/s3/s3.c \ acpi/s3power/s3power.c \ acpi/s4/s4.c \ + acpi/spcr/spcr.c \ acpi/syntaxcheck/syntaxcheck.c \ acpi/wakealarm/wakealarm.c \ acpi/wmi/wmi.c \ diff --git a/src/acpi/spcr/spcr.c b/src/acpi/spcr/spcr.c new file mode 100644 index 0000000..4bcbd7a --- /dev/null +++ b/src/acpi/spcr/spcr.c @@ -0,0 +1,292 @@ +/* + * Copyright (C) 2015 Canonical + * + * Portions of this code original from the Linux-ready Firmware Developer Kit + * + * 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 "fwts.h" + +#ifdef FWTS_ARCH_INTEL + +#include +#include +#include +#include +#include +#include +#include +#include + +static const fwts_acpi_table_spcr *spcr; + +static int spcr_init(fwts_framework *fw) +{ + fwts_acpi_table_info *table; + + if (fwts_acpi_find_table(fw, "SPCR", 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 SPCR table does not exist, skipping test"); + return FWTS_SKIP; + } + spcr = (const fwts_acpi_table_spcr*)table->data; + + return FWTS_OK; +} + +/* + * For SPCR and serial port types refer to: + * https://msdn.microsoft.com/en-gb/library/windows/hardware/dn639132%28v=vs.85%29.aspx + * https://msdn.microsoft.com/en-us/library/windows/hardware/dn639131%28v=vs.85%29.aspx + */ +static int spcr_test1(fwts_framework *fw) +{ + char *str; + bool reserved = false; + bool not_pci = false; + + /* Assuming revision 2 */ + switch (spcr->interface_type) { + case 0x00: + str = "16550 compatible"; + break; + case 0x01: + str = "16450 compatible"; + break; + case 0x03: + str = "ARM PL011 UART"; + break; + case 0x02: + case 0x04 ... 0x09: + str = "Reserved (Do not Use)"; + reserved = true; + break; + default: + str = "Reserved"; + reserved = true; + break; + } + + fwts_log_info_verbatum(fw, "Serial Interface: %s", str); + if (reserved) { + fwts_failed(fw, LOG_LEVEL_HIGH, + "SPCRInterfaceReserved", + "SPCR Serial interface type 0x%2.2" PRIx8 + "is a reserved interface", spcr->interface_type); + } + + if ((spcr->reserved1[0] | + spcr->reserved1[1] | + spcr->reserved1[2])) { + fwts_failed(fw, LOG_LEVEL_LOW, + "SPCRReservedNonZero", + "SPCR reserved field must be zero, got " + "0x%2.2" PRIx8 "%2.2" PRIx8 "%2.2" PRIx8 " instead", + spcr->reserved1[0], + spcr->reserved1[1], + spcr->reserved1[2]); + } + + if (spcr->interrupt_type == 0) { + fwts_failed(fw, LOG_LEVEL_HIGH, + "SPCRUnknownInterruptType", + "SPCR interrupt type field is zero, expecting support bits to be set"); + } + if (spcr->interrupt_type & 0xf0) { + fwts_failed(fw, LOG_LEVEL_HIGH, + "SPCRIllegalReservedInterruptType", + "SPCR interrupt type reserved bits are non-zero zero, got 0x%" PRIx8, + spcr->interrupt_type); + } + + /* Check PC-AT compatible UART IRQs */ + if (spcr->interrupt_type & 1) { + switch (spcr->irq) { + case 2 ... 7: + case 9 ... 12: + case 14 ... 15: + break; + default: + fwts_failed(fw, LOG_LEVEL_HIGH, + "SPCRIllegalIRQ", + "SPCR PC-AT compatible IRQ 0x%" PRIx8 " is invalid", spcr->irq); + break; + } + } + + reserved = false; + switch (spcr->baud_rate) { + case 0x03: + str = "9600"; + break; + case 0x04: + str = "19200"; + break; + case 0x06: + str = "57600"; + break; + case 0x07: + str = "115200"; + break; + default: + str = "Reserved"; + reserved = true; + } + fwts_log_info_verbatum(fw, "Baud Rate: %s", str); + if (reserved) { + fwts_failed(fw, LOG_LEVEL_HIGH, + "SPCRBaudRateReserved", + "SPCR Serial baud rate type 0x%2.2" PRIx8 + "is a reserved baud rate", spcr->baud_rate); + } + + if (spcr->parity & 0xfe) { + fwts_failed(fw, LOG_LEVEL_HIGH, + "SPCRParityReserved", + "SPCR parity reserved bits 1..7 are non-zero, value is 0x%2.2" PRIx8, + spcr->parity); + } + + if (spcr->flow_control & 0xfe) { + fwts_failed(fw, LOG_LEVEL_HIGH, + "SPCRFlowControlReserved", + "SPCR flow control reserved bits 1..7 are non-zero, value is 0x%2.2" PRIx8, + spcr->flow_control); + } + + reserved = false; + switch (spcr->terminal_type) { + case 0x00: + str = "VT100"; + break; + case 0x01: + str = "VT100+"; + break; + case 0x02: + str = "VT-UTF8"; + break; + case 0x03: + str = "ANSI"; + break; + default: + str = "Reserved"; + reserved = true; + } + fwts_log_info_verbatum(fw, "Terminal Type: %s", str); + if (reserved) { + fwts_failed(fw, LOG_LEVEL_HIGH, + "SPCRTerminalTypeReserved", + "SPCR terminal type type 0x%2.2" PRIx8 + "is a reserved terminal type", spcr->terminal_type); + } + + if (spcr->reserved2) { + fwts_failed(fw, LOG_LEVEL_LOW, + "SPCRReservedNonZero", + "SPCR reserved field must be zero, got " + "0x%2.2" PRIx8 " instead", spcr->reserved2); + } + + /* According to the spec, any of these values indicate NOT a PCI device */ + if ((spcr->pci_device_id == 0xffff) || + (spcr->pci_vendor_id == 0xffff) || + (spcr->pci_bus_number == 0) || + (spcr->pci_device_number == 0) || + (spcr->pci_function_number == 0) || + ((spcr->pci_flags & 1) == 0)) + not_pci = true; + + /* Now validate all pci specific fields if not-PCI enabled */ + if (not_pci) { + if (spcr->pci_device_id != 0xffff) { + fwts_failed(fw, LOG_LEVEL_HIGH, + "SPCRPciDeviceID", + "SPCR PCI device ID is 0x%4.4" PRIx16 + ", expecting 0xffff for non-PCI device", + spcr->pci_device_id); + } + if (spcr->pci_vendor_id != 0xffff) { + fwts_failed(fw, LOG_LEVEL_HIGH, + "SPCRPciVendorID", + "SPCR PCI vendor ID is 0x%4.4" PRIx16 + ", expecting 0xffff for non-PCI device", + spcr->pci_vendor_id); + } + if (spcr->pci_bus_number != 0x00) { + fwts_failed(fw, LOG_LEVEL_HIGH, + "SPCRPciBusNumber", + "SPCR PCI bus number is 0x%2.2" PRIx8 + ", expecting 0x00 for non-PCI device", + spcr->pci_bus_number); + } + if (spcr->pci_device_number != 0x00) { + fwts_failed(fw, LOG_LEVEL_HIGH, + "SPCRPciDeviceNumber", + "SPCR PCI device number is 0x%2.2" PRIx8 + ", expecting 0x00 for non-PCI device", + spcr->pci_device_number); + } + if (spcr->pci_function_number != 0x00) { + fwts_failed(fw, LOG_LEVEL_HIGH, + "SPCRPciFunctionNumber", + "SPCR PCI function number is 0x%2.2" PRIx8 + ", expecting 0x00 for non-PCI device", + spcr->pci_function_number); + } + if ((spcr->pci_flags & 1) != 0) { + fwts_failed(fw, LOG_LEVEL_HIGH, + "SPCRPciFlagsBit0", + "SPCR PCI flags compatibility bit 0 is %" PRIx32 + ", expecting 0 for non-PCI device", + spcr->pci_flags & 1); + } + } + + if (spcr->pci_flags & 0xfffe) { + fwts_failed(fw, LOG_LEVEL_HIGH, + "SPCRPciFlags", + "SPCR PCI flags reserved bits 1-31 are %" PRIx32 + ", expecting 0", + spcr->pci_flags); + } + + if (spcr->reserved3) { + fwts_failed(fw, LOG_LEVEL_LOW, + "SPCRReservedNonZero", + "SPCR reserved field must be zero, got " + "0x%2.2" PRIx8 " instead", spcr->reserved3); + } + + return FWTS_OK; +} + +static fwts_framework_minor_test spcr_tests[] = { + { spcr_test1, "SPCR Serial Port Console Redirection Table test." }, + { NULL, NULL } +}; + +static fwts_framework_ops spcr_ops = { + .description = "SPCR Serial Port Console Redirection Table test.", + .init = spcr_init, + .minor_tests = spcr_tests +}; + +FWTS_REGISTER("spcr", &spcr_ops, FWTS_TEST_ANYTIME, FWTS_FLAG_BATCH | FWTS_FLAG_ROOT_PRIV) + +#endif