]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ArmVirtPkg: 16550 UART Platform hook library
authorSami Mujawar <sami.mujawar@arm.com>
Fri, 2 Oct 2020 21:14:03 +0000 (22:14 +0100)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Fri, 16 Oct 2020 17:21:04 +0000 (17:21 +0000)
The BaseSerialPort16550 library invokes the
PlatformHookSerialPortInitialize() implemented as
part of the PlatformHook library, to perform platform
specific initialization required to enable use of the
16550 device. The BaseSerialPort16550 library uses
the PcdSerialRegisterBase to obtain the base address
of the UART for MMIO operations.

Some VMMs like Kvmtool provide the base address of
the console serial port in the platform device tree.

This patch introduces two instances of the Platform
Hook library:
1. EarlyFdt16550SerialPortHookLib - parses the
   platform device tree to extract the base
   address of the 16550 UART and update the PCD
   PcdSerialRegisterBase.
2. Fdt16550SerialPortHookLib - reads the GUID
   Hob gEarly16550UartBaseAddressGuid (that caches
   the base address of the 16550 UART discovered
   during early stages) and updates the PCD
   PcdSerialRegisterBase.

Note:
  a. The PCD PcdSerialRegisterBase is configured
     as PatchableInModule.
  b. A separate patch introduces a PlatformPeiLib
     that trampolines the 16550 UART base address
     from the Pcd PcdSerialRegisterBase to the
     GUID Hob gEarly16550UartBaseAddressGuid.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
Reviewed-by: Ard Biesheuvel <Ard.Biesheuvel@arm.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
ArmVirtPkg/Library/Fdt16550SerialPortHookLib/EarlyFdt16550SerialPortHookLib.c [new file with mode: 0644]
ArmVirtPkg/Library/Fdt16550SerialPortHookLib/EarlyFdt16550SerialPortHookLib.inf [new file with mode: 0644]
ArmVirtPkg/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.c [new file with mode: 0644]
ArmVirtPkg/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.inf [new file with mode: 0644]
ArmVirtPkg/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.uni [new file with mode: 0644]

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