From 9123b687480fa3e4191ab2113f53af321baa85da Mon Sep 17 00:00:00 2001 From: Sami Mujawar Date: Sat, 15 Dec 2018 12:27:03 +0000 Subject: DynamicTablesPkg: Arm SPCR Table Generator The SPCR generator uses the configuration manager protocol to obtain the serial port information from the platform configuration manager. It then updates a template SPCR table structure. This table data is used by the Table Manager to install the SPCR table. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/DynamicTables.dsc.inc | 1 + .../Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf | 42 +++ .../Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c | 347 +++++++++++++++++++++ 3 files changed, 390 insertions(+) create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/DynamicTables.dsc.inc index ad943bc55d..069ce635e5 100644 --- a/DynamicTablesPkg/DynamicTables.dsc.inc +++ b/DynamicTablesPkg/DynamicTables.dsc.inc @@ -31,6 +31,7 @@ NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf + NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf } # diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf new file mode 100644 index 0000000000..8dd94e550b --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf @@ -0,0 +1,42 @@ +## @file +# SPCR Table Generator +# +# Copyright (c) 2017 - 2018, ARM Limited. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +## + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = AcpiSpcrLibArm + FILE_GUID = 55088136-7B78-4974-B1EE-F630150D0DE7 + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_DRIVER + LIBRARY_CLASS = NULL|DXE_DRIVER + CONSTRUCTOR = AcpiSpcrLibConstructor + DESTRUCTOR = AcpiSpcrLibDestructor + +[Sources] + SpcrGenerator.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + DynamicTablesPkg/DynamicTablesPkg.dec + +[LibraryClasses] + BaseLib + +[Pcd] + +[Protocols] + +[Guids] + diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c new file mode 100644 index 0000000000..23d3a50713 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c @@ -0,0 +1,347 @@ +/** @file + SPCR Table Generator + + Copyright (c) 2017 - 2019, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - Microsoft Serial Port Console Redirection Table + Specification - Version 1.03 - August 10, 2015. + +**/ + +#include +#include +#include +#include +#include + +// Module specific include files. +#include +#include +#include +#include +#include + +/** ARM standard SPCR Table Generator + + Constructs the SPCR table for PL011 or SBSA UART peripherals. + +Requirements: + The following Configuration Manager Object(s) are required by + this Generator: + - EArmObjSerialConsolePortInfo + +NOTE: This implementation ignores the possibility that the Serial settings may + be modified from the UEFI Shell. A more complex handler would be needed + to (e.g.) recover serial port settings from the UART, or non-volatile + storage. +*/ + +#pragma pack(1) + +/** This macro defines the no flow control option. +*/ +#define SPCR_FLOW_CONTROL_NONE 0 + +/**A template for generating the SPCR Table. + + Note: fields marked "{Template}" will be updated dynamically. +*/ +STATIC +EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE AcpiSpcr = { + ACPI_HEADER ( + EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE, + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE, + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION + ), + 0, // {Template}: Serial Port Subtype + { + EFI_ACPI_RESERVED_BYTE, + EFI_ACPI_RESERVED_BYTE, + EFI_ACPI_RESERVED_BYTE + }, + ARM_GAS32 (0), // {Template}: Serial Port Base Address + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_GIC, + 0, // Not used on ARM + 0, // {Template}: Serial Port Interrupt + 0, // {Template}: Serial Port Baudrate + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_PARITY_NO_PARITY, + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_STOP_BITS_1, + SPCR_FLOW_CONTROL_NONE, + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_ANSI, + EFI_ACPI_RESERVED_BYTE, + 0xFFFF, + 0xFFFF, + 0x00, + 0x00, + 0x00, + 0x00000000, + 0x00, + EFI_ACPI_RESERVED_DWORD +}; + +#pragma pack() + +/** This macro expands to a function that retrieves the Serial + Port Information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArm, + EArmObjSerialConsolePortInfo, + CM_ARM_SERIAL_PORT_INFO + ) + +/** Construct the SPCR ACPI table. + + This function invokes the Configuration Manager protocol interface + to get the required hardware information for generating the ACPI + table. + + If this function allocates any resources then they must be freed + in the FreeXXXXTableResources function. + + @param [in] This Pointer to the table generator. + @param [in] AcpiTableInfo Pointer to the ACPI Table Info. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [out] Table Pointer to the constructed ACPI Table. + + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The required object was not found. + @retval EFI_UNSUPPORTED An unsupported baudrate was specified by the + Configuration Manager. + @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration + Manager is less than the Object size for the + requested object. +**/ +STATIC +EFI_STATUS +EFIAPI +BuildSpcrTable ( + IN CONST ACPI_TABLE_GENERATOR * CONST This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol, + OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table + ) +{ + EFI_STATUS Status; + CM_ARM_SERIAL_PORT_INFO * SerialPortInfo; + + ASSERT (This != NULL); + ASSERT (AcpiTableInfo != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (Table != NULL); + ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); + + if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) || + (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SPCR: Requested table revision = %d, is not supported." + "Supported table revision: Minimum = %d, Maximum = %d\n", + AcpiTableInfo->AcpiTableRevision, + This->MinAcpiTableRevision, + This->AcpiTableRevision + )); + return EFI_INVALID_PARAMETER; + } + + *Table = NULL; + + Status = GetEArmObjSerialConsolePortInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &SerialPortInfo, + NULL + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SPCR: Failed to get serial port information. Status = %r\n", + Status + )); + goto error_handler; + } + + if (SerialPortInfo->BaseAddress == 0) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: SPCR: Uart port base address is invalid. BaseAddress = 0x%lx\n", + SerialPortInfo->BaseAddress + )); + goto error_handler; + } + + if ((SerialPortInfo->PortSubtype != + EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART) && + (SerialPortInfo->PortSubtype != + EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X) && + (SerialPortInfo->PortSubtype != + EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART) && + (SerialPortInfo->PortSubtype != + EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_DCC)) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: SPCR: Uart port sybtype is invalid. PortSubtype = 0x%x\n", + SerialPortInfo->PortSubtype + )); + goto error_handler; + } + + DEBUG ((DEBUG_INFO, "SPCR UART Configuration:\n")); + DEBUG ((DEBUG_INFO, " UART Base = 0x%lx\n", SerialPortInfo->BaseAddress)); + DEBUG ((DEBUG_INFO, " Clock = %d\n", SerialPortInfo->Clock)); + DEBUG ((DEBUG_INFO, " Baudrate = %ld\n", SerialPortInfo->BaudRate)); + DEBUG ((DEBUG_INFO, " Interrupt = %d\n", SerialPortInfo->Interrupt)); + + Status = AddAcpiHeader ( + CfgMgrProtocol, + This, + (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr, + AcpiTableInfo->AcpiTableRevision, + sizeof (EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE) + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SPCR: Failed to add ACPI header. Status = %r\n", + Status + )); + goto error_handler; + } + + // Update the serial port subtype + AcpiSpcr.InterfaceType = SerialPortInfo->PortSubtype; + + // Update the base address + AcpiSpcr.BaseAddress.Address = SerialPortInfo->BaseAddress; + + // Update the UART interrupt + AcpiSpcr.GlobalSystemInterrupt = SerialPortInfo->Interrupt; + + switch (SerialPortInfo->BaudRate) { + case 9600: + AcpiSpcr.BaudRate = + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_9600; + break; + case 19200: + AcpiSpcr.BaudRate = + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_19200; + break; + case 57600: + AcpiSpcr.BaudRate = + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_57600; + break; + case 115200: + AcpiSpcr.BaudRate = + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_115200; + break; + default: + Status = EFI_UNSUPPORTED; + DEBUG (( + DEBUG_ERROR, + "ERROR: SPCR: Invalid Baud Rate %ld, Status = %r\n", + SerialPortInfo->BaudRate, + Status + )); + goto error_handler; + } // switch + + *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr; + +error_handler: + return Status; +} + +/** This macro defines the SPCR Table Generator revision. +*/ +#define SPCR_GENERATOR_REVISION CREATE_REVISION (1, 0) + +/** The interface for the SPCR Table Generator. +*/ +STATIC +CONST +ACPI_TABLE_GENERATOR SpcrGenerator = { + // Generator ID + CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSpcr), + // Generator Description + L"ACPI.STD.SPCR.GENERATOR", + // ACPI Table Signature + EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE, + // ACPI Table Revision supported by this Generator + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION, + // Minimum supported ACPI Table Revision + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION, + // Creator ID + TABLE_GENERATOR_CREATOR_ID_ARM, + // Creator Revision + SPCR_GENERATOR_REVISION, + // Build Table function + BuildSpcrTable, + // No additional resources are allocated by the generator. + // Hence the Free Resource function is not required. + NULL, + // Extended build function not needed + NULL, + // Extended build function not implemented by the generator. + // Hence extended free resource function is not required. + NULL +}; + +/** Register the Generator with the ACPI Table Factory. + + @param [in] ImageHandle The handle to the image. + @param [in] SystemTable Pointer to the System Table. + + @retval EFI_SUCCESS The Generator is registered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_ALREADY_STARTED The Generator for the Table ID + is already registered. +**/ +EFI_STATUS +EFIAPI +AcpiSpcrLibConstructor ( + IN CONST EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE * CONST SystemTable + ) +{ + EFI_STATUS Status; + Status = RegisterAcpiTableGenerator (&SpcrGenerator); + DEBUG ((DEBUG_INFO, "SPCR: Register Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** Deregister the Generator from the ACPI Table Factory. + + @param [in] ImageHandle The handle to the image. + @param [in] SystemTable Pointer to the System Table. + + @retval EFI_SUCCESS The Generator is deregistered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The Generator is not registered. +**/ +EFI_STATUS +EFIAPI +AcpiSpcrLibDestructor ( + IN CONST EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE * CONST SystemTable + ) +{ + EFI_STATUS Status; + Status = DeregisterAcpiTableGenerator (&SpcrGenerator); + DEBUG ((DEBUG_INFO, "SPCR: Deregister Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} -- cgit v1.2.3