@@ -44,3 +44,4 @@
[PcdsDynamic,PcdsFixedAtBuild]
gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeBaseAddress|0x0|UINT64|0x00000002
+ gArmVirtualizationTokenSpaceGuid.PcdPL011BaseAddress|0x0|UINT64|0x00000003
new file mode 100644
@@ -0,0 +1,186 @@
+/** @file
+ Serial I/O Port library functions with base address discovered from FDT
+
+ Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+ Copyright (c) 2012 - 2013, ARM Ltd. All rights reserved.<BR>
+ Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR>
+
+ 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 <Base.h>
+
+#include <Library/PcdLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/SerialPortExtLib.h>
+#include <libfdt.h>
+
+#include <Drivers/PL011Uart.h>
+
+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;
+
+ 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) {
+ INT32 Len;
+ CONST CHAR8 *Compatible;
+ CONST CHAR8 *CompItem;
+
+ 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 (CompItem = Compatible; CompItem < Compatible + Len;
+ CompItem += 1 + AsciiStrLen (CompItem)) {
+
+ if (AsciiStrCmp (CompItem, "arm,pl011") == 0) {
+ CONST UINT64 *RegProp;
+ UINTN UartBase;
+ RETURN_STATUS Status;
+
+ RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
+ if (Len != 16) {
+ return 0;
+ }
+ UartBase = (UINTN)fdt64_to_cpu(RegProp[0]);
+
+ 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 (Status == RETURN_SUCCESS) {
+ 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;
+}
new file mode 100644
@@ -0,0 +1,45 @@
+#/** @file
+#
+# Component description file for EarlyFdtPL011SerialPortLib module
+#
+# Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
+#
+# 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
+
+[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
new file mode 100644
@@ -0,0 +1,145 @@
+/** @file
+ Serial I/O Port library functions with base address discovered from FDT
+
+ Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+ Copyright (c) 2012 - 2013, ARM Ltd. All rights reserved.<BR>
+ Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR>
+
+ 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 <Base.h>
+
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/SerialPortExtLib.h>
+
+//
+// This is an artifical dependency on UefiBootServicesTableLib.h, which is
+// needed to make sure PcdGet64 () is callable once we get to our constructor
+//
+#include <Uefi/UefiSpec.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Drivers/PL011Uart.h>
+
+UINTN mSerialBaseAddress;
+
+/**
+
+ 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
+SerialPortInitialize (
+ VOID
+ )
+{
+ return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+EFIAPI
+FdtPL011SerialPortLibInitialize (
+ VOID
+ )
+{
+ UINT64 BaudRate;
+ UINT32 ReceiveFifoDepth;
+ EFI_PARITY_TYPE Parity;
+ UINT8 DataBits;
+ EFI_STOP_BITS_TYPE StopBits;
+
+ mSerialBaseAddress = (UINTN)PcdGet64 (PcdPL011BaseAddress);
+ 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;
+}
new file mode 100644
@@ -0,0 +1,50 @@
+#/** @file
+#
+# Component description file for PL011SerialPortLib module
+#
+# Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
+#
+# 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 = 0983616A-49BC-4732-B531-4AF98D2056F0
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SerialPortLib
+ CONSTRUCTOR = FdtPL011SerialPortLibInitialize
+
+[Sources.common]
+ FdtPL011SerialPortLib.c
+
+[LibraryClasses]
+ PL011UartLib
+ PcdLib
+ UefiBootServicesTableLib
+
+[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
+
+[Pcd]
+ gArmVirtualizationTokenSpaceGuid.PcdPL011BaseAddress
+ gArmTokenSpaceGuid.PcdSystemMemorySize
new file mode 100644
@@ -0,0 +1,47 @@
+/** @file
+
+ Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR>
+
+ 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 <Library/SerialPortExtLib.h>
+
+RETURN_STATUS
+EFIAPI
+SerialPortSetAttributes (
+ IN OUT UINT64 *BaudRate,
+ IN OUT UINT32 *ReceiveFifoDepth,
+ IN OUT UINT32 *Timeout,
+ IN OUT EFI_PARITY_TYPE *Parity,
+ IN OUT UINT8 *DataBits,
+ IN OUT EFI_STOP_BITS_TYPE *StopBits
+ )
+{
+ return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+EFIAPI
+SerialPortSetControl (
+ IN UINT32 Control
+ )
+{
+ return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+EFIAPI
+SerialPortGetControl (
+ OUT UINT32 *Control
+ )
+{
+ return RETURN_SUCCESS;
+}
new file mode 100644
@@ -0,0 +1,30 @@
+#/** @file
+#
+# Component description file for PL011SerialPortLib module
+#
+# Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
+#
+# 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 = NullSerialPortExtLib
+ FILE_GUID = BD396D28-085E-477A-A5DE-A8D91DD1F752
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SerialPortExtLib
+
+[Sources.common]
+ NullSerialPortExtLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
This adds 2 implementations of SerialPortLib for device tree based platforms using a PL011 UART: - an 'early' one which is completely stateless and uses only fixed PCDs - a normal one which takes its base address from a potentially dynamic PcdPL011BaseAddress PCD A NULL SerialPortExtLib instance is also provided. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> --- .../ArmVirtualizationPkg/ArmVirtualizationPkg.dec | 1 + .../EarlyFdtPL011SerialPortLib.c | 186 +++++++++++++++++++++ .../EarlyFdtPL011SerialPortLib.inf | 45 +++++ .../FdtPL011SerialPortLib/FdtPL011SerialPortLib.c | 145 ++++++++++++++++ .../FdtPL011SerialPortLib.inf | 50 ++++++ .../FdtPL011SerialPortLib/NullSerialPortExtLib.c | 47 ++++++ .../FdtPL011SerialPortLib/NullSerialPortExtLib.inf | 30 ++++ 7 files changed, 504 insertions(+) create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.c create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.inf create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.c create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.inf create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/NullSerialPortExtLib.c create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/NullSerialPortExtLib.inf