Hi Pierre, Please find my response inline marked [SAMI]. Regards, Sami Mujawar On 23/06/2021 01:38 PM, Pierre.Gondois@arm.com wrote: > From: Pierre Gondois > > The Microsoft Debug Port Table 2 (DBG2), the Serial Port Console > Redirector (SPCR) table are mandatory tables required for booting > a standards-based operating system. The DBG2 table is used by the > OS debugger while the SPCR table is used to configure the serial > terminal. Additionally, the serial ports available on a platform > for generic use also need to be described in DSDT/SSDT for an OS > to be able to use the serial ports. > > The Arm Base System Architecture 1.0 specification a lists of > supported serial port hardware for Arm Platforms. This list > includes the following serial port UARTs: > - SBSA/Generic UART > - a fully 16550 compatible UART. > Along, with these the PL011 UART is the most commonly used serial > port hardware on Arm platforms. > > The serial port hardware information is described in the platform > Device Tree, the bindings for which can be found at: > - linux/Documentation/devicetree/bindings/serial/serial.yaml > - linux/Documentation/devicetree/bindings/serial/8250.txt > - linux/Documentation/devicetree/bindings/serial/arm_sbsa_uart.txt > - linux/Documentation/devicetree/bindings/serial/pl011.yaml > > The FdtHwInfoParser implements a Serial Port Parser that parses > the platform Device Tree to create CM_ARM_SERIAL_PORT_INFO objects > with the following IDs: > - EArmObjSerialConsolePortInfo (for use by SPCR) > - EArmObjSerialDebugPortInfo (for use by DBG2) > - EArmObjSerialPortInfo (for use as generic Serial Ports) > > The Serial Port for use by SPCR is selected by parsing the Device > Tree for the '/chosen' node with the 'stdout-path' property. The > next Serial Port is selected for use as the Debug Serial Port and > the remaining serial ports are used as generic serial ports. > > The CM_ARM_SERIAL_PORT_INFO objects are encapsulated in Configuration > Manager descriptor objects with the respective IDs and are added to > the platform information repository. > > The platform Configuration Manager can then utilise this information > when generating the DBG2, SPCR and the SSDT serial port tables. > > Signed-off-by: Pierre Gondois > Signed-off-by: Sami Mujawar > --- > .../Serial/ArmSerialPortParser.c | 621 ++++++++++++++++++ > .../Serial/ArmSerialPortParser.h | 47 ++ > 2 files changed, 668 insertions(+) > create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/Serial/ArmSerialPortParser.c > create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/Serial/ArmSerialPortParser.h > > diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/Serial/ArmSerialPortParser.c b/DynamicTablesPkg/Library/FdtHwInfoParserLib/Serial/ArmSerialPortParser.c > new file mode 100644 > index 000000000000..d5db206ae93c > --- /dev/null > +++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/Serial/ArmSerialPortParser.c > @@ -0,0 +1,621 @@ > +/** @file > + Arm Serial Port Parser. > + > + Copyright (c) 2021, ARM Limited. All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent > + > + @par Reference(s): > + - linux/Documentation/devicetree/bindings/serial/serial.yaml > + - linux/Documentation/devicetree/bindings/serial/8250.txt > + - linux/Documentation/devicetree/bindings/serial/arm_sbsa_uart.txt > + - linux/Documentation/devicetree/bindings/serial/pl011.yaml > +**/ > + > +#include > + > +#include "CmObjectDescUtility.h" > +#include "FdtHwInfoParser.h" > +#include "Serial/ArmSerialPortParser.h" > + > +/** List of "compatible" property values for serial port nodes. > + > + Any other "compatible" value is not supported by this module. > +*/ > +STATIC CONST COMPATIBILITY_STR SerialCompatibleStr[] = { > + {"ns16550a"}, > + {"arm,sbsa-uart"} > +}; > + > +/** COMPATIBILITY_INFO structure for the SerialCompatible. > +*/ > +CONST COMPATIBILITY_INFO SerialCompatibleInfo = { > + ARRAY_SIZE (SerialCompatibleStr), > + SerialCompatibleStr > +}; > + > +/** 16550 UART compatible strings. > + > + Any string of this list must be part of SerialCompatible. > +*/ > +STATIC CONST COMPATIBILITY_STR Serial16550CompatibleStr[] = { > + {"ns16550a"} > +}; > + > +/** COMPATIBILITY_INFO structure for the Serial16550Compatible. > +*/ > +CONST COMPATIBILITY_INFO Serial16550CompatibleInfo = { > + ARRAY_SIZE (Serial16550CompatibleStr), > + Serial16550CompatibleStr > +}; > + > +/** SBSA UART compatible strings. > + > + Any string of this list must be part of SerialCompatible. > +*/ > +STATIC CONST COMPATIBILITY_STR SerialSbsaCompatibleStr[] = { > + {"arm,sbsa-uart"} > +}; > + > +/** COMPATIBILITY_INFO structure for the SerialSbsaCompatible. > +*/ > +CONST COMPATIBILITY_INFO SerialSbsaCompatibleInfo = { > + ARRAY_SIZE (SerialSbsaCompatibleStr), > + SerialSbsaCompatibleStr > +}; > + > +/** Parse a serial port node. > + > + @param [in] Fdt Pointer to a Flattened Device Tree (Fdt). > + @param [in] SerialPortNode Offset of a serial-port node. > + @param [in] SerialPortInfo The CM_ARM_SERIAL_PORT_INFO to populate. > + > + @retval EFI_SUCCESS The function completed successfully. > + @retval EFI_ABORTED An error occurred. > + @retval EFI_INVALID_PARAMETER Invalid parameter. > + @retval EFI_UNSUPPORTED Unsupported. > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +SerialPortNodeParser ( > + IN CONST VOID * Fdt, > + IN INT32 SerialPortNode, > + IN CM_ARM_SERIAL_PORT_INFO * SerialPortInfo > + ) > +{ > + EFI_STATUS Status; > + INT32 IntcNode; > + CONST UINT8 * SizeValue; > + > + INT32 AddressCells; > + INT32 SizeCells; > + INT32 IntCells; > + > + CONST UINT8 * Data; > + INT32 DataSize; > + UINT8 AccessSize; > + > + if ((Fdt == NULL) || > + (SerialPortInfo == NULL)) { > + ASSERT (0); > + return EFI_INVALID_PARAMETER; > + } > + > + Status = FdtGetParentAddressInfo ( > + Fdt, > + SerialPortNode, > + &AddressCells, > + &SizeCells > + ); > + if (EFI_ERROR (Status)) { > + ASSERT (0); > + return Status; > + } > + > + // Don't support more than 64 bits and less than 32 bits addresses. > + if ((AddressCells < 1) || > + (AddressCells > 2) || > + (SizeCells < 1) || > + (SizeCells > 2)) { > + ASSERT (0); > + return EFI_ABORTED; > + } > + > + Data = fdt_getprop (Fdt, SerialPortNode, "reg", &DataSize); > + if ((Data == NULL) || > + (DataSize < (INT32)(sizeof (UINT32) * > + GET_DT_REG_ADDRESS_OFFSET (1, AddressCells, SizeCells)) - 1)) { > + // If error or not enough space. > + ASSERT (0); > + return EFI_ABORTED; > + } > + > + if (AddressCells == 2) { > + SerialPortInfo->BaseAddress = fdt64_to_cpu (*(UINT64*)Data); > + } else { > + SerialPortInfo->BaseAddress = fdt32_to_cpu (*(UINT32*)Data); > + } > + > + SizeValue = Data + (sizeof (UINT32) * > + GET_DT_REG_SIZE_OFFSET (0, AddressCells, SizeCells)); > + if (SizeCells == 2) { > + SerialPortInfo->BaseAddressLength = fdt64_to_cpu (*(UINT64*)SizeValue); > + } else { > + SerialPortInfo->BaseAddressLength = fdt32_to_cpu (*(UINT32*)SizeValue); > + } > + > + // Get the associated interrupt-controller. > + Status= FdtGetIntcParentNode (Fdt, SerialPortNode, &IntcNode); > + if (EFI_ERROR (Status)) { > + ASSERT (0); > + if (Status == EFI_NOT_FOUND) { > + // Should have found the node. > + Status = EFI_ABORTED; > + } > + return Status; > + } > + > + // Get the number of cells used to encode an interrupt. > + Status = FdtGetInterruptCellsInfo (Fdt, IntcNode, &IntCells); > + if (EFI_ERROR (Status)) { > + ASSERT (0); > + return Status; > + } > + > + Data = fdt_getprop (Fdt, SerialPortNode, "interrupts", &DataSize); > + if ((Data == NULL) || (DataSize != (IntCells * sizeof (UINT32)))) { > + // If error or not 1 interrupt. > + ASSERT (0); > + return EFI_ABORTED; > + } > + > + SerialPortInfo->Interrupt = FdtGetInterruptId ((CONST UINT32*)Data); > + > + // Note: clock-frequency is optional for SBSA UART. > + Data = fdt_getprop (Fdt, SerialPortNode, "clock-frequency", &DataSize); > + if (Data != NULL) { > + if (DataSize < sizeof (UINT32)) { > + // If error or not enough space. > + ASSERT (0); > + return EFI_ABORTED; > + } else if (fdt_node_offset_by_phandle (Fdt, fdt32_to_cpu (*Data)) >= 0) { > + // "clock-frequency" can be a "clocks phandle to refer to the clk used". > + // This is not supported. > + ASSERT (0); > + return EFI_UNSUPPORTED; > + } > + SerialPortInfo->Clock = fdt32_to_cpu (*(UINT32*)Data); > + } > + > + if (FdtNodeIsCompatible (Fdt, SerialPortNode, &Serial16550CompatibleInfo)) { > + SerialPortInfo->PortSubtype = EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_FULL_16550; [SAMI] I think this needs to be set toEFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_16550_WITH_GAS. > + > + /* reg-io-width: > + description: | > + The size (in bytes) of the IO accesses that should be performed on the > + device. There are some systems that require 32-bit accesses to the > + UART. > + */ > + Data = fdt_getprop (Fdt, SerialPortNode, "reg-io-width", &DataSize); > + if (Data != NULL) { > + if (DataSize < sizeof (UINT32)) { > + // If error or not enough space. > + ASSERT (0); > + return EFI_ABORTED; > + } > + > + AccessSize = fdt32_to_cpu (*(UINT32*)Data); > + if (AccessSize > EFI_ACPI_6_3_QWORD) { > + ASSERT (0); > + return EFI_INVALID_PARAMETER; > + } > + SerialPortInfo->AccessSize = AccessSize; > + } else { > + // 8250/16550 defaults to byte access. > + SerialPortInfo->AccessSize = EFI_ACPI_6_3_BYTE; > + } > + } else if (FdtNodeIsCompatible ( > + Fdt, > + SerialPortNode, > + &SerialSbsaCompatibleInfo > + )) { > + SerialPortInfo->PortSubtype = > + EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART; [SAMI] Should PL011 be supported as well? > + } else { > + ASSERT (0); > + return EFI_UNSUPPORTED; > + } > + > + // Set Baudrate to 115200 by default > + SerialPortInfo->BaudRate = 115200; > + return EFI_SUCCESS; > +} > + > +/** Find the console serial-port node in the DT. > + > + This function fetches the node referenced in the "stdout-path" > + property of the "chosen" node. > + > + @param [in] Fdt Pointer to a Flattened Device Tree (Fdt). > + @param [out] SerialConsoleNode If success, contains the node offset > + of the console serial-port node. > + > + @retval EFI_SUCCESS The function completed successfully. > + @retval EFI_ABORTED An error occurred. > + @retval EFI_INVALID_PARAMETER Invalid parameter. > + @retval EFI_NOT_FOUND Not found. > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +GetSerialConsoleNode ( > + IN CONST VOID * Fdt, > + OUT INT32 * SerialConsoleNode > + ) > +{ > + CONST CHAR8 * Prop; > + INT32 PropSize; > + CONST CHAR8 * Path; > + INT32 PathLen; > + INT32 ChosenNode; > + > + if ((Fdt == NULL) || > + (SerialConsoleNode == NULL)) { > + ASSERT (0); > + return EFI_INVALID_PARAMETER; > + } > + > + // The "chosen" node resides at the the root of the DT. Fetch it. > + ChosenNode = fdt_path_offset (Fdt, "/chosen"); > + if (ChosenNode < 0) { > + return EFI_NOT_FOUND; > + } > + > + Prop = fdt_getprop (Fdt, ChosenNode, "stdout-path", &PropSize); > + if ((Prop == NULL) || (PropSize < 0)) { > + return EFI_NOT_FOUND; > + } > + > + // Determine the actual path length, as a colon terminates the path. > + Path = ScanMem8 (Prop, ':', PropSize); > + if (Path == NULL) { > + PathLen = (UINT32)AsciiStrLen (Prop); > + } else { > + PathLen = (INT32)(Path - Prop); > + } > + > + // Aliases cannot start with a '/', so it must be the actual path. > + if (Prop[0] == '/') { > + *SerialConsoleNode = fdt_path_offset_namelen (Fdt, Prop, PathLen); > + return EFI_SUCCESS; > + } > + > + // Lookup the alias, as this contains the actual path. > + Path = fdt_get_alias_namelen (Fdt, Prop, PathLen); > + if (Path == NULL) { > + return EFI_NOT_FOUND; > + } > + > + *SerialConsoleNode = fdt_path_offset (Fdt, Path); > + return EFI_SUCCESS; > +} > + > +/** CM_ARM_SERIAL_PORT_INFO dispatcher function (for a generic serial-port). > + > + @param [in] FdtParserHandle A handle to the parser instance. > + @param [in] GenericSerialInfo Pointer to a serial port info list. > + @param [in] NodeCount Count of serial ports to dispatch. > + @param [in] SerialObjectId Serial port object ID. > + > + @retval EFI_SUCCESS The function completed successfully. > + @retval EFI_ABORTED An error occurred. > + @retval EFI_INVALID_PARAMETER Invalid parameter. > + @retval EFI_NOT_FOUND Not found. > + @retval EFI_UNSUPPORTED Unsupported. > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +ArmSerialPortInfoDispatch ( > + IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle, > + IN CM_ARM_SERIAL_PORT_INFO * GenericSerialInfo, > + IN INT32 NodeCount, > + IN EARM_OBJECT_ID SerialObjectId > +) > +{ > + EFI_STATUS Status; > + CM_OBJ_DESCRIPTOR * NewCmObjDesc; > + > + if ((GenericSerialInfo == NULL) || (NodeCount == 0)) { > + ASSERT (0); > + return EFI_INVALID_PARAMETER; > + } > + > + if ((SerialObjectId != EArmObjSerialPortInfo) && > + (SerialObjectId != EArmObjSerialDebugPortInfo) && > + (SerialObjectId != EArmObjSerialConsolePortInfo)) { > + ASSERT (0); > + return EFI_INVALID_PARAMETER; > + } > + > + // Dispatch the Generic Serial ports > + Status = CreateCmObjDesc ( > + CREATE_CM_ARM_OBJECT_ID (SerialObjectId), > + NodeCount, > + GenericSerialInfo, > + sizeof (CM_ARM_SERIAL_PORT_INFO) * NodeCount, > + &NewCmObjDesc > + ); > + if (EFI_ERROR (Status)) { > + ASSERT (0); > + return Status; > + } > + > + // Add all the CmObjs to the Configuration Manager. > + Status = AddMultipleCmObj (FdtParserHandle, NewCmObjDesc, 0, NULL); > + if (EFI_ERROR (Status)) { > + ASSERT (0); > + } > + > + FreeCmObjDesc (NewCmObjDesc); > + return Status; > +} > + > +/** CM_ARM_SERIAL_PORT_INFO parser function (for debug/console serial-port). > + > + This parser expects FdtBranch to be the debug serial-port node. > + At most one CmObj is created. > + The following structure is populated: > + typedef struct CmArmSerialPortInfo { > + UINT64 BaseAddress; // {Populated} > + UINT32 Interrupt; // {Populated} > + UINT64 BaudRate; // {default} > + UINT32 Clock; // {Populated} > + UINT16 PortSubtype; // {Populated} > + UINT64 BaseAddressLength // {Populated} > + } CM_ARM_SERIAL_PORT_INFO; > + > + A parser parses a Device Tree to populate a specific CmObj type. None, > + one or many CmObj can be created by the parser. > + The created CmObj are then handed to the parser's caller through the > + HW_INFO_ADD_OBJECT interface. > + This can also be a dispatcher. I.e. a function that not parsing a > + Device Tree but calling other parsers. > + > + @param [in] FdtParserHandle A handle to the parser instance. > + @param [in] FdtBranch When searching for DT node name, restrict > + the search to this Device Tree branch. > + @param [in] SerialObjectId ArmNamespace Object ID for the serial port. > + > + @retval EFI_SUCCESS The function completed successfully. > + @retval EFI_ABORTED An error occurred. > + @retval EFI_INVALID_PARAMETER Invalid parameter. > + @retval EFI_NOT_FOUND Not found. > + @retval EFI_UNSUPPORTED Unsupported. > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +ArmSerialPortInfoParser ( > + IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle, > + IN INT32 FdtBranch, > + IN EARM_OBJECT_ID SerialObjectId > + ) > +{ > + EFI_STATUS Status; > + CM_ARM_SERIAL_PORT_INFO SerialInfo; > + > + if ((SerialObjectId != EArmObjSerialDebugPortInfo) && > + (SerialObjectId != EArmObjSerialConsolePortInfo)) { > + ASSERT (0); > + return EFI_INVALID_PARAMETER; > + } > + > + ZeroMem (&SerialInfo, sizeof (SerialInfo)); > + > + Status = SerialPortNodeParser ( > + FdtParserHandle->Fdt, > + FdtBranch, > + &SerialInfo > + ); > + if (EFI_ERROR (Status)) { > + ASSERT (0); > + return Status; > + } > + > + Status = ArmSerialPortInfoDispatch ( > + FdtParserHandle, > + &SerialInfo, > + 1, > + SerialObjectId > + ); > + if (EFI_ERROR (Status)) { > + ASSERT (0); > + } > + > + return Status; > +} > + > +/** SerialPort dispatcher. > + > + This disptacher populates the CM_ARM_SERIAL_PORT_INFO structure for > + the following CM_OBJ_ID: > + - EArmObjSerialConsolePortInfo > + - EArmObjSerialDebugPortInfo > + - EArmObjSerialPortInfo > + > + A parser parses a Device Tree to populate a specific CmObj type. None, > + one or many CmObj can be created by the parser. > + The created CmObj are then handed to the parser's caller through the > + HW_INFO_ADD_OBJECT interface. > + This can also be a dispatcher. I.e. a function that not parsing a > + Device Tree but calling other parsers. > + > + @param [in] FdtParserHandle A handle to the parser instance. > + @param [in] FdtBranch When searching for DT node name, restrict > + the search to this Device Tree branch. > + > + @retval EFI_SUCCESS The function completed successfully. > + @retval EFI_ABORTED An error occurred. > + @retval EFI_INVALID_PARAMETER Invalid parameter. > + @retval EFI_NOT_FOUND Not found. > + @retval EFI_UNSUPPORTED Unsupported. > +**/ > +EFI_STATUS > +EFIAPI > +SerialPortDispatcher ( > + IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle, > + IN INT32 FdtBranch > + ) > +{ > + EFI_STATUS Status; > + INT32 SerialConsoleNode; > + INT32 SerialDebugNode; > + INT32 SerialNode; > + UINT32 Index; > + UINT32 SerialNodeCount; > + UINT32 SerialNodesRemaining; > + CM_ARM_SERIAL_PORT_INFO * GenericSerialInfo; > + UINT32 GenericSerialIndex; > + VOID * Fdt; > + > + if (FdtParserHandle == NULL) { > + ASSERT (0); > + return EFI_INVALID_PARAMETER; > + } > + > + Fdt = FdtParserHandle->Fdt; > + > + // Count the number of serial-ports. > + Status = FdtCountCompatNodeInBranch ( > + Fdt, > + FdtBranch, > + &SerialCompatibleInfo, > + &SerialNodeCount > + ); > + if (EFI_ERROR (Status)) { > + ASSERT (0); > + return Status; > + } > + > + if (SerialNodeCount == 0) { > + return EFI_NOT_FOUND; > + } > + > + // Track remaining nodes separately as SerialNodeCount > + // is used in for loop below and reducing SerialNodeCount > + // would result in the Generic Serial port nodes not > + // being found if the serial console port node is among > + // the first few serial nodes. > + SerialNodesRemaining = SerialNodeCount; > + > + // Identify the serial console port. > + Status = GetSerialConsoleNode (Fdt, &SerialConsoleNode); > + if (Status == EFI_NOT_FOUND) { > + // No serial console. > + SerialConsoleNode = -1; > + } else if (EFI_ERROR (Status)) { > + ASSERT (0); > + return Status; > + } else { > + // Parse the console serial-port. > + Status = ArmSerialPortInfoParser ( > + FdtParserHandle, > + SerialConsoleNode, > + EArmObjSerialConsolePortInfo > + ); > + if (EFI_ERROR (Status)) { > + ASSERT (0); > + return Status; > + } > + SerialNodesRemaining--; > + } > + > + GenericSerialInfo = NULL; > + if (SerialNodesRemaining > 1) { > + // We have more than one serial port remaining. > + // This means that the first serial port will > + // be reserved as a debug port, and the remaining > + // will be for general purpose use. > + SerialNodesRemaining--; > + GenericSerialInfo = AllocateZeroPool ( > + SerialNodesRemaining * > + sizeof (CM_ARM_SERIAL_PORT_INFO) > + ); > + if (GenericSerialInfo == NULL) { > + ASSERT (0); > + return EFI_OUT_OF_RESOURCES; > + } > + } > + > + SerialNode = FdtBranch; > + SerialDebugNode = -1; > + GenericSerialIndex = 0; > + for (Index = 0; Index < SerialNodeCount; Index++) { > + // Search the next serial-port node in the branch. > + Status = FdtGetNextCompatNodeInBranch ( > + Fdt, > + FdtBranch, > + &SerialCompatibleInfo, > + &SerialNode > + ); > + if (EFI_ERROR (Status)) { > + ASSERT (0); > + if (Status == EFI_NOT_FOUND) { > + // Should have found the node. > + Status = EFI_ABORTED; > + } > + goto exit_handler; > + } > + > + // Ignore the serial console node. > + if (SerialNode == SerialConsoleNode) { > + continue; > + } else if (SerialDebugNode == -1) { > + // The first serial-port node, not being the console serial-port, > + // will be the debug serial-port. > + SerialDebugNode = SerialNode; > + Status = ArmSerialPortInfoParser ( > + FdtParserHandle, > + SerialDebugNode, > + EArmObjSerialDebugPortInfo > + ); > + if (EFI_ERROR (Status)) { > + ASSERT (0); > + goto exit_handler; > + } > + } else { > + if (GenericSerialInfo == NULL) { > + // Should not be possible. > + ASSERT (0); > + Status = EFI_ABORTED; > + goto exit_handler; > + } > + > + Status = SerialPortNodeParser ( > + Fdt, > + SerialNode, > + &GenericSerialInfo[GenericSerialIndex++] > + ); > + if (EFI_ERROR (Status)) { > + ASSERT (0); > + goto exit_handler; > + } > + } > + } // for > + > + if (GenericSerialIndex > 0) { > + Status = ArmSerialPortInfoDispatch ( > + FdtParserHandle, > + GenericSerialInfo, > + GenericSerialIndex, > + EArmObjSerialPortInfo > + ); > + } > + > +exit_handler: > + if (GenericSerialInfo != NULL) { > + FreePool (GenericSerialInfo); > + } > + return Status; > +} > diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/Serial/ArmSerialPortParser.h b/DynamicTablesPkg/Library/FdtHwInfoParserLib/Serial/ArmSerialPortParser.h > new file mode 100644 > index 000000000000..5e4707849e39 > --- /dev/null > +++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/Serial/ArmSerialPortParser.h > @@ -0,0 +1,47 @@ > +/** @file > + Arm Serial Port Parser. > + > + Copyright (c) 2021, ARM Limited. All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent > + > + @par Reference(s): > + - linux/Documentation/devicetree/bindings/serial/serial.yaml > + - linux/Documentation/devicetree/bindings/serial/8250.txt > +**/ > + > +#ifndef ARM_SERIAL_PORT_PARSER_H_ > +#define ARM_SERIAL_PORT_PARSER_H_ > + > +/** SerialPort dispatcher. > + > + This disptacher populates the CM_ARM_SERIAL_PORT_INFO structure for > + the following CM_OBJ_ID: > + - EArmObjSerialConsolePortInfo > + - EArmObjSerialDebugPortInfo > + - EArmObjSerialPortInfo > + > + A parser parses a Device Tree to populate a specific CmObj type. None, > + one or many CmObj can be created by the parser. > + The created CmObj are then handed to the parser's caller through the > + HW_INFO_ADD_OBJECT interface. > + This can also be a dispatcher. I.e. a function that not parsing a > + Device Tree but calling other parsers. > + > + @param [in] FdtParserHandle A handle to the parser instance. > + @param [in] FdtBranch When searching for DT node name, restrict > + the search to this Device Tree branch. > + > + @retval EFI_SUCCESS The function completed successfully. > + @retval EFI_ABORTED An error occurred. > + @retval EFI_INVALID_PARAMETER Invalid parameter. > + @retval EFI_NOT_FOUND Not found. > + @retval EFI_UNSUPPORTED Unsupported. > +**/ > +EFI_STATUS > +EFIAPI > +SerialPortDispatcher ( > + IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle, > + IN INT32 FdtBranch > + ); > + > +#endif // ARM_SERIAL_PORT_PARSER_H_