mirror of https://github.com/acidanthera/audk.git
DynamicTablesPkg: Add SSDT Serial port for SPCR
According to Arm Server Base Boot Requirements, Platform Design Document version 1.2 revision D, September 2, 2019, section '4.2.1.8 SPCR'; the SPCR console device must be included in the DSDT. The SSDT Serial port fixup library provides interfaces to generate a SSDT Serial port table based on the serial port information. Update the SPCR Generator to use the SSDT serial port fixup library to build a serial port definition block corresponding to the SPCR serial port and install the SSDT table. Signed-off-by: Pierre Gondois <pierre.gondois@arm.com> Signed-off-by: Sami Mujawar <sami.mujawar@arm.com> Reviewed-by: Alexei Fedorov <Alexei.Fedorov@arm.com>
This commit is contained in:
parent
5b035defa8
commit
c76028a6ff
|
@ -1,7 +1,7 @@
|
||||||
## @file
|
## @file
|
||||||
# SPCR Table Generator
|
# SPCR Table Generator
|
||||||
#
|
#
|
||||||
# Copyright (c) 2017 - 2018, ARM Limited. All rights reserved.
|
# Copyright (c) 2017 - 2020, Arm Limited. All rights reserved.<BR>
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
##
|
##
|
||||||
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
[LibraryClasses]
|
[LibraryClasses]
|
||||||
BaseLib
|
BaseLib
|
||||||
|
SsdtSerialPortFixupLib
|
||||||
|
|
||||||
[Pcd]
|
[Pcd]
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
/** @file
|
/** @file
|
||||||
SPCR Table Generator
|
SPCR Table Generator
|
||||||
|
|
||||||
Copyright (c) 2017 - 2020, ARM Limited. All rights reserved.
|
Copyright (c) 2017 - 2020, Arm Limited. All rights reserved.<BR>
|
||||||
|
|
||||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
@par Reference(s):
|
@par Reference(s):
|
||||||
|
@ -14,12 +15,14 @@
|
||||||
#include <IndustryStandard/SerialPortConsoleRedirectionTable.h>
|
#include <IndustryStandard/SerialPortConsoleRedirectionTable.h>
|
||||||
#include <Library/AcpiLib.h>
|
#include <Library/AcpiLib.h>
|
||||||
#include <Library/DebugLib.h>
|
#include <Library/DebugLib.h>
|
||||||
|
#include <Library/MemoryAllocationLib.h>
|
||||||
#include <Protocol/AcpiTable.h>
|
#include <Protocol/AcpiTable.h>
|
||||||
|
|
||||||
// Module specific include files.
|
// Module specific include files.
|
||||||
#include <AcpiTableGenerator.h>
|
#include <AcpiTableGenerator.h>
|
||||||
#include <ConfigurationManagerObject.h>
|
#include <ConfigurationManagerObject.h>
|
||||||
#include <ConfigurationManagerHelper.h>
|
#include <ConfigurationManagerHelper.h>
|
||||||
|
#include <Library/SsdtSerialPortFixupLib.h>
|
||||||
#include <Library/TableHelperLib.h>
|
#include <Library/TableHelperLib.h>
|
||||||
#include <Protocol/ConfigurationManagerProtocol.h>
|
#include <Protocol/ConfigurationManagerProtocol.h>
|
||||||
|
|
||||||
|
@ -40,6 +43,14 @@ NOTE: This implementation ignores the possibility that the Serial settings may
|
||||||
|
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
|
|
||||||
|
/** A string representing the name of the SPCR port.
|
||||||
|
*/
|
||||||
|
#define NAME_STR_SPCR_PORT "COM1"
|
||||||
|
|
||||||
|
/** An UID representing the SPCR port.
|
||||||
|
*/
|
||||||
|
#define UID_SPCR_PORT 1
|
||||||
|
|
||||||
/** This macro defines the no flow control option.
|
/** This macro defines the no flow control option.
|
||||||
*/
|
*/
|
||||||
#define SPCR_FLOW_CONTROL_NONE 0
|
#define SPCR_FLOW_CONTROL_NONE 0
|
||||||
|
@ -92,47 +103,111 @@ GET_OBJECT_LIST (
|
||||||
CM_ARM_SERIAL_PORT_INFO
|
CM_ARM_SERIAL_PORT_INFO
|
||||||
)
|
)
|
||||||
|
|
||||||
/** Construct the SPCR ACPI table.
|
/** Free any resources allocated for constructing the tables.
|
||||||
|
|
||||||
|
@param [in] This Pointer to the ACPI table generator.
|
||||||
|
@param [in] AcpiTableInfo Pointer to the ACPI Table Info.
|
||||||
|
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
|
||||||
|
Protocol Interface.
|
||||||
|
@param [in, out] Table Pointer to an array of pointers
|
||||||
|
to ACPI Table(s).
|
||||||
|
@param [in] TableCount Number of ACPI table(s).
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The resources were freed successfully.
|
||||||
|
@retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FreeSpcrTableEx (
|
||||||
|
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,
|
||||||
|
IN OUT EFI_ACPI_DESCRIPTION_HEADER *** CONST Table,
|
||||||
|
IN CONST UINTN TableCount
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_ACPI_DESCRIPTION_HEADER ** TableList;
|
||||||
|
|
||||||
|
ASSERT (This != NULL);
|
||||||
|
ASSERT (AcpiTableInfo != NULL);
|
||||||
|
ASSERT (CfgMgrProtocol != NULL);
|
||||||
|
ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
|
||||||
|
ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
|
||||||
|
|
||||||
|
if ((Table == NULL) ||
|
||||||
|
(*Table == NULL) ||
|
||||||
|
(TableCount != 2)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "ERROR: SPCR: Invalid Table Pointer\n"));
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
TableList = *Table;
|
||||||
|
|
||||||
|
if ((TableList[1] == NULL) ||
|
||||||
|
(TableList[1]->Signature !=
|
||||||
|
EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "ERROR: SPCR: Invalid SSDT table pointer.\n"));
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only need to free the SSDT table at index 1. The SPCR table is static.
|
||||||
|
Status = FreeSsdtSerialPortTable (TableList[1]);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
// Free the table list.
|
||||||
|
FreePool (*Table);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Construct the SPCR ACPI table and its associated SSDT table.
|
||||||
|
|
||||||
This function invokes the Configuration Manager protocol interface
|
This function invokes the Configuration Manager protocol interface
|
||||||
to get the required hardware information for generating the ACPI
|
to get the required hardware information for generating the ACPI
|
||||||
table.
|
table.
|
||||||
|
|
||||||
If this function allocates any resources then they must be freed
|
If this function allocates any resources then they must be freed
|
||||||
in the FreeXXXXTableResources function.
|
in the FreeXXXXTableResourcesEx function.
|
||||||
|
|
||||||
@param [in] This Pointer to the table generator.
|
@param [in] This Pointer to the ACPI table generator.
|
||||||
@param [in] AcpiTableInfo Pointer to the ACPI Table Info.
|
@param [in] AcpiTableInfo Pointer to the ACPI table information.
|
||||||
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
|
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
|
||||||
Protocol Interface.
|
Protocol interface.
|
||||||
@param [out] Table Pointer to the constructed ACPI Table.
|
@param [out] Table Pointer to a list of generated ACPI table(s).
|
||||||
|
@param [out] TableCount Number of generated ACPI table(s).
|
||||||
|
|
||||||
@retval EFI_SUCCESS Table generated successfully.
|
@retval EFI_SUCCESS Table generated successfully.
|
||||||
@retval EFI_INVALID_PARAMETER A parameter is invalid.
|
@retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
|
||||||
@retval EFI_NOT_FOUND The required object was not found.
|
Manager is less than the Object size for
|
||||||
@retval EFI_UNSUPPORTED An unsupported baudrate was specified by the
|
the requested object.
|
||||||
Configuration Manager.
|
@retval EFI_INVALID_PARAMETER A parameter is invalid.
|
||||||
@retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
|
@retval EFI_NOT_FOUND Could not find information.
|
||||||
Manager is less than the Object size for the
|
@retval EFI_OUT_OF_RESOURCES Could not allocate memory.
|
||||||
requested object.
|
@retval EFI_UNSUPPORTED Unsupported configuration.
|
||||||
**/
|
**/
|
||||||
STATIC
|
STATIC
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
EFIAPI
|
EFIAPI
|
||||||
BuildSpcrTable (
|
BuildSpcrTableEx (
|
||||||
IN CONST ACPI_TABLE_GENERATOR * CONST This,
|
IN CONST ACPI_TABLE_GENERATOR * This,
|
||||||
IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,
|
IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,
|
||||||
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
|
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
|
||||||
OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table
|
OUT EFI_ACPI_DESCRIPTION_HEADER *** Table,
|
||||||
|
OUT UINTN * CONST TableCount
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
CM_ARM_SERIAL_PORT_INFO * SerialPortInfo;
|
CM_ARM_SERIAL_PORT_INFO * SerialPortInfo;
|
||||||
|
UINT32 SerialPortCount;
|
||||||
|
EFI_ACPI_DESCRIPTION_HEADER ** TableList;
|
||||||
|
|
||||||
ASSERT (This != NULL);
|
ASSERT (This != NULL);
|
||||||
ASSERT (AcpiTableInfo != NULL);
|
ASSERT (AcpiTableInfo != NULL);
|
||||||
ASSERT (CfgMgrProtocol != NULL);
|
ASSERT (CfgMgrProtocol != NULL);
|
||||||
ASSERT (Table != NULL);
|
ASSERT (Table != NULL);
|
||||||
|
ASSERT (TableCount != NULL);
|
||||||
ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
|
ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
|
||||||
ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
|
ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
|
||||||
|
|
||||||
|
@ -155,7 +230,7 @@ BuildSpcrTable (
|
||||||
CfgMgrProtocol,
|
CfgMgrProtocol,
|
||||||
CM_NULL_TOKEN,
|
CM_NULL_TOKEN,
|
||||||
&SerialPortInfo,
|
&SerialPortInfo,
|
||||||
NULL
|
&SerialPortCount
|
||||||
);
|
);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((
|
DEBUG ((
|
||||||
|
@ -163,44 +238,46 @@ BuildSpcrTable (
|
||||||
"ERROR: SPCR: Failed to get serial port information. Status = %r\n",
|
"ERROR: SPCR: Failed to get serial port information. Status = %r\n",
|
||||||
Status
|
Status
|
||||||
));
|
));
|
||||||
goto error_handler;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SerialPortInfo->BaseAddress == 0) {
|
if (SerialPortCount == 0) {
|
||||||
Status = EFI_INVALID_PARAMETER;
|
|
||||||
DEBUG ((
|
DEBUG ((
|
||||||
DEBUG_ERROR,
|
DEBUG_ERROR,
|
||||||
"ERROR: SPCR: Uart port base address is invalid. BaseAddress = 0x%lx\n",
|
"ERROR: SPCR: Serial port information not found. Status = %r\n",
|
||||||
SerialPortInfo->BaseAddress
|
EFI_NOT_FOUND
|
||||||
));
|
));
|
||||||
goto error_handler;
|
return EFI_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((SerialPortInfo->PortSubtype !=
|
// Validate the SerialPort info. Only one SPCR port can be described.
|
||||||
EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART) &&
|
// If platform provides description for multiple SPCR ports, use the
|
||||||
(SerialPortInfo->PortSubtype !=
|
// first SPCR port information.
|
||||||
EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X) &&
|
Status = ValidateSerialPortInfo (SerialPortInfo, 1);
|
||||||
(SerialPortInfo->PortSubtype !=
|
if (EFI_ERROR (Status)) {
|
||||||
EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART) &&
|
|
||||||
(SerialPortInfo->PortSubtype !=
|
|
||||||
EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_FULL_16550) &&
|
|
||||||
(SerialPortInfo->PortSubtype !=
|
|
||||||
EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_DCC)) {
|
|
||||||
Status = EFI_INVALID_PARAMETER;
|
|
||||||
DEBUG ((
|
DEBUG ((
|
||||||
DEBUG_ERROR,
|
DEBUG_ERROR,
|
||||||
"ERROR: SPCR: Uart port subtype is invalid. PortSubtype = 0x%x\n",
|
"ERROR: SPCR: Invalid serial port information. Status = %r\n",
|
||||||
SerialPortInfo->PortSubtype
|
Status
|
||||||
));
|
));
|
||||||
goto error_handler;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG ((DEBUG_INFO, "SPCR UART Configuration:\n"));
|
// Allocate a table to store pointers to the SPCR and SSDT tables.
|
||||||
DEBUG ((DEBUG_INFO, " UART Base = 0x%lx\n", SerialPortInfo->BaseAddress));
|
TableList = (EFI_ACPI_DESCRIPTION_HEADER**)
|
||||||
DEBUG ((DEBUG_INFO, " Clock = %d\n", SerialPortInfo->Clock));
|
AllocateZeroPool (sizeof (EFI_ACPI_DESCRIPTION_HEADER*) * 2);
|
||||||
DEBUG ((DEBUG_INFO, " Baudrate = %ld\n", SerialPortInfo->BaudRate));
|
if (TableList == NULL) {
|
||||||
DEBUG ((DEBUG_INFO, " Interrupt = %d\n", SerialPortInfo->Interrupt));
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"ERROR: SPCR: Failed to allocate memory for Table List," \
|
||||||
|
" Status = %r\n",
|
||||||
|
Status
|
||||||
|
));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build SPCR table.
|
||||||
Status = AddAcpiHeader (
|
Status = AddAcpiHeader (
|
||||||
CfgMgrProtocol,
|
CfgMgrProtocol,
|
||||||
This,
|
This,
|
||||||
|
@ -267,9 +344,35 @@ BuildSpcrTable (
|
||||||
goto error_handler;
|
goto error_handler;
|
||||||
} // switch
|
} // switch
|
||||||
|
|
||||||
*Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr;
|
TableList[0] = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr;
|
||||||
|
|
||||||
|
// Build a SSDT table describing the serial port.
|
||||||
|
Status = BuildSsdtSerialPortTable (
|
||||||
|
AcpiTableInfo,
|
||||||
|
SerialPortInfo,
|
||||||
|
NAME_STR_SPCR_PORT,
|
||||||
|
UID_SPCR_PORT,
|
||||||
|
&TableList[1]
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"ERROR: SPCR: Failed to build associated SSDT table. Status = %r\n",
|
||||||
|
Status
|
||||||
|
));
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
*TableCount = 2;
|
||||||
|
*Table = TableList;
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
|
||||||
error_handler:
|
error_handler:
|
||||||
|
if (TableList != NULL) {
|
||||||
|
FreePool (TableList);
|
||||||
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,7 +390,7 @@ ACPI_TABLE_GENERATOR SpcrGenerator = {
|
||||||
// Generator Description
|
// Generator Description
|
||||||
L"ACPI.STD.SPCR.GENERATOR",
|
L"ACPI.STD.SPCR.GENERATOR",
|
||||||
// ACPI Table Signature
|
// ACPI Table Signature
|
||||||
EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
|
EFI_ACPI_6_3_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
|
||||||
// ACPI Table Revision supported by this Generator
|
// ACPI Table Revision supported by this Generator
|
||||||
EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION,
|
EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION,
|
||||||
// Minimum supported ACPI Table Revision
|
// Minimum supported ACPI Table Revision
|
||||||
|
@ -296,16 +399,14 @@ ACPI_TABLE_GENERATOR SpcrGenerator = {
|
||||||
TABLE_GENERATOR_CREATOR_ID_ARM,
|
TABLE_GENERATOR_CREATOR_ID_ARM,
|
||||||
// Creator Revision
|
// Creator Revision
|
||||||
SPCR_GENERATOR_REVISION,
|
SPCR_GENERATOR_REVISION,
|
||||||
// Build Table function
|
// Build table function. Use the extended version instead.
|
||||||
BuildSpcrTable,
|
|
||||||
// No additional resources are allocated by the generator.
|
|
||||||
// Hence the Free Resource function is not required.
|
|
||||||
NULL,
|
NULL,
|
||||||
// Extended build function not needed
|
// Free table function. Use the extended version instead.
|
||||||
NULL,
|
NULL,
|
||||||
// Extended build function not implemented by the generator.
|
// Extended Build table function.
|
||||||
// Hence extended free resource function is not required.
|
BuildSpcrTableEx,
|
||||||
NULL
|
// Extended free function.
|
||||||
|
FreeSpcrTableEx
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Register the Generator with the ACPI Table Factory.
|
/** Register the Generator with the ACPI Table Factory.
|
||||||
|
|
Loading…
Reference in New Issue