diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.c new file mode 100644 index 0000000000..ba6d277d45 --- /dev/null +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.c @@ -0,0 +1,185 @@ +/** @file + Serial I/O Port library functions with base address discovered from FDT + + Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.
+ Copyright (c) 2012 - 2013, ARM Ltd. All rights reserved.
+ Copyright (c) 2014, Linaro Ltd. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include + +#include + +RETURN_STATUS +EFIAPI +SerialPortInitialize ( + VOID + ) +{ + // + // This SerialPortInitialize() function is completely empty, for a number of + // reasons: + // - if we are executing from flash, it is hard to keep state (i.e., store the + // discovered base address in a global), and the most robust way to deal + // with this is to discover the base address at every Write (); + // - calls to the Write() function in this module may be issued before this + // initialization function is called: this is not a problem when the base + // address of the UART is hardcoded, and only the baud rate may be wrong, + // but if we don't know the base address yet, we may be poking into memory + // that does not tolerate being poked into; + // - SEC and PEI phases produce debug output only, so with debug disabled, no + // initialization (or device tree parsing) is performed at all. + // + // Note that this means that on *every* Write () call, the device tree will be + // parsed and the UART re-initialized. However, this is a small price to pay + // for having serial debug output on a UART with no fixed base address. + // + return RETURN_SUCCESS; +} + +STATIC +UINT64 +SerialPortGetBaseAddress ( + VOID + ) +{ + UINT64 BaudRate; + UINT32 ReceiveFifoDepth; + EFI_PARITY_TYPE Parity; + UINT8 DataBits; + EFI_STOP_BITS_TYPE StopBits; + VOID *DeviceTreeBase; + INT32 Node, Prev; + INT32 Len; + CONST CHAR8 *Compatible; + CONST CHAR8 *CompatibleItem; + CONST UINT64 *RegProperty; + UINTN UartBase; + RETURN_STATUS Status; + + DeviceTreeBase = (VOID *)(UINTN)FixedPcdGet64 (PcdDeviceTreeInitialBaseAddress); + + if ((DeviceTreeBase == NULL) || (fdt_check_header (DeviceTreeBase) != 0)) { + return 0; + } + + // + // Enumerate all FDT nodes looking for a PL011 and capture its base address + // + for (Prev = 0;; Prev = Node) { + Node = fdt_next_node (DeviceTreeBase, Prev, NULL); + if (Node < 0) { + break; + } + + Compatible = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len); + if (Compatible == NULL) { + continue; + } + + // + // Iterate over the NULL-separated items in the compatible string + // + for (CompatibleItem = Compatible; CompatibleItem < Compatible + Len; + CompatibleItem += 1 + AsciiStrLen (CompatibleItem)) { + + if (AsciiStrCmp (CompatibleItem, "arm,pl011") == 0) { + RegProperty = fdt_getprop (DeviceTreeBase, Node, "reg", &Len); + if (Len != 16) { + return 0; + } + UartBase = (UINTN)fdt64_to_cpu (ReadUnaligned64 (RegProperty)); + + BaudRate = (UINTN)FixedPcdGet64 (PcdUartDefaultBaudRate); + ReceiveFifoDepth = 0; // Use the default value for Fifo depth + Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity); + DataBits = FixedPcdGet8 (PcdUartDefaultDataBits); + StopBits = (EFI_STOP_BITS_TYPE) FixedPcdGet8 (PcdUartDefaultStopBits); + + Status = PL011UartInitializePort ( + UartBase, + &BaudRate, &ReceiveFifoDepth, &Parity, &DataBits, &StopBits); + if (!EFI_ERROR (Status)) { + return UartBase; + } + } + } + } + return 0; +} + +/** + Write data to serial device. + + @param Buffer Point of data buffer which need to be written. + @param NumberOfBytes Number of output bytes which are cached in Buffer. + + @retval 0 Write data failed. + @retval !0 Actual number of bytes written to serial device. + +**/ +UINTN +EFIAPI +SerialPortWrite ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes + ) +{ + UINT64 SerialRegisterBase; + + SerialRegisterBase = SerialPortGetBaseAddress (); + if (SerialRegisterBase != 0) { + return PL011UartWrite ((UINTN)SerialRegisterBase, Buffer, NumberOfBytes); + } + return 0; +} + +/** + Read data from serial device and save the data in buffer. + + @param Buffer Point of data buffer which need to be written. + @param NumberOfBytes Size of Buffer[]. + + @retval 0 Read data failed. + @retval !0 Actual number of bytes read from serial device. + +**/ +UINTN +EFIAPI +SerialPortRead ( + OUT UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + return 0; +} + +/** + Check to see if any data is available to be read from the debug device. + + @retval TRUE At least one byte of data is available to be read + @retval FALSE No data is available to be read + +**/ +BOOLEAN +EFIAPI +SerialPortPoll ( + VOID + ) +{ + return FALSE; +} diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.inf new file mode 100644 index 0000000000..d62f87bc30 --- /dev/null +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.inf @@ -0,0 +1,45 @@ +#/** @file +# +# Component description file for EarlyFdtPL011SerialPortLib module +# +# Copyright (c) 2011-2012, ARM Ltd. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = EarlyFdtPL011SerialPortLib + FILE_GUID = 0983616A-49BC-4732-B531-4AF98D2056F0 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = SerialPortLib|SEC PEI_CORE PEIM + +[Sources.common] + EarlyFdtPL011SerialPortLib.c + +[LibraryClasses] + PL011UartLib + PcdLib + FdtLib + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec + +[FixedPcd] + gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress + + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.c new file mode 100644 index 0000000000..aced6666a9 --- /dev/null +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.c @@ -0,0 +1,150 @@ +/** @file + Serial I/O Port library functions with base address discovered from FDT + + Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.
+ Copyright (c) 2012 - 2013, ARM Ltd. All rights reserved.
+ Copyright (c) 2014, Linaro Ltd. All rights reserved.
+ Copyright (c) 2014, Red Hat, Inc.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +STATIC UINTN mSerialBaseAddress; + +RETURN_STATUS +EFIAPI +SerialPortInitialize ( + VOID + ) +{ + return RETURN_SUCCESS; +} + +/** + + Program hardware of Serial port + + @return RETURN_NOT_FOUND if no PL011 base address could be found + Otherwise, result of PL011UartInitializePort () is returned + +**/ +RETURN_STATUS +EFIAPI +FdtPL011SerialPortLibInitialize ( + VOID + ) +{ + VOID *Hob; + CONST UINT64 *UartBase; + UINT64 BaudRate; + UINT32 ReceiveFifoDepth; + EFI_PARITY_TYPE Parity; + UINT8 DataBits; + EFI_STOP_BITS_TYPE StopBits; + + Hob = GetFirstGuidHob (&gEarlyPL011BaseAddressGuid); + if (Hob == NULL || GET_GUID_HOB_DATA_SIZE (Hob) != sizeof *UartBase) { + return RETURN_NOT_FOUND; + } + UartBase = GET_GUID_HOB_DATA (Hob); + + mSerialBaseAddress = (UINTN)*UartBase; + if (mSerialBaseAddress == 0) { + return RETURN_NOT_FOUND; + } + + 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); + + return PL011UartInitializePort ( + mSerialBaseAddress, &BaudRate, &ReceiveFifoDepth, + &Parity, &DataBits, &StopBits); +} + +/** + Write data to serial device. + + @param Buffer Point of data buffer which need to be written. + @param NumberOfBytes Number of output bytes which are cached in Buffer. + + @retval 0 Write data failed. + @retval !0 Actual number of bytes written to serial device. + +**/ +UINTN +EFIAPI +SerialPortWrite ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes + ) +{ + if (mSerialBaseAddress != 0) { + return PL011UartWrite (mSerialBaseAddress, Buffer, NumberOfBytes); + } + return 0; +} + +/** + Read data from serial device and save the data in buffer. + + @param Buffer Point of data buffer which need to be written. + @param NumberOfBytes Number of output bytes which are cached in Buffer. + + @retval 0 Read data failed. + @retval !0 Actual number of bytes read from serial device. + +**/ +UINTN +EFIAPI +SerialPortRead ( + OUT UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + if (mSerialBaseAddress != 0) { + return PL011UartRead (mSerialBaseAddress, Buffer, NumberOfBytes); + } + return 0; +} + +/** + Check to see if any data is available to be read from the debug device. + + @retval TRUE At least one byte of data is available to be read + @retval FALSE No data is available to be read + +**/ +BOOLEAN +EFIAPI +SerialPortPoll ( + VOID + ) +{ + if (mSerialBaseAddress != 0) { + return PL011UartPoll (mSerialBaseAddress); + } + return FALSE; +} diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.inf new file mode 100644 index 0000000000..178e6c4e02 --- /dev/null +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.inf @@ -0,0 +1,48 @@ +#/** @file +# +# Component description file for PL011SerialPortLib module +# +# Copyright (c) 2011-2012, ARM Ltd. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FdtPL011SerialPortLib + FILE_GUID = CB768406-7DE6-49B6-BC2C-F324E110DE5A + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = SerialPortLib|DXE_CORE DXE_DRIVER UEFI_DRIVER DXE_RUNTIME_DRIVER + CONSTRUCTOR = FdtPL011SerialPortLibInitialize + +[Sources.common] + FdtPL011SerialPortLib.c + +[LibraryClasses] + PL011UartLib + HobLib + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec + ArmPkg/ArmPkg.dec + +[FixedPcd] + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits + +[Guids] + gEarlyPL011BaseAddressGuid