diff --git a/ArmVirtPkg/Library/Fdt16550SerialPortHookLib/EarlyFdt16550SerialPortHookLib.c b/ArmVirtPkg/Library/Fdt16550SerialPortHookLib/EarlyFdt16550SerialPortHookLib.c new file mode 100644 index 0000000000..61c9c47127 --- /dev/null +++ b/ArmVirtPkg/Library/Fdt16550SerialPortHookLib/EarlyFdt16550SerialPortHookLib.c @@ -0,0 +1,137 @@ +/** @file + Early Platform Hook Library instance for 16550 Uart. + + Copyright (c) 2020, ARM Ltd. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +/** Get the UART base address of the console serial-port from the DT. + + This function fetches the node referenced in the "stdout-path" + property of the "chosen" node and returns the base address of + the console UART. + + @param [in] Fdt Pointer to a Flattened Device Tree (Fdt). + @param [out] SerialConsoleAddress If success, contains the base address + of the console serial-port. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_FOUND Console serial-port info not found in DT. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +GetSerialConsolePortAddress ( + IN CONST VOID *Fdt, + OUT UINT64 *SerialConsoleAddress + ) +{ + CONST CHAR8 *Prop; + INT32 PropSize; + CONST CHAR8 *Path; + INT32 PathLen; + INT32 ChosenNode; + INT32 SerialConsoleNode; + INT32 Len; + CONST CHAR8 *NodeStatus; + CONST UINT64 *RegProperty; + + if ((Fdt == NULL) || (fdt_check_header (Fdt) != 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 (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 = AsciiStrLen (Prop); + } else { + PathLen = 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); + } else { + // 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); + } + + NodeStatus = fdt_getprop (Fdt, SerialConsoleNode, "status", &Len); + if ((NodeStatus != NULL) && (AsciiStrCmp (NodeStatus, "okay") != 0)) { + return EFI_NOT_FOUND; + } + + RegProperty = fdt_getprop (Fdt, SerialConsoleNode, "reg", &Len); + if (Len != 16) { + return EFI_INVALID_PARAMETER; + } + + *SerialConsoleAddress = fdt64_to_cpu (ReadUnaligned64 (RegProperty)); + + return EFI_SUCCESS; +} + +/** Platform hook to retrieve the 16550 UART base address from the platform + Device tree and store it in PcdSerialRegisterBase. + + @retval RETURN_SUCCESS Success. + @retval RETURN_INVALID_PARAMETER A parameter was invalid. + @retval RETURN_NOT_FOUND Serial port information not found. + +**/ +RETURN_STATUS +EFIAPI +PlatformHookSerialPortInitialize ( + VOID + ) +{ + RETURN_STATUS Status; + VOID *DeviceTreeBase; + UINT64 SerialConsoleAddress; + + if (PcdGet64 (PcdSerialRegisterBase) != 0) { + return RETURN_SUCCESS; + } + + DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress); + if (DeviceTreeBase == NULL) { + return RETURN_NOT_FOUND; + } + + Status = GetSerialConsolePortAddress (DeviceTreeBase, &SerialConsoleAddress); + if (RETURN_ERROR (Status)) { + return Status; + } + + return (EFI_STATUS)PcdSet64S (PcdSerialRegisterBase, SerialConsoleAddress); +} diff --git a/ArmVirtPkg/Library/Fdt16550SerialPortHookLib/EarlyFdt16550SerialPortHookLib.inf b/ArmVirtPkg/Library/Fdt16550SerialPortHookLib/EarlyFdt16550SerialPortHookLib.inf new file mode 100644 index 0000000000..007a45eca2 --- /dev/null +++ b/ArmVirtPkg/Library/Fdt16550SerialPortHookLib/EarlyFdt16550SerialPortHookLib.inf @@ -0,0 +1,36 @@ +## @file +# Early Platform Hook Library instance for 16550 Uart. +# +# Copyright (c) 2020, ARM Ltd. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = EarlyFdt16550SerialPortHookLib + MODULE_UNI_FILE = Fdt16550SerialPortHookLib.uni + FILE_GUID = FFB19961-79CC-4684-84A8-C31B0A2BBE82 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PlatformHookLib|SEC PEI_CORE PEIM + +[Sources] + EarlyFdt16550SerialPortHookLib.c + +[LibraryClasses] + BaseLib + PcdLib + FdtLib + HobLib + +[Packages] + ArmVirtPkg/ArmVirtPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + +[Pcd] + gArmVirtTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase diff --git a/ArmVirtPkg/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.c b/ArmVirtPkg/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.c new file mode 100644 index 0000000000..803725c3ce --- /dev/null +++ b/ArmVirtPkg/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.c @@ -0,0 +1,56 @@ +/** @file + Platform Hook Library instance for 16550 Uart. + + Copyright (c) 2020, ARM Ltd. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +/** Platform hook to retrieve the 16550 UART base address from the GUID Hob + that caches the UART base address from early boot stage and store it in + PcdSerialRegisterBase. + + @retval RETURN_SUCCESS Success. + @retval RETURN_NOT_FOUND Serial Port information not found. + +**/ +RETURN_STATUS +EFIAPI +PlatformHookSerialPortInitialize ( + VOID + ) +{ + VOID *Hob; + UINT64 *UartBase; + + if (PcdGet64 (PcdSerialRegisterBase) != 0) { + return RETURN_SUCCESS; + } + + Hob = GetFirstGuidHob (&gEarly16550UartBaseAddressGuid); + if ((Hob == NULL) || (GET_GUID_HOB_DATA_SIZE (Hob) != sizeof (*UartBase))) { + return RETURN_NOT_FOUND; + } + + UartBase = GET_GUID_HOB_DATA (Hob); + if ((UINTN)*UartBase == 0) { + return RETURN_NOT_FOUND; + } + + return (RETURN_STATUS)PcdSet64S (PcdSerialRegisterBase, (UINTN)*UartBase); +} diff --git a/ArmVirtPkg/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.inf b/ArmVirtPkg/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.inf new file mode 100644 index 0000000000..b131916470 --- /dev/null +++ b/ArmVirtPkg/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.inf @@ -0,0 +1,38 @@ +## @file +# Platform Hook Library instance for 16550 Uart. +# +# Copyright (c) 2020, ARM Ltd. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = Fdt16550SerialPortHookLib + MODULE_UNI_FILE = Fdt16550SerialPortHookLib.uni + FILE_GUID = C6DFD3F0-179D-4376-89A5-F641A2E7EFB5 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PlatformHookLib|DXE_CORE DXE_DRIVER UEFI_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION + CONSTRUCTOR = PlatformHookSerialPortInitialize + +[Sources] + Fdt16550SerialPortHookLib.c + +[LibraryClasses] + BaseLib + PcdLib + HobLib + +[Packages] + ArmVirtPkg/ArmVirtPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase + +[Guids] + gEarly16550UartBaseAddressGuid diff --git a/ArmVirtPkg/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.uni b/ArmVirtPkg/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.uni new file mode 100644 index 0000000000..70356534e9 --- /dev/null +++ b/ArmVirtPkg/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.uni @@ -0,0 +1,13 @@ +// /** @file +// Platform Hook Library instance for 16550 Uart. +// +// +// Copyright (c) 2020, ARM Ltd. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_MODULE_ABSTRACT #language en-US "Platform Hook Library instance for 16550 Uart." + +#string STR_MODULE_DESCRIPTION #language en-US "Platform Hook Library instance for 16550 Uart."