|
@@ -0,0 +1,524 @@
|
|
|
+/** @file
|
|
|
+ SSDT Serial Port Fixup Library.
|
|
|
+
|
|
|
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
|
|
|
+
|
|
|
+ SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
+
|
|
|
+ @par Reference(s):
|
|
|
+ - Arm Server Base Boot Requirements (SBBR), s4.2.1.8 "SPCR".
|
|
|
+ - Microsoft Debug Port Table 2 (DBG2) Specification - December 10, 2015.
|
|
|
+**/
|
|
|
+
|
|
|
+#include <IndustryStandard/DebugPort2Table.h>
|
|
|
+#include <Library/AcpiLib.h>
|
|
|
+#include <Library/BaseLib.h>
|
|
|
+#include <Library/BaseMemoryLib.h>
|
|
|
+#include <Library/DebugLib.h>
|
|
|
+#include <Library/MemoryAllocationLib.h>
|
|
|
+#include <Library/UefiBootServicesTableLib.h>
|
|
|
+#include <Protocol/AcpiTable.h>
|
|
|
+
|
|
|
+// Module specific include files.
|
|
|
+#include <AcpiTableGenerator.h>
|
|
|
+#include <ConfigurationManagerObject.h>
|
|
|
+#include <ConfigurationManagerHelper.h>
|
|
|
+#include <Library/AmlLib/AmlLib.h>
|
|
|
+#include <Library/TableHelperLib.h>
|
|
|
+#include <Protocol/ConfigurationManagerProtocol.h>
|
|
|
+
|
|
|
+/** C array containing the compiled AML template.
|
|
|
+ This symbol is defined in the auto generated C file
|
|
|
+ containing the AML bytecode array.
|
|
|
+*/
|
|
|
+extern CHAR8 ssdtserialporttemplate_aml_code[];
|
|
|
+
|
|
|
+/** UART address range length.
|
|
|
+*/
|
|
|
+#define MIN_UART_ADDRESS_LENGTH 0x1000U
|
|
|
+
|
|
|
+/** Validate the Serial Port Information.
|
|
|
+
|
|
|
+ @param [in] SerialPortInfoTable Table of CM_ARM_SERIAL_PORT_INFO.
|
|
|
+ @param [in] SerialPortCount Count of SerialPort in the table.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS Success.
|
|
|
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+ValidateSerialPortInfo (
|
|
|
+ IN CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfoTable,
|
|
|
+ IN UINT32 SerialPortCount
|
|
|
+ )
|
|
|
+{
|
|
|
+ UINT32 Index;
|
|
|
+ CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfo;
|
|
|
+
|
|
|
+ if ((SerialPortInfoTable == NULL) ||
|
|
|
+ (SerialPortCount == 0)) {
|
|
|
+ ASSERT (0);
|
|
|
+ return EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (Index = 0; Index < SerialPortCount; Index++) {
|
|
|
+ SerialPortInfo = &SerialPortInfoTable[Index];
|
|
|
+ ASSERT (SerialPortInfo != NULL);
|
|
|
+
|
|
|
+ if ((SerialPortInfo == NULL ) ||
|
|
|
+ (SerialPortInfo->BaseAddress == 0)) {
|
|
|
+ DEBUG ((
|
|
|
+ DEBUG_ERROR,
|
|
|
+ "ERROR: UART port base address is invalid. BaseAddress = 0x%llx\n",
|
|
|
+ SerialPortInfo->BaseAddress
|
|
|
+ ));
|
|
|
+ return EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+
|
|
|
+ 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) &&
|
|
|
+ (SerialPortInfo->PortSubtype !=
|
|
|
+ EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_FULL_16550)) {
|
|
|
+ DEBUG ((
|
|
|
+ DEBUG_ERROR,
|
|
|
+ "ERROR: UART port subtype is invalid."
|
|
|
+ " UART Base = 0x%llx, PortSubtype = 0x%x\n",
|
|
|
+ SerialPortInfo->BaseAddress,
|
|
|
+ SerialPortInfo->PortSubtype
|
|
|
+ ));
|
|
|
+ return EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+
|
|
|
+ DEBUG ((DEBUG_INFO, "UART Configuration:\n"));
|
|
|
+ DEBUG ((
|
|
|
+ DEBUG_INFO,
|
|
|
+ " UART Base = 0x%llx\n", SerialPortInfo->BaseAddress
|
|
|
+ ));
|
|
|
+ DEBUG ((
|
|
|
+ DEBUG_INFO,
|
|
|
+ " Length = 0x%llx\n",
|
|
|
+ SerialPortInfo->BaseAddressLength
|
|
|
+ ));
|
|
|
+ DEBUG ((DEBUG_INFO, " Clock = %lu\n", SerialPortInfo->Clock));
|
|
|
+ DEBUG ((DEBUG_INFO, " BaudRate = %llu\n", SerialPortInfo->BaudRate));
|
|
|
+ DEBUG ((DEBUG_INFO, " Interrupt = %lu\n", SerialPortInfo->Interrupt));
|
|
|
+ } // for
|
|
|
+
|
|
|
+ return EFI_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+/** Fixup the Serial Port Ids (_UID, _HID, _CID).
|
|
|
+
|
|
|
+ @param [in] RootNodeHandle Pointer to the root of an AML tree.
|
|
|
+ @param [in] Uid UID for the Serial Port.
|
|
|
+ @param [in] SerialPortInfo Pointer to a Serial Port Information
|
|
|
+ structure.
|
|
|
+ Get the Serial Port Information from there.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS The function completed successfully.
|
|
|
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
|
|
|
+ @retval EFI_NOT_FOUND Could not find information.
|
|
|
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
|
|
|
+**/
|
|
|
+STATIC
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+FixupIds (
|
|
|
+ IN OUT AML_ROOT_NODE_HANDLE RootNodeHandle,
|
|
|
+ IN CONST UINT64 Uid,
|
|
|
+ IN CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfo
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+ AML_OBJECT_NODE_HANDLE NameOpIdNode;
|
|
|
+ CONST CHAR8 * HidString;
|
|
|
+ CONST CHAR8 * CidString;
|
|
|
+
|
|
|
+ // Get the _CID and _HID value to write.
|
|
|
+ switch (SerialPortInfo->PortSubtype) {
|
|
|
+ case EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_FULL_16550:
|
|
|
+ {
|
|
|
+ HidString = "PNP0501";
|
|
|
+ CidString = "PNP0500";
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART:
|
|
|
+ {
|
|
|
+ HidString = "ARMH0011";
|
|
|
+ CidString = "ARMHB000";
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART:
|
|
|
+ case EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X:
|
|
|
+ {
|
|
|
+ HidString = "ARMH0011";
|
|
|
+ CidString = "";
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ {
|
|
|
+ return EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+ } // switch
|
|
|
+
|
|
|
+ // Get the _UID NameOp object defined by the "Name ()" statement,
|
|
|
+ // and update its value.
|
|
|
+ Status = AmlFindNode (
|
|
|
+ RootNodeHandle,
|
|
|
+ "\\_SB_.COM0._UID",
|
|
|
+ &NameOpIdNode
|
|
|
+ );
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ Status = AmlNameOpUpdateInteger (NameOpIdNode, (UINT64)Uid);
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get the _HID NameOp object defined by the "Name ()" statement,
|
|
|
+ // and update its value.
|
|
|
+ Status = AmlFindNode (
|
|
|
+ RootNodeHandle,
|
|
|
+ "\\_SB_.COM0._HID",
|
|
|
+ &NameOpIdNode
|
|
|
+ );
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ Status = AmlNameOpUpdateString (NameOpIdNode, HidString);
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get the _CID NameOp object defined by the "Name ()" statement,
|
|
|
+ // and update its value.
|
|
|
+ Status = AmlFindNode (
|
|
|
+ RootNodeHandle,
|
|
|
+ "\\_SB_.COM0._CID",
|
|
|
+ &NameOpIdNode
|
|
|
+ );
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ // If we have a CID then update a _CID node else delete the node.
|
|
|
+ if (AsciiStrLen (CidString) != 0) {
|
|
|
+ Status = AmlNameOpUpdateString (NameOpIdNode, CidString);
|
|
|
+ } else {
|
|
|
+ // First detach the node from the tree.
|
|
|
+ Status = AmlDetachNode (NameOpIdNode);
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Delete the detached node.
|
|
|
+ Status = AmlDeleteTree (NameOpIdNode);
|
|
|
+ }
|
|
|
+
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+/** Fixup the Serial Port _CRS values (BaseAddress, ...).
|
|
|
+
|
|
|
+ @param [in] RootNodeHandle Pointer to the root of an AML tree.
|
|
|
+ @param [in] SerialPortInfo Pointer to a Serial Port Information
|
|
|
+ structure.
|
|
|
+ Get the Serial Port Information from there.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS The function completed successfully.
|
|
|
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
|
|
|
+ @retval EFI_NOT_FOUND Could not find information.
|
|
|
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
|
|
|
+**/
|
|
|
+STATIC
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+FixupCrs (
|
|
|
+ IN OUT AML_ROOT_NODE_HANDLE RootNodeHandle,
|
|
|
+ IN CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfo
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+ AML_OBJECT_NODE_HANDLE NameOpCrsNode;
|
|
|
+ AML_DATA_NODE_HANDLE QWordRdNode;
|
|
|
+ AML_DATA_NODE_HANDLE InterruptRdNode;
|
|
|
+
|
|
|
+ // Get the "_CRS" object defined by the "Name ()" statement.
|
|
|
+ Status = AmlFindNode (
|
|
|
+ RootNodeHandle,
|
|
|
+ "\\_SB_.COM0._CRS",
|
|
|
+ &NameOpCrsNode
|
|
|
+ );
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get the first Rd node in the "_CRS" object.
|
|
|
+ Status = AmlNameOpCrsGetFirstRdNode (NameOpCrsNode, &QWordRdNode);
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (QWordRdNode == NULL) {
|
|
|
+ return EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Update the Serial Port base address and length.
|
|
|
+ Status = AmlUpdateRdQWord (
|
|
|
+ QWordRdNode,
|
|
|
+ SerialPortInfo->BaseAddress,
|
|
|
+ ((SerialPortInfo->BaseAddressLength < MIN_UART_ADDRESS_LENGTH) ?
|
|
|
+ MIN_UART_ADDRESS_LENGTH: SerialPortInfo->BaseAddressLength)
|
|
|
+ );
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get the Interrupt node.
|
|
|
+ // It is the second Resource Data element in the NameOpCrsNode's
|
|
|
+ // variable list of arguments.
|
|
|
+ Status = AmlNameOpCrsGetNextRdNode (QWordRdNode, &InterruptRdNode);
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (InterruptRdNode == NULL) {
|
|
|
+ return EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Update the interrupt number.
|
|
|
+ return AmlUpdateRdInterrupt (InterruptRdNode, SerialPortInfo->Interrupt);
|
|
|
+}
|
|
|
+
|
|
|
+/** Fixup the Serial Port device name.
|
|
|
+
|
|
|
+ @param [in] RootNodeHandle Pointer to the root of an AML tree.
|
|
|
+ @param [in] SerialPortInfo Pointer to a Serial Port Information
|
|
|
+ structure.
|
|
|
+ Get the Serial Port Information from there.
|
|
|
+ @param [in] Name The Name to give to the Device.
|
|
|
+ Must be a NULL-terminated ASL NameString
|
|
|
+ e.g.: "DEV0", "DV15.DEV0", etc.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS The function completed successfully.
|
|
|
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
|
|
|
+ @retval EFI_NOT_FOUND Could not find information.
|
|
|
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
|
|
|
+**/
|
|
|
+STATIC
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+FixupName (
|
|
|
+ IN OUT AML_ROOT_NODE_HANDLE RootNodeHandle,
|
|
|
+ IN CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfo,
|
|
|
+ IN CONST CHAR8 * Name
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+ AML_OBJECT_NODE_HANDLE DeviceNode;
|
|
|
+
|
|
|
+ // Get the COM0 variable defined by the "Device ()" statement.
|
|
|
+ Status = AmlFindNode (RootNodeHandle, "\\_SB_.COM0", &DeviceNode);
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Update the Device's name.
|
|
|
+ return AmlDeviceOpUpdateName (DeviceNode, (CHAR8*)Name);
|
|
|
+}
|
|
|
+
|
|
|
+/** Fixup the Serial Port Information in the AML tree.
|
|
|
+
|
|
|
+ For each template value:
|
|
|
+ - find the node to update;
|
|
|
+ - update the value.
|
|
|
+
|
|
|
+ @param [in] RootNodeHandle Pointer to the root of the AML tree.
|
|
|
+ @param [in] SerialPortInfo Pointer to a Serial Port Information
|
|
|
+ structure.
|
|
|
+ Get the Serial Port Information from there.
|
|
|
+ @param [in] Name The Name to give to the Device.
|
|
|
+ Must be a NULL-terminated ASL NameString
|
|
|
+ e.g.: "DEV0", "DV15.DEV0", etc.
|
|
|
+ @param [in] Uid UID for the Serial Port.
|
|
|
+ @param [out] Table If success, contains the serialized
|
|
|
+ SSDT table.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS The function completed successfully.
|
|
|
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
|
|
|
+ @retval EFI_NOT_FOUND Could not find information.
|
|
|
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
|
|
|
+**/
|
|
|
+STATIC
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+FixupSerialPortInfo (
|
|
|
+ IN OUT AML_ROOT_NODE_HANDLE RootNodeHandle,
|
|
|
+ IN CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfo,
|
|
|
+ IN CONST CHAR8 * Name,
|
|
|
+ IN CONST UINT64 Uid,
|
|
|
+ OUT EFI_ACPI_DESCRIPTION_HEADER ** Table
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+
|
|
|
+ ASSERT (RootNodeHandle != NULL);
|
|
|
+ ASSERT (SerialPortInfo != NULL);
|
|
|
+ ASSERT (Name != NULL);
|
|
|
+ ASSERT (Table != NULL);
|
|
|
+
|
|
|
+ // Fixup the _UID, _HID and _CID values.
|
|
|
+ Status = FixupIds (RootNodeHandle, Uid, SerialPortInfo);
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Fixup the _CRS values.
|
|
|
+ Status = FixupCrs (RootNodeHandle, SerialPortInfo);
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Fixup the serial-port name.
|
|
|
+ // This MUST be done at the end, otherwise AML paths won't be valid anymore.
|
|
|
+ return FixupName (RootNodeHandle, SerialPortInfo, Name);
|
|
|
+}
|
|
|
+
|
|
|
+/** Free an SSDT table previously created by
|
|
|
+ the BuildSsdtSerialTable function.
|
|
|
+
|
|
|
+ @param [in] Table Pointer to a SSDT table allocated by
|
|
|
+ the BuildSsdtSerialTable function.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS Success.
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+FreeSsdtSerialPortTable (
|
|
|
+ IN EFI_ACPI_DESCRIPTION_HEADER * Table
|
|
|
+ )
|
|
|
+{
|
|
|
+ ASSERT (Table != NULL);
|
|
|
+ FreePool (Table);
|
|
|
+ return EFI_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+/** Build a SSDT table describing the input serial port.
|
|
|
+
|
|
|
+ The table created by this function must be freed by FreeSsdtSerialTable.
|
|
|
+
|
|
|
+ @param [in] AcpiTableInfo Pointer to the ACPI table information.
|
|
|
+ @param [in] SerialPortInfo Serial port to describe in the SSDT table.
|
|
|
+ @param [in] Name The Name to give to the Device.
|
|
|
+ Must be a NULL-terminated ASL NameString
|
|
|
+ e.g.: "DEV0", "DV15.DEV0", etc.
|
|
|
+ @param [in] Uid UID for the Serial Port.
|
|
|
+ @param [out] Table If success, pointer to the created SSDT table.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS Table generated successfully.
|
|
|
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
|
|
|
+ @retval EFI_NOT_FOUND Could not find information.
|
|
|
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+BuildSsdtSerialPortTable (
|
|
|
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * AcpiTableInfo,
|
|
|
+ IN CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfo,
|
|
|
+ IN CONST CHAR8 * Name,
|
|
|
+ IN CONST UINT64 Uid,
|
|
|
+ OUT EFI_ACPI_DESCRIPTION_HEADER ** Table
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+ EFI_STATUS Status1;
|
|
|
+ AML_ROOT_NODE_HANDLE RootNodeHandle;
|
|
|
+
|
|
|
+ ASSERT (AcpiTableInfo != NULL);
|
|
|
+ ASSERT (SerialPortInfo != NULL);
|
|
|
+ ASSERT (Name != NULL);
|
|
|
+ ASSERT (Table != NULL);
|
|
|
+
|
|
|
+ // Validate the Serial Port Info.
|
|
|
+ Status = ValidateSerialPortInfo (SerialPortInfo, 1);
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Parse the SSDT Serial Port Template.
|
|
|
+ Status = AmlParseDefinitionBlock (
|
|
|
+ (EFI_ACPI_DESCRIPTION_HEADER*)ssdtserialporttemplate_aml_code,
|
|
|
+ &RootNodeHandle
|
|
|
+ );
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ DEBUG ((
|
|
|
+ DEBUG_ERROR,
|
|
|
+ "ERROR: SSDT-SERIAL-PORT-FIXUP:"
|
|
|
+ " Failed to parse SSDT Serial Port Template. Status = %r\n",
|
|
|
+ Status
|
|
|
+ ));
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Fixup the template values.
|
|
|
+ Status = FixupSerialPortInfo (
|
|
|
+ RootNodeHandle,
|
|
|
+ SerialPortInfo,
|
|
|
+ Name,
|
|
|
+ Uid,
|
|
|
+ Table
|
|
|
+ );
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ DEBUG ((
|
|
|
+ DEBUG_ERROR,
|
|
|
+ "ERROR: SSDT-SERIAL-PORT-FIXUP: Failed to fixup SSDT Serial Port Table."
|
|
|
+ " Status = %r\n",
|
|
|
+ Status
|
|
|
+ ));
|
|
|
+ goto exit_handler;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Serialize the tree.
|
|
|
+ Status = AmlSerializeDefinitionBlock (
|
|
|
+ RootNodeHandle,
|
|
|
+ Table
|
|
|
+ );
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ DEBUG ((
|
|
|
+ DEBUG_ERROR,
|
|
|
+ "ERROR: SSDT-SERIAL-PORT-FIXUP: Failed to Serialize SSDT Table Data."
|
|
|
+ " Status = %r\n",
|
|
|
+ Status
|
|
|
+ ));
|
|
|
+ }
|
|
|
+
|
|
|
+exit_handler:
|
|
|
+ // Cleanup
|
|
|
+ if (RootNodeHandle != NULL) {
|
|
|
+ Status1 = AmlDeleteTree (RootNodeHandle);
|
|
|
+ if (EFI_ERROR (Status1)) {
|
|
|
+ DEBUG ((
|
|
|
+ DEBUG_ERROR,
|
|
|
+ "ERROR: SSDT-SERIAL-PORT-FIXUP: Failed to cleanup AML tree."
|
|
|
+ " Status = %r\n",
|
|
|
+ Status1
|
|
|
+ ));
|
|
|
+ // If Status was success but we failed to delete the AML Tree
|
|
|
+ // return Status1 else return the original error code, i.e. Status.
|
|
|
+ if (!EFI_ERROR (Status)) {
|
|
|
+ return Status1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return Status;
|
|
|
+}
|