--- /dev/null
+/** @file\r
+ DBG2 Table Generator\r
+\r
+ Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+ @par Reference(s):\r
+ - Microsoft Debug Port Table 2 (DBG2) Specification - December 10, 2015.\r
+\r
+**/\r
+\r
+#include <IndustryStandard/DebugPort2Table.h>\r
+#include <Library/AcpiLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PL011UartLib.h>\r
+#include <Protocol/AcpiTable.h>\r
+#include <Protocol/SerialIo.h>\r
+\r
+// Module specific include files.\r
+#include <AcpiTableGenerator.h>\r
+#include <ConfigurationManagerObject.h>\r
+#include <ConfigurationManagerHelper.h>\r
+#include <Library/TableHelperLib.h>\r
+#include <Protocol/ConfigurationManagerProtocol.h>\r
+\r
+/** ARM standard DBG2 Table Generator\r
+\r
+ Constructs the DBG2 table for PL011 or SBSA UART peripherals.\r
+\r
+Requirements:\r
+ The following Configuration Manager Object(s) are required by\r
+ this Generator:\r
+ - EArmObjSerialDebugPortInfo\r
+*/\r
+\r
+#pragma pack(1)\r
+\r
+/** The number of debug ports represented by the Table.\r
+*/\r
+#define DBG2_NUM_DEBUG_PORTS 1\r
+\r
+/** The number of Generic Address Registers\r
+ presented in the debug device information.\r
+*/\r
+#define DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS 1\r
+\r
+/** The index for the debug port 1 in the Debug port information list.\r
+*/\r
+#define DBG_PORT_INDEX_PORT1 0\r
+\r
+/** A string representing the name of the debug port 1.\r
+*/\r
+#define NAME_STR_PORT1 "COM1"\r
+\r
+/** The length of the namespace string.\r
+*/\r
+#define DBG2_NAMESPACESTRING_FIELD_SIZE sizeof (NAME_STR_PORT1)\r
+\r
+/** The PL011 UART address range length.\r
+*/\r
+#define PL011_UART_LENGTH 0x1000\r
+\r
+/** A structure that provides the OS with the required information\r
+ for initializing a debugger connection.\r
+*/\r
+typedef struct {\r
+ /// The debug device information for the platform\r
+ EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT Dbg2Device;\r
+\r
+ /// The base address register for the serial port\r
+ EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister;\r
+\r
+ /// The address size\r
+ UINT32 AddressSize;\r
+\r
+ /// The debug port name string\r
+ UINT8 NameSpaceString[DBG2_NAMESPACESTRING_FIELD_SIZE];\r
+} DBG2_DEBUG_DEVICE_INFORMATION;\r
+\r
+/** A structure representing the information about the debug port(s)\r
+ available on the platform.\r
+*/\r
+typedef struct {\r
+ /// The DBG2 table header\r
+ EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE Description;\r
+\r
+ /// Debug port information list\r
+ DBG2_DEBUG_DEVICE_INFORMATION Dbg2DeviceInfo[DBG2_NUM_DEBUG_PORTS];\r
+} DBG2_TABLE;\r
+\r
+/** A helper macro used for initializing the debug port device\r
+ information structure.\r
+\r
+ @param [in] NumReg The number of generic address registers.\r
+ @param [in] SubType The DBG Port SubType.\r
+ @param [in] UartBase The UART port base address.\r
+ @param [in] UartAddrLen The UART port address range length.\r
+ @param [in] UartNameStr The UART port name string.\r
+**/\r
+#define DBG2_DEBUG_PORT_DDI( \\r
+ NumReg, \\r
+ SubType, \\r
+ UartBase, \\r
+ UartAddrLen, \\r
+ UartNameStr \\r
+ ) { \\r
+ { \\r
+ /* UINT8 Revision */ \\r
+ EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION, \\r
+ /* UINT16 Length */ \\r
+ sizeof (DBG2_DEBUG_DEVICE_INFORMATION), \\r
+ /* UINT8 NumberofGenericAddressRegisters */ \\r
+ NumReg, \\r
+ /* UINT16 NameSpaceStringLength */ \\r
+ DBG2_NAMESPACESTRING_FIELD_SIZE, \\r
+ /* UINT16 NameSpaceStringOffset */ \\r
+ OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, NameSpaceString), \\r
+ /* UINT16 OemDataLength */ \\r
+ 0, \\r
+ /* UINT16 OemDataOffset */ \\r
+ 0, \\r
+ /* UINT16 Port Type */ \\r
+ EFI_ACPI_DBG2_PORT_TYPE_SERIAL, \\r
+ /* UINT16 Port Subtype */ \\r
+ SubType, \\r
+ /* UINT8 Reserved[2] */ \\r
+ {EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE}, \\r
+ /* UINT16 BaseAddressRegister Offset */ \\r
+ OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, BaseAddressRegister), \\r
+ /* UINT16 AddressSize Offset */ \\r
+ OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, AddressSize) \\r
+ }, \\r
+ /* EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister */ \\r
+ ARM_GAS32 (UartBase), \\r
+ /* UINT32 AddressSize */ \\r
+ UartAddrLen, \\r
+ /* UINT8 NameSpaceString[MAX_DBG2_NAME_LEN] */ \\r
+ UartNameStr \\r
+ }\r
+\r
+/** The DBG2 Table template definition.\r
+\r
+ Note: fields marked with "{Template}" will be set dynamically\r
+*/\r
+STATIC\r
+DBG2_TABLE AcpiDbg2 = {\r
+ {\r
+ ACPI_HEADER (\r
+ EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE,\r
+ DBG2_TABLE,\r
+ EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION\r
+ ),\r
+ OFFSET_OF (DBG2_TABLE, Dbg2DeviceInfo),\r
+ DBG2_NUM_DEBUG_PORTS\r
+ },\r
+ {\r
+ /*\r
+ * Debug port 1\r
+ */\r
+ DBG2_DEBUG_PORT_DDI (\r
+ DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS,\r
+ 0, // {Template}: Serial Port Subtype\r
+ 0, // {Template}: Serial Port Base Address\r
+ PL011_UART_LENGTH,\r
+ NAME_STR_PORT1\r
+ )\r
+ }\r
+};\r
+\r
+#pragma pack()\r
+\r
+/** This macro expands to a function that retrieves the Serial\r
+ debug port information from the Configuration Manager\r
+*/\r
+GET_OBJECT_LIST (\r
+ EObjNameSpaceArm,\r
+ EArmObjSerialDebugPortInfo,\r
+ CM_ARM_SERIAL_PORT_INFO\r
+ );\r
+\r
+/** Initialize the PL011 UART with the parameters obtained from\r
+ the Configuration Manager.\r
+\r
+ @param [in] SerialPortInfo Pointer to the Serial Port Information.\r
+\r
+ @retval EFI_SUCCESS Success.\r
+ @retval EFI_INVALID_PARAMETER The parameters for serial port initialization\r
+ are invalid.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+SetupDebugUart (\r
+ IN CONST CM_ARM_SERIAL_PORT_INFO * CONST SerialPortInfo\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT64 BaudRate;\r
+ UINT32 ReceiveFifoDepth;\r
+ EFI_PARITY_TYPE Parity;\r
+ UINT8 DataBits;\r
+ EFI_STOP_BITS_TYPE StopBits;\r
+\r
+ ASSERT (SerialPortInfo != NULL);\r
+\r
+ // Initialize the Serial Debug UART\r
+ DEBUG ((DEBUG_INFO, "Initializing Serial Debug UART...\n"));\r
+ ReceiveFifoDepth = 0; // Use the default value for FIFO depth\r
+ Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);\r
+ DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);\r
+ StopBits = (EFI_STOP_BITS_TYPE)FixedPcdGet8 (PcdUartDefaultStopBits);\r
+\r
+ BaudRate = SerialPortInfo->BaudRate;\r
+ Status = PL011UartInitializePort (\r
+ (UINTN)SerialPortInfo->BaseAddress,\r
+ SerialPortInfo->Clock,\r
+ &BaudRate,\r
+ &ReceiveFifoDepth,\r
+ &Parity,\r
+ &DataBits,\r
+ &StopBits\r
+ );\r
+\r
+ DEBUG ((DEBUG_INFO, "Debug UART Configuration:\n"));\r
+ DEBUG ((DEBUG_INFO, "UART Base = 0x%lx\n", SerialPortInfo->BaseAddress));\r
+ DEBUG ((DEBUG_INFO, "Clock = %d\n", SerialPortInfo->Clock));\r
+ DEBUG ((DEBUG_INFO, "Baudrate = %ld\n", BaudRate));\r
+ DEBUG ((DEBUG_INFO, "Configuring Debug UART. Status = %r\n", Status));\r
+\r
+ ASSERT_EFI_ERROR (Status);\r
+ return Status;\r
+}\r
+\r
+/** Construct the DBG2 ACPI table\r
+\r
+ The BuildDbg2Table function is called by the Dynamic Table Manager\r
+ to construct the DBG2 ACPI table.\r
+\r
+ This function invokes the Configuration Manager protocol interface\r
+ to get the required hardware information for generating the ACPI\r
+ table.\r
+\r
+ If this function allocates any resources then they must be freed\r
+ in the FreeXXXXTableResources function.\r
+\r
+ @param [in] This Pointer to the table generator.\r
+ @param [in] AcpiTableInfo Pointer to the ACPI Table Info.\r
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
+ Protocol Interface.\r
+ @param [out] Table Pointer to the constructed ACPI Table.\r
+\r
+ @retval EFI_SUCCESS Table generated successfully.\r
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
+ @retval EFI_NOT_FOUND The required object was not found.\r
+ @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration\r
+ Manager is less than the Object size for the\r
+ requested object.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+BuildDbg2Table (\r
+ IN CONST ACPI_TABLE_GENERATOR * CONST This,\r
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,\r
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
+ OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CM_ARM_SERIAL_PORT_INFO * SerialPortInfo;\r
+\r
+ ASSERT (This != NULL);\r
+ ASSERT (AcpiTableInfo != NULL);\r
+ ASSERT (CfgMgrProtocol != NULL);\r
+ ASSERT (Table != NULL);\r
+ ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
+ ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
+\r
+ if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||\r
+ (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: DBG2: Requested table revision = %d, is not supported."\r
+ "Supported table revision: Minimum = %d, Maximum = %d\n",\r
+ AcpiTableInfo->AcpiTableRevision,\r
+ This->MinAcpiTableRevision,\r
+ This->AcpiTableRevision\r
+ ));\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *Table = NULL;\r
+\r
+ Status = GetEArmObjSerialDebugPortInfo (\r
+ CfgMgrProtocol,\r
+ CM_NULL_TOKEN,\r
+ &SerialPortInfo,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: DBG2: Failed to get serial port information. Status = %r\n",\r
+ Status\r
+ ));\r
+ goto error_handler;\r
+ }\r
+\r
+ if (SerialPortInfo->BaseAddress == 0) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: DBG2: Uart port base address is invalid. BaseAddress = 0x%lx\n",\r
+ SerialPortInfo->BaseAddress\r
+ ));\r
+ goto error_handler;\r
+ }\r
+\r
+ if ((SerialPortInfo->PortSubtype !=\r
+ EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART) &&\r
+ (SerialPortInfo->PortSubtype !=\r
+ EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X) &&\r
+ (SerialPortInfo->PortSubtype !=\r
+ EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART) &&\r
+ (SerialPortInfo->PortSubtype !=\r
+ EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_DCC)) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: DBG2: Uart port sybtype is invalid. PortSubtype = 0x%x\n",\r
+ SerialPortInfo->PortSubtype\r
+ ));\r
+ goto error_handler;\r
+ }\r
+\r
+ Status = AddAcpiHeader (\r
+ CfgMgrProtocol,\r
+ This,\r
+ (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiDbg2,\r
+ AcpiTableInfo->AcpiTableRevision,\r
+ sizeof (DBG2_TABLE)\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: DBG2: Failed to add ACPI header. Status = %r\n",\r
+ Status\r
+ ));\r
+ goto error_handler;\r
+ }\r
+\r
+ // Update the base address\r
+ AcpiDbg2.Dbg2DeviceInfo[DBG_PORT_INDEX_PORT1].BaseAddressRegister.Address =\r
+ SerialPortInfo->BaseAddress;\r
+\r
+ // Update the serial port subtype\r
+ AcpiDbg2.Dbg2DeviceInfo[DBG_PORT_INDEX_PORT1].Dbg2Device.PortSubtype =\r
+ SerialPortInfo->PortSubtype;\r
+\r
+ // Initialize the serial port\r
+ Status = SetupDebugUart (SerialPortInfo);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: DBG2: Failed to configure debug serial port. Status = %r\n",\r
+ Status\r
+ ));\r
+ goto error_handler;\r
+ }\r
+\r
+ *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiDbg2;\r
+\r
+error_handler:\r
+ return Status;\r
+}\r
+\r
+/** This macro defines the DBG2 Table Generator revision.\r
+*/\r
+#define DBG2_GENERATOR_REVISION CREATE_REVISION (1, 0)\r
+\r
+/** The interface for the DBG2 Table Generator.\r
+*/\r
+STATIC\r
+CONST\r
+ACPI_TABLE_GENERATOR Dbg2Generator = {\r
+ // Generator ID\r
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdDbg2),\r
+ // Generator Description\r
+ L"ACPI.STD.DBG2.GENERATOR",\r
+ // ACPI Table Signature\r
+ EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE,\r
+ // ACPI Table Revision supported by this Generator\r
+ EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION,\r
+ // Minimum supported ACPI Table Revision\r
+ EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION,\r
+ // Creator ID\r
+ TABLE_GENERATOR_CREATOR_ID_ARM,\r
+ // Creator Revision\r
+ DBG2_GENERATOR_REVISION,\r
+ // Build Table function\r
+ BuildDbg2Table,\r
+ // No additional resources are allocated by the generator.\r
+ // Hence the Free Resource function is not required.\r
+ NULL,\r
+ // Extended build function not needed\r
+ NULL,\r
+ // Extended build function not implemented by the generator.\r
+ // Hence extended free resource function is not required.\r
+ NULL\r
+};\r
+\r
+/** Register the Generator with the ACPI Table Factory.\r
+\r
+ @param [in] ImageHandle The handle to the image.\r
+ @param [in] SystemTable Pointer to the System Table.\r
+\r
+ @retval EFI_SUCCESS The Generator is registered.\r
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
+ @retval EFI_ALREADY_STARTED The Generator for the Table ID\r
+ is already registered.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AcpiDbg2LibConstructor (\r
+ IN CONST EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE * CONST SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ Status = RegisterAcpiTableGenerator (&Dbg2Generator);\r
+ DEBUG ((DEBUG_INFO, "DBG2: Register Generator. Status = %r\n", Status));\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
+\r
+/** Deregister the Generator from the ACPI Table Factory.\r
+\r
+ @param [in] ImageHandle The handle to the image.\r
+ @param [in] SystemTable Pointer to the System Table.\r
+\r
+ @retval EFI_SUCCESS The Generator is deregistered.\r
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
+ @retval EFI_NOT_FOUND The Generator is not registered.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AcpiDbg2LibDestructor (\r
+ IN CONST EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE * CONST SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ Status = DeregisterAcpiTableGenerator (&Dbg2Generator);\r
+ DEBUG ((DEBUG_INFO, "DBG2: Deregister Generator. Status = %r\n", Status));\r
+ ASSERT_EFI_ERROR (Status);\r
+ return Status;\r
+}\r