diff options
4 files changed, 229 insertions, 0 deletions
diff --git a/ArmVirtPkg/Library/DebugLibFdtPL011Uart/DebugLibFdtPL011UartRam.inf b/ArmVirtPkg/Library/DebugLibFdtPL011Uart/DebugLibFdtPL011UartRam.inf new file mode 100644 index 0000000000..a5f4c2d80a --- /dev/null +++ b/ArmVirtPkg/Library/DebugLibFdtPL011Uart/DebugLibFdtPL011UartRam.inf @@ -0,0 +1,60 @@ +## @file
+# DebugLib instance that produces debug output directly via PL011UartLib.
+#
+# If there are at least two PL011 UARTs in the device tree, and the /chosen
+# node's "stdout-path" property references one PL011 UART, then both raw
+# SerialPortLib IO, and -- via SerialDxe -- UEFI console IO, will occur on that
+# UART; and this DebugLib instance will produce output on a *different* UART.
+#
+# This instance is suitable for modules that can only run from RAM (except
+# DXE_RUNTIME_DRIVER).
+#
+# Copyright (C) Red Hat
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 1.27
+ BASE_NAME = DebugLibFdtPL011UartRam
+ FILE_GUID = 0584DE55-9C4C-49C1-ADA0-F62C9C1F3600
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = DebugLib|DXE_CORE SMM_CORE MM_CORE_STANDALONE DXE_DRIVER DXE_SMM_DRIVER SMM_DRIVER MM_STANDALONE UEFI_DRIVER UEFI_APPLICATION
+ CONSTRUCTOR = DebugLibFdtPL011UartRamConstructor
+
+[Sources]
+ DebugLib.c
+ Ram.c
+ Ram.h
+ RamNonRuntime.c
+ Write.h
+
+[Packages]
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ ArmVirtPkg/ArmVirtPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugPrintErrorLevelLib
+ HobLib # Ram.c
+ PL011UartLib
+ PcdLib
+ PrintLib
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask
+ gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel
+
+[FixedPcd]
+ gArmPlatformTokenSpaceGuid.PL011UartClkInHz
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
+
+[Guids]
+ gEarlyPL011BaseAddressGuid # Ram.c
diff --git a/ArmVirtPkg/Library/DebugLibFdtPL011Uart/Ram.c b/ArmVirtPkg/Library/DebugLibFdtPL011Uart/Ram.c new file mode 100644 index 0000000000..bc5be015bd --- /dev/null +++ b/ArmVirtPkg/Library/DebugLibFdtPL011Uart/Ram.c @@ -0,0 +1,124 @@ +/** @file
+ Define DebugLibFdtPL011UartWrite() for modules that can only run from RAM.
+
+ Copyright (C) Red Hat
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Uefi/UefiMultiPhase.h>
+#include <Pi/PiBootMode.h>
+#include <Pi/PiHob.h>
+#include <Library/HobLib.h>
+#include <Library/PL011UartLib.h>
+#include <Library/PcdLib.h>
+#include <Guid/EarlyPL011BaseAddress.h>
+
+#include "Ram.h"
+#include "Write.h"
+
+UINTN mDebugLibFdtPL011UartAddress;
+RETURN_STATUS mDebugLibFdtPL011UartPermanentStatus = RETURN_SUCCESS;
+
+/**
+ Statefully initialize both the library instance and the debug PL011 UART.
+**/
+STATIC
+RETURN_STATUS
+Initialize (
+ VOID
+ )
+{
+ CONST VOID *Hob;
+ CONST EARLY_PL011_BASE_ADDRESS *UartBase;
+ RETURN_STATUS Status;
+ UINTN DebugAddress;
+ UINT64 BaudRate;
+ UINT32 ReceiveFifoDepth;
+ EFI_PARITY_TYPE Parity;
+ UINT8 DataBits;
+ EFI_STOP_BITS_TYPE StopBits;
+
+ if (mDebugLibFdtPL011UartAddress != 0) {
+ return RETURN_SUCCESS;
+ }
+
+ if (RETURN_ERROR (mDebugLibFdtPL011UartPermanentStatus)) {
+ return mDebugLibFdtPL011UartPermanentStatus;
+ }
+
+ Hob = GetFirstGuidHob (&gEarlyPL011BaseAddressGuid);
+ if ((Hob == NULL) || (GET_GUID_HOB_DATA_SIZE (Hob) != sizeof *UartBase)) {
+ Status = RETURN_NOT_FOUND;
+ goto Failed;
+ }
+
+ UartBase = GET_GUID_HOB_DATA (Hob);
+
+ DebugAddress = (UINTN)UartBase->DebugAddress;
+ if (DebugAddress == 0) {
+ Status = RETURN_NOT_FOUND;
+ goto Failed;
+ }
+
+ BaudRate = (UINTN)PcdGet64 (PcdUartDefaultBaudRate);
+ ReceiveFifoDepth = 0; // Use the default value for Fifo depth
+ Parity = (EFI_PARITY_TYPE)PcdGet8 (PcdUartDefaultParity);
+ DataBits = PcdGet8 (PcdUartDefaultDataBits);
+ StopBits = (EFI_STOP_BITS_TYPE)PcdGet8 (PcdUartDefaultStopBits);
+
+ Status = PL011UartInitializePort (
+ DebugAddress,
+ FixedPcdGet32 (PL011UartClkInHz),
+ &BaudRate,
+ &ReceiveFifoDepth,
+ &Parity,
+ &DataBits,
+ &StopBits
+ );
+ if (RETURN_ERROR (Status)) {
+ goto Failed;
+ }
+
+ mDebugLibFdtPL011UartAddress = DebugAddress;
+ return RETURN_SUCCESS;
+
+Failed:
+ mDebugLibFdtPL011UartPermanentStatus = Status;
+ return Status;
+}
+
+/**
+ (Copied from SerialPortWrite() in "MdePkg/Include/Library/SerialPortLib.h" at
+ commit c4547aefb3d0, with the Buffer non-nullity assertion removed:)
+
+ Write data from buffer to serial device.
+
+ Writes NumberOfBytes data bytes from Buffer to the serial device.
+ The number of bytes actually written to the serial device is returned.
+ If the return value is less than NumberOfBytes, then the write operation failed.
+ If NumberOfBytes is zero, then return 0.
+
+ @param Buffer Pointer to the data buffer to be written.
+ @param NumberOfBytes Number of bytes to written to the serial device.
+
+ @retval 0 NumberOfBytes is 0.
+ @retval >0 The number of bytes written to the serial device.
+ If this value is less than NumberOfBytes, then the write operation failed.
+**/
+UINTN
+DebugLibFdtPL011UartWrite (
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+ )
+{
+ RETURN_STATUS Status;
+
+ Status = Initialize ();
+ if (RETURN_ERROR (Status)) {
+ return 0;
+ }
+
+ return PL011UartWrite (mDebugLibFdtPL011UartAddress, Buffer, NumberOfBytes);
+}
diff --git a/ArmVirtPkg/Library/DebugLibFdtPL011Uart/Ram.h b/ArmVirtPkg/Library/DebugLibFdtPL011Uart/Ram.h new file mode 100644 index 0000000000..8c1ef52b4d --- /dev/null +++ b/ArmVirtPkg/Library/DebugLibFdtPL011Uart/Ram.h @@ -0,0 +1,18 @@ +/** @file
+ Declare the variables that modules that can only run from RAM use for
+ remembering initialization status.
+
+ Copyright (C) Red Hat
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef DEBUG_LIB_FDT_PL011_UART_RAM_H_
+#define DEBUG_LIB_FDT_PL011_UART_RAM_H_
+
+#include <Base.h>
+
+extern UINTN mDebugLibFdtPL011UartAddress;
+extern RETURN_STATUS mDebugLibFdtPL011UartPermanentStatus;
+
+#endif
diff --git a/ArmVirtPkg/Library/DebugLibFdtPL011Uart/RamNonRuntime.c b/ArmVirtPkg/Library/DebugLibFdtPL011Uart/RamNonRuntime.c new file mode 100644 index 0000000000..715d3400dd --- /dev/null +++ b/ArmVirtPkg/Library/DebugLibFdtPL011Uart/RamNonRuntime.c @@ -0,0 +1,27 @@ +/** @file
+ Provide an empty lib instance constructor for modules that can only run from
+ RAM but are not DXE_RUNTIME_DRIVER modules.
+
+ This ensures that e.g. any HobLib constructor is ordered correctly. (The
+ DXE_CORE calls constructors late, but the DXE_CORE HobLib instance needs no
+ construction anyway.)
+
+ Copyright (C) Red Hat
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+
+/**
+ Empty library instance constructor, only for ensuring the connectivity of the
+ constructor dependency graph.
+**/
+RETURN_STATUS
+EFIAPI
+DebugLibFdtPL011UartRamConstructor (
+ VOID
+ )
+{
+ return RETURN_SUCCESS;
+}
|