public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Pankaj Bansal" <pankaj.bansal@nxp.com>
To: Leif Lindholm <leif@nuviainc.com>
Cc: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>,
	Michael D Kinney <michael.d.kinney@intel.com>,
	Varun Sethi <V.Sethi@nxp.com>,
	"devel@edk2.groups.io" <devel@edk2.groups.io>
Subject: Re: [PATCH 04/19] Silicon/NXP: Remove DuartLib and use BaseSerialPortLib16550
Date: Mon, 10 Feb 2020 05:48:47 +0000	[thread overview]
Message-ID: <VI1PR0401MB2496690823259E1779E5E823F1190@VI1PR0401MB2496.eurprd04.prod.outlook.com> (raw)
In-Reply-To: <20200208174620.GG23627@bivouac.eciton.net>



> -----Original Message-----
> From: Leif Lindholm <leif@nuviainc.com>
> Sent: Saturday, February 8, 2020 11:16 PM
> To: Pankaj Bansal <pankaj.bansal@nxp.com>
> Cc: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>; Michael D Kinney
> <michael.d.kinney@intel.com>; Varun Sethi <V.Sethi@nxp.com>;
> devel@edk2.groups.io
> Subject: Re: [PATCH 04/19] Silicon/NXP: Remove DuartLib and use
> BaseSerialPortLib16550
> 
> On Fri, Feb 07, 2020 at 18:13:13 +0530, Pankaj Bansal wrote:
> > UART in LS1043A conforms to ns16550 register set. so we can use the
> > SerialPortLib16550 from MdeModulePkg.
> 
> 1) This patch adds a new library and deletes an existing one - those
>    are two operationsand hence should be two patches.

OK. I can split the patch in two

> 
> 2) That is irrelevant, because if you can use BaseSerialPortLib16550,
>    then use BaseSerialPortLib16550. Copying an existing library in
>    order to make some minor tweaks is not an option.

If you look at the [PATCH 05/19] NXP/BaseSerialPortLib16550: remove SerialPortInitalize functionality
(https://edk2.groups.io/g/devel/message/54011?p=,,,20,0,0,0::Created,,BaseSerialPortLib16550,20,2,0,71046325)

I have removed SerialPortInitalize functionality, which I am guessing would not work for each platform using BaseSerialPortLib16550
Which is why I have forked the BaseSerialPortLib16550 for NXP platforms.

> 
> > We have removed the PCIe specific part from the library and also added
> > the APIs to get the UART clock from SOC lib instead of using the fixed
> > PCD.
> 
> So, what you need to do is update BaseSerialPortLib16550 to be usable
> for you. This library is already used by several ARM platforms that
> don't actually implement PCIe.

Again, I can do that In the similar way we have done for PL011 (https://github.com/tianocore/edk2/commit/cbba5ca104fbc8baa0c613951e833e1a07bb34df)
But as I stated above, this is an unnecessary overhead which increases code size as well as execution time.
Both of which we want to avoid.
That is why we have forked BaseSerialPortLib16550 (and even PL011SerialPortLib for that matter for LX2160A) for NXP platforms.

> 
> > Signed-off-by: Pankaj Bansal <pankaj.bansal@nxp.com>
> > ---
> >  Silicon/NXP/LS1043A/LS1043A.dsc.inc           |   2 +-
> >  .../BaseSerialPortLib16550.c                  | 804 ++++++++++++++++++
> >  .../BaseSerialPortLib16550.inf                |  39 +
> >  .../BaseSerialPortLib16550.uni                |  17 +
> 
> Please don't leave out the --stat and --stat-graph-width when
> following the format-patch instructions at
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.co
> m%2Ftianocore%2Ftianocore.github.io%2Fwiki%2FLaszlo%2527s-unkempt-git-
> guide-for-edk2-contributors-and-
> maintainers&amp;data=02%7C01%7Cpankaj.bansal%40nxp.com%7C696ddff166
> 5a4367502608d7acbed0e8%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C
> 0%7C637167807871085424&amp;sdata=8tHGzseG00MNL1Hc62fFIxKGqcl0quW
> Rq%2Bc9W%2BQRFRU%3D&amp;reserved=0
> 
> /
>     Leif
> 
> >  Silicon/NXP/Library/DUartPortLib/DUart.h      | 122 ---
> >  .../NXP/Library/DUartPortLib/DUartPortLib.c   | 364 --------
> >  .../NXP/Library/DUartPortLib/DUartPortLib.inf |  34 -
> >  7 files changed, 861 insertions(+), 521 deletions(-)
> >  create mode 100644
> Silicon/NXP/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.c
> >  create mode 100644
> Silicon/NXP/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
> >  create mode 100644
> Silicon/NXP/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.uni
> >  delete mode 100644 Silicon/NXP/Library/DUartPortLib/DUart.h
> >  delete mode 100644 Silicon/NXP/Library/DUartPortLib/DUartPortLib.c
> >  delete mode 100644 Silicon/NXP/Library/DUartPortLib/DUartPortLib.inf
> >
> > diff --git a/Silicon/NXP/LS1043A/LS1043A.dsc.inc
> b/Silicon/NXP/LS1043A/LS1043A.dsc.inc
> > index 8790db6ff8..754eff396a 100644
> > --- a/Silicon/NXP/LS1043A/LS1043A.dsc.inc
> > +++ b/Silicon/NXP/LS1043A/LS1043A.dsc.inc
> > @@ -9,7 +9,7 @@
> >
> >  [LibraryClasses.common]
> >    SocLib|Silicon/NXP/Library/SocLib/LS1043aSocLib.inf
> > -  SerialPortLib|Silicon/NXP/Library/DUartPortLib/DUartPortLib.inf
> > +
> SerialPortLib|Silicon/NXP/Library/BaseSerialPortLib16550/BaseSerialPortLib165
> 50.inf
> >
> >
> #################################################################
> ###############
> >  #
> > diff --git
> a/Silicon/NXP/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.c
> b/Silicon/NXP/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.c
> > new file mode 100644
> > index 0000000000..2c5c54ac7d
> > --- /dev/null
> > +++ b/Silicon/NXP/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.c
> > @@ -0,0 +1,804 @@
> > +/** @file
> > +  16550 UART Serial Port library functions
> > +
> > +  (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
> > +  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> > +  Copyright (c) 2018, AMD Incorporated. All rights reserved.<BR>
> > +  Copyright 2020 NXP
> > +
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <Base.h>
> > +#include <Library/SerialPortLib.h>
> > +#include <Library/PcdLib.h>
> > +#include <Library/IoLib.h>
> > +#include <Library/BaseLib.h>
> > +
> > +//
> > +// 16550 UART register offsets and bitfields
> > +//
> > +#define R_UART_RXBUF          0   // LCR_DLAB = 0
> > +#define R_UART_TXBUF          0   // LCR_DLAB = 0
> > +#define R_UART_BAUD_LOW       0   // LCR_DLAB = 1
> > +#define R_UART_BAUD_HIGH      1   // LCR_DLAB = 1
> > +#define R_UART_IER            1   // LCR_DLAB = 0
> > +#define R_UART_FCR            2
> > +#define   B_UART_FCR_FIFOE    BIT0
> > +#define   B_UART_FCR_FIFO64   BIT5
> > +#define R_UART_LCR            3
> > +#define   B_UART_LCR_DLAB     BIT7
> > +#define R_UART_MCR            4
> > +#define   B_UART_MCR_DTRC     BIT0
> > +#define   B_UART_MCR_RTS      BIT1
> > +#define R_UART_LSR            5
> > +#define   B_UART_LSR_RXRDY    BIT0
> > +#define   B_UART_LSR_TXRDY    BIT5
> > +#define   B_UART_LSR_TEMT     BIT6
> > +#define R_UART_MSR            6
> > +#define   B_UART_MSR_CTS      BIT4
> > +#define   B_UART_MSR_DSR      BIT5
> > +#define   B_UART_MSR_RI       BIT6
> > +#define   B_UART_MSR_DCD      BIT7
> > +
> > +extern
> > +UINT64
> > +GetBusFrequency (
> > +  VOID
> > +  );
> > +
> > +/**
> > +  Read an 8-bit 16550 register.  If PcdSerialUseMmio is TRUE, then the value is
> read from
> > +  MMIO space.  If PcdSerialUseMmio is FALSE, then the value is read from I/O
> space.  The
> > +  parameter Offset is added to the base address of the 16550 registers that is
> specified
> > +  by PcdSerialRegisterBase. PcdSerialRegisterAccessWidth specifies the MMIO
> space access
> > +  width and defaults to 8 bit access, and supports 8 or 32 bit access.
> > +
> > +  @param  Base    The base address register of UART device.
> > +  @param  Offset  The offset of the 16550 register to read.
> > +
> > +  @return The value read from the 16550 register.
> > +
> > +**/
> > +UINT8
> > +SerialPortReadRegister (
> > +  UINTN  Base,
> > +  UINTN  Offset
> > +  )
> > +{
> > +  return MmioRead8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride));
> > +}
> > +
> > +/**
> > +  Write an 8-bit 16550 register.  If PcdSerialUseMmio is TRUE, then the value
> is written to
> > +  MMIO space.  If PcdSerialUseMmio is FALSE, then the value is written to I/O
> space.  The
> > +  parameter Offset is added to the base address of the 16550 registers that is
> specified
> > +  by PcdSerialRegisterBase. PcdSerialRegisterAccessWidth specifies the MMIO
> space access
> > +  width and defaults to 8 bit access, and supports 8 or 32 bit access.
> > +
> > +  @param  Base    The base address register of UART device.
> > +  @param  Offset  The offset of the 16550 register to write.
> > +  @param  Value   The value to write to the 16550 register specified by Offset.
> > +
> > +  @return The value written to the 16550 register.
> > +
> > +**/
> > +UINT8
> > +SerialPortWriteRegister (
> > +  UINTN  Base,
> > +  UINTN  Offset,
> > +  UINT8  Value
> > +  )
> > +{
> > +  return MmioWrite8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride),
> Value);
> > +}
> > +
> > +/**
> > +  Retrieve the I/O or MMIO base address register for the PCI UART device.
> > +
> > +  This function assumes Root Bus Numer is Zero, and enables I/O and MMIO
> in PCI UART
> > +  Device if they are not already enabled.
> > +
> > +  @return  The base address register of the UART device.
> > +
> > +**/
> > +UINTN
> > +GetSerialRegisterBase (
> > +  VOID
> > +  )
> > +{
> > +  return (UINTN)PcdGet64 (PcdSerialRegisterBase);
> > +}
> > +
> > +/**
> > +  Return whether the hardware flow control signal allows writing.
> > +
> > +  @param  SerialRegisterBase The base address register of UART device.
> > +
> > +  @retval TRUE  The serial port is writable.
> > +  @retval FALSE The serial port is not writable.
> > +**/
> > +BOOLEAN
> > +SerialPortWritable (
> > +  UINTN  SerialRegisterBase
> > +  )
> > +{
> > +  if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
> > +    if (PcdGetBool (PcdSerialDetectCable)) {
> > +      //
> > +      // Wait for both DSR and CTS to be set
> > +      //   DSR is set if a cable is connected.
> > +      //   CTS is set if it is ok to transmit data
> > +      //
> > +      //   DSR  CTS  Description                               Action
> > +      //   ===  ===  ========================================  ========
> > +      //    0    0   No cable connected.                       Wait
> > +      //    0    1   No cable connected.                       Wait
> > +      //    1    0   Cable connected, but not clear to send.   Wait
> > +      //    1    1   Cable connected, and clear to send.       Transmit
> > +      //
> > +      return (BOOLEAN) ((SerialPortReadRegister (SerialRegisterBase,
> R_UART_MSR) & (B_UART_MSR_DSR | B_UART_MSR_CTS)) ==
> (B_UART_MSR_DSR | B_UART_MSR_CTS));
> > +    } else {
> > +      //
> > +      // Wait for both DSR and CTS to be set OR for DSR to be clear.
> > +      //   DSR is set if a cable is connected.
> > +      //   CTS is set if it is ok to transmit data
> > +      //
> > +      //   DSR  CTS  Description                               Action
> > +      //   ===  ===  ========================================  ========
> > +      //    0    0   No cable connected.                       Transmit
> > +      //    0    1   No cable connected.                       Transmit
> > +      //    1    0   Cable connected, but not clear to send.   Wait
> > +      //    1    1   Cable connected, and clar to send.        Transmit
> > +      //
> > +      return (BOOLEAN) ((SerialPortReadRegister (SerialRegisterBase,
> R_UART_MSR) & (B_UART_MSR_DSR | B_UART_MSR_CTS)) !=
> (B_UART_MSR_DSR));
> > +    }
> > +  }
> > +
> > +  return TRUE;
> > +}
> > +
> > +/**
> > +  Initialize the serial device hardware.
> > +
> > +  If no initialization is required, then return RETURN_SUCCESS.
> > +  If the serial device was successfully initialized, then return
> RETURN_SUCCESS.
> > +  If the serial device could not be initialized, then return
> RETURN_DEVICE_ERROR.
> > +
> > +  @retval RETURN_SUCCESS        The serial device was initialized.
> > +  @retval RETURN_DEVICE_ERROR   The serial device could not be initialized.
> > +
> > +**/
> > +RETURN_STATUS
> > +EFIAPI
> > +SerialPortInitialize (
> > +  VOID
> > +  )
> > +{
> > +  UINTN          SerialRegisterBase;
> > +  UINT32         Divisor;
> > +  UINT32         CurrentDivisor;
> > +  BOOLEAN        Initialized;
> > +  UINT64         SerialClock;
> > +
> > +  //
> > +  // Perform platform specific initialization required to enable use of the
> 16550 device
> > +  // at the location specified by PcdSerialUseMmio and PcdSerialRegisterBase.
> > +  //
> > +  SerialClock = GetBusFrequency ();
> > +  if (SerialClock == 0) {
> > +    return EFI_DEVICE_ERROR;
> > +  }
> > +
> > +  //
> > +  // Calculate divisor for baud generator
> > +  //    Ref_Clk_Rate / Baud_Rate / 16
> > +  //
> > +  Divisor = SerialClock / (PcdGet32 (PcdSerialBaudRate) * 16);
> > +  if ((SerialClock % (PcdGet32 (PcdSerialBaudRate) * 16)) >= PcdGet32
> (PcdSerialBaudRate) * 8) {
> > +    Divisor++;
> > +  }
> > +
> > +  //
> > +  // Get the base address of the serial port in either I/O or MMIO space
> > +  //
> > +  SerialRegisterBase = GetSerialRegisterBase ();
> > +  if (SerialRegisterBase == 0) {
> > +    return RETURN_DEVICE_ERROR;
> > +  }
> > +
> > +  //
> > +  // See if the serial port is already initialized
> > +  //
> > +  Initialized = TRUE;
> > +  if ((SerialPortReadRegister (SerialRegisterBase, R_UART_LCR) & 0x3F) !=
> (PcdGet8 (PcdSerialLineControl) & 0x3F)) {
> > +    Initialized = FALSE;
> > +  }
> > +  SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR,
> (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_LCR) |
> B_UART_LCR_DLAB));
> > +  CurrentDivisor =  SerialPortReadRegister (SerialRegisterBase,
> R_UART_BAUD_HIGH) << 8;
> > +  CurrentDivisor |= (UINT32) SerialPortReadRegister (SerialRegisterBase,
> R_UART_BAUD_LOW);
> > +  SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR,
> (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_LCR) &
> ~B_UART_LCR_DLAB));
> > +  if (CurrentDivisor != Divisor) {
> > +    Initialized = FALSE;
> > +  }
> > +  if (Initialized) {
> > +    return RETURN_SUCCESS;
> > +  }
> > +
> > +  //
> > +  // Wait for the serial port to be ready.
> > +  // Verify that both the transmit FIFO and the shift register are empty.
> > +  //
> > +  while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) &
> (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) != (B_UART_LSR_TEMT |
> B_UART_LSR_TXRDY));
> > +
> > +  //
> > +  // Configure baud rate
> > +  //
> > +  SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR,
> B_UART_LCR_DLAB);
> > +  SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_HIGH, (UINT8)
> (Divisor >> 8));
> > +  SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_LOW, (UINT8)
> (Divisor & 0xff));
> > +
> > +  //
> > +  // Clear DLAB and configure Data Bits, Parity, and Stop Bits.
> > +  // Strip reserved bits from PcdSerialLineControl
> > +  //
> > +  SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(PcdGet8
> (PcdSerialLineControl) & 0x3F));
> > +
> > +  //
> > +  // Enable and reset FIFOs
> > +  // Strip reserved bits from PcdSerialFifoControl
> > +  //
> > +  SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, 0x00);
> > +  SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, (UINT8)(PcdGet8
> (PcdSerialFifoControl) & (B_UART_FCR_FIFOE | B_UART_FCR_FIFO64)));
> > +
> > +  //
> > +  // Set FIFO Polled Mode by clearing IER after setting FCR
> > +  //
> > +  SerialPortWriteRegister (SerialRegisterBase, R_UART_IER, 0x00);
> > +
> > +  //
> > +  // Put Modem Control Register(MCR) into its reset state of 0x00.
> > +  //
> > +  SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, 0x00);
> > +
> > +  return RETURN_SUCCESS;
> > +}
> > +
> > +/**
> > +  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 Buffer is NULL, then ASSERT().
> > +
> > +  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
> > +EFIAPI
> > +SerialPortWrite (
> > +  IN UINT8     *Buffer,
> > +  IN UINTN     NumberOfBytes
> > +  )
> > +{
> > +  UINTN  SerialRegisterBase;
> > +  UINTN  Result;
> > +  UINTN  Index;
> > +  UINTN  FifoSize;
> > +
> > +  if (Buffer == NULL) {
> > +    return 0;
> > +  }
> > +
> > +  SerialRegisterBase = GetSerialRegisterBase ();
> > +  if (SerialRegisterBase ==0) {
> > +    return 0;
> > +  }
> > +
> > +  if (NumberOfBytes == 0) {
> > +    //
> > +    // Flush the hardware
> > +    //
> > +
> > +    //
> > +    // Wait for both the transmit FIFO and shift register empty.
> > +    //
> > +    while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) &
> (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) != (B_UART_LSR_TEMT |
> B_UART_LSR_TXRDY));
> > +
> > +    //
> > +    // Wait for the hardware flow control signal
> > +    //
> > +    while (!SerialPortWritable (SerialRegisterBase));
> > +    return 0;
> > +  }
> > +
> > +  //
> > +  // Compute the maximum size of the Tx FIFO
> > +  //
> > +  FifoSize = 1;
> > +  if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFOE) != 0) {
> > +    if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFO64) == 0) {
> > +      FifoSize = 16;
> > +    } else {
> > +      FifoSize = PcdGet32 (PcdSerialExtendedTxFifoSize);
> > +    }
> > +  }
> > +
> > +  Result = NumberOfBytes;
> > +  while (NumberOfBytes != 0) {
> > +    //
> > +    // Wait for the serial port to be ready, to make sure both the transmit FIFO
> > +    // and shift register empty.
> > +    //
> > +    while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) &
> (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) != (B_UART_LSR_TEMT |
> B_UART_LSR_TXRDY));
> > +
> > +    //
> > +    // Fill then entire Tx FIFO
> > +    //
> > +    for (Index = 0; Index < FifoSize && NumberOfBytes != 0; Index++,
> NumberOfBytes--, Buffer++) {
> > +      //
> > +      // Wait for the hardware flow control signal
> > +      //
> > +      while (!SerialPortWritable (SerialRegisterBase));
> > +
> > +      //
> > +      // Write byte to the transmit buffer.
> > +      //
> > +      SerialPortWriteRegister (SerialRegisterBase, R_UART_TXBUF, *Buffer);
> > +    }
> > +  }
> > +  return Result;
> > +}
> > +
> > +/**
> > +  Reads data from a serial device into a buffer.
> > +
> > +  @param  Buffer           Pointer to the data buffer to store the data read from
> the serial device.
> > +  @param  NumberOfBytes    Number of bytes to read from the serial device.
> > +
> > +  @retval 0                NumberOfBytes is 0.
> > +  @retval >0               The number of bytes read from the serial device.
> > +                           If this value is less than NumberOfBytes, then the read
> operation failed.
> > +
> > +**/
> > +UINTN
> > +EFIAPI
> > +SerialPortRead (
> > +  OUT UINT8     *Buffer,
> > +  IN  UINTN     NumberOfBytes
> > +  )
> > +{
> > +  UINTN  SerialRegisterBase;
> > +  UINTN  Result;
> > +  UINT8  Mcr;
> > +
> > +  if (NULL == Buffer) {
> > +    return 0;
> > +  }
> > +
> > +  SerialRegisterBase = GetSerialRegisterBase ();
> > +  if (SerialRegisterBase ==0) {
> > +    return 0;
> > +  }
> > +
> > +  Mcr = (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_MCR) &
> ~B_UART_MCR_RTS);
> > +
> > +  for (Result = 0; NumberOfBytes-- != 0; Result++, Buffer++) {
> > +    //
> > +    // Wait for the serial port to have some data.
> > +    //
> > +    while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) &
> B_UART_LSR_RXRDY) == 0) {
> > +      if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
> > +        //
> > +        // Set RTS to let the peer send some data
> > +        //
> > +        SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, (UINT8)(Mcr
> | B_UART_MCR_RTS));
> > +      }
> > +    }
> > +    if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
> > +      //
> > +      // Clear RTS to prevent peer from sending data
> > +      //
> > +      SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, Mcr);
> > +    }
> > +
> > +    //
> > +    // Read byte from the receive buffer.
> > +    //
> > +    *Buffer = SerialPortReadRegister (SerialRegisterBase, R_UART_RXBUF);
> > +  }
> > +
> > +  return Result;
> > +}
> > +
> > +
> > +/**
> > +  Polls a serial device to see if there is any data waiting to be read.
> > +
> > +  Polls aserial device to see if there is any data waiting to be read.
> > +  If there is data waiting to be read from the serial device, then TRUE is
> returned.
> > +  If there is no data waiting to be read from the serial device, then FALSE is
> returned.
> > +
> > +  @retval TRUE             Data is waiting to be read from the serial device.
> > +  @retval FALSE            There is no data waiting to be read from the serial
> device.
> > +
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +SerialPortPoll (
> > +  VOID
> > +  )
> > +{
> > +  UINTN  SerialRegisterBase;
> > +
> > +  SerialRegisterBase = GetSerialRegisterBase ();
> > +  if (SerialRegisterBase ==0) {
> > +    return FALSE;
> > +  }
> > +
> > +  //
> > +  // Read the serial port status
> > +  //
> > +  if ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) &
> B_UART_LSR_RXRDY) != 0) {
> > +    if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
> > +      //
> > +      // Clear RTS to prevent peer from sending data
> > +      //
> > +      SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR,
> (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_MCR) &
> ~B_UART_MCR_RTS));
> > +    }
> > +    return TRUE;
> > +  }
> > +
> > +  if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
> > +    //
> > +    // Set RTS to let the peer send some data
> > +    //
> > +    SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR,
> (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_MCR) |
> B_UART_MCR_RTS));
> > +  }
> > +
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Sets the control bits on a serial device.
> > +
> > +  @param Control                Sets the bits of Control that are settable.
> > +
> > +  @retval RETURN_SUCCESS        The new control bits were set on the serial
> device.
> > +  @retval RETURN_UNSUPPORTED    The serial device does not support this
> operation.
> > +  @retval RETURN_DEVICE_ERROR   The serial device is not functioning
> correctly.
> > +
> > +**/
> > +RETURN_STATUS
> > +EFIAPI
> > +SerialPortSetControl (
> > +  IN UINT32 Control
> > +  )
> > +{
> > +  UINTN SerialRegisterBase;
> > +  UINT8 Mcr;
> > +
> > +  //
> > +  // First determine the parameter is invalid.
> > +  //
> > +  if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND |
> EFI_SERIAL_DATA_TERMINAL_READY |
> > +                    EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) != 0) {
> > +    return RETURN_UNSUPPORTED;
> > +  }
> > +
> > +  SerialRegisterBase = GetSerialRegisterBase ();
> > +  if (SerialRegisterBase ==0) {
> > +    return RETURN_UNSUPPORTED;
> > +  }
> > +
> > +  //
> > +  // Read the Modem Control Register.
> > +  //
> > +  Mcr = SerialPortReadRegister (SerialRegisterBase, R_UART_MCR);
> > +  Mcr &= (~(B_UART_MCR_DTRC | B_UART_MCR_RTS));
> > +
> > +  if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) ==
> EFI_SERIAL_DATA_TERMINAL_READY) {
> > +    Mcr |= B_UART_MCR_DTRC;
> > +  }
> > +
> > +  if ((Control & EFI_SERIAL_REQUEST_TO_SEND) ==
> EFI_SERIAL_REQUEST_TO_SEND) {
> > +    Mcr |= B_UART_MCR_RTS;
> > +  }
> > +
> > +  //
> > +  // Write the Modem Control Register.
> > +  //
> > +  SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, Mcr);
> > +
> > +  return RETURN_SUCCESS;
> > +}
> > +
> > +/**
> > +  Retrieve the status of the control bits on a serial device.
> > +
> > +  @param Control                A pointer to return the current control signals from
> the serial device.
> > +
> > +  @retval RETURN_SUCCESS        The control bits were read from the serial
> device.
> > +  @retval RETURN_UNSUPPORTED    The serial device does not support this
> operation.
> > +  @retval RETURN_DEVICE_ERROR   The serial device is not functioning
> correctly.
> > +
> > +**/
> > +RETURN_STATUS
> > +EFIAPI
> > +SerialPortGetControl (
> > +  OUT UINT32 *Control
> > +  )
> > +{
> > +  UINTN SerialRegisterBase;
> > +  UINT8 Msr;
> > +  UINT8 Mcr;
> > +  UINT8 Lsr;
> > +
> > +  SerialRegisterBase = GetSerialRegisterBase ();
> > +  if (SerialRegisterBase ==0) {
> > +    return RETURN_UNSUPPORTED;
> > +  }
> > +
> > +  *Control = 0;
> > +
> > +  //
> > +  // Read the Modem Status Register.
> > +  //
> > +  Msr = SerialPortReadRegister (SerialRegisterBase, R_UART_MSR);
> > +
> > +  if ((Msr & B_UART_MSR_CTS) == B_UART_MSR_CTS) {
> > +    *Control |= EFI_SERIAL_CLEAR_TO_SEND;
> > +  }
> > +
> > +  if ((Msr & B_UART_MSR_DSR) == B_UART_MSR_DSR) {
> > +    *Control |= EFI_SERIAL_DATA_SET_READY;
> > +  }
> > +
> > +  if ((Msr & B_UART_MSR_RI) == B_UART_MSR_RI) {
> > +    *Control |= EFI_SERIAL_RING_INDICATE;
> > +  }
> > +
> > +  if ((Msr & B_UART_MSR_DCD) == B_UART_MSR_DCD) {
> > +    *Control |= EFI_SERIAL_CARRIER_DETECT;
> > +  }
> > +
> > +  //
> > +  // Read the Modem Control Register.
> > +  //
> > +  Mcr = SerialPortReadRegister (SerialRegisterBase, R_UART_MCR);
> > +
> > +  if ((Mcr & B_UART_MCR_DTRC) == B_UART_MCR_DTRC) {
> > +    *Control |= EFI_SERIAL_DATA_TERMINAL_READY;
> > +  }
> > +
> > +  if ((Mcr & B_UART_MCR_RTS) == B_UART_MCR_RTS) {
> > +    *Control |= EFI_SERIAL_REQUEST_TO_SEND;
> > +  }
> > +
> > +  if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
> > +    *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
> > +  }
> > +
> > +  //
> > +  // Read the Line Status Register.
> > +  //
> > +  Lsr = SerialPortReadRegister (SerialRegisterBase, R_UART_LSR);
> > +
> > +  if ((Lsr & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) ==
> (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) {
> > +    *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
> > +  }
> > +
> > +  if ((Lsr & B_UART_LSR_RXRDY) == 0) {
> > +    *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
> > +  }
> > +
> > +  return RETURN_SUCCESS;
> > +}
> > +
> > +/**
> > +  Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,
> > +  data bits, and stop bits on a serial device.
> > +
> > +  @param BaudRate           The requested baud rate. A BaudRate value of 0
> will use the
> > +                            device's default interface speed.
> > +                            On output, the value actually set.
> > +  @param ReveiveFifoDepth   The requested depth of the FIFO on the receive
> side of the
> > +                            serial interface. A ReceiveFifoDepth value of 0 will use
> > +                            the device's default FIFO depth.
> > +                            On output, the value actually set.
> > +  @param Timeout            The requested time out for a single character in
> microseconds.
> > +                            This timeout applies to both the transmit and receive side of
> the
> > +                            interface. A Timeout value of 0 will use the device's default
> time
> > +                            out value.
> > +                            On output, the value actually set.
> > +  @param Parity             The type of parity to use on this serial device. A Parity
> value of
> > +                            DefaultParity will use the device's default parity value.
> > +                            On output, the value actually set.
> > +  @param DataBits           The number of data bits to use on the serial device.
> A DataBits
> > +                            vaule of 0 will use the device's default data bit setting.
> > +                            On output, the value actually set.
> > +  @param StopBits           The number of stop bits to use on this serial device.
> A StopBits
> > +                            value of DefaultStopBits will use the device's default number
> of
> > +                            stop bits.
> > +                            On output, the value actually set.
> > +
> > +  @retval RETURN_SUCCESS            The new attributes were set on the serial
> device.
> > +  @retval RETURN_UNSUPPORTED        The serial device does not support this
> operation.
> > +  @retval RETURN_INVALID_PARAMETER  One or more of the attributes has
> an unsupported value.
> > +  @retval RETURN_DEVICE_ERROR       The serial device is not functioning
> correctly.
> > +
> > +**/
> > +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
> > +  )
> > +{
> > +  UINTN     SerialRegisterBase;
> > +  UINT32    SerialBaudRate;
> > +  UINTN     Divisor;
> > +  UINT8     Lcr;
> > +  UINT8     LcrData;
> > +  UINT8     LcrParity;
> > +  UINT8     LcrStop;
> > +  UINT64    SerialClock;
> > +
> > +  SerialRegisterBase = GetSerialRegisterBase ();
> > +  if (SerialRegisterBase ==0) {
> > +    return RETURN_UNSUPPORTED;
> > +  }
> > +
> > +  SerialClock = GetBusFrequency ();
> > +  if (SerialClock == 0) {
> > +    return EFI_DEVICE_ERROR;
> > +  }
> > +
> > +  //
> > +  // Check for default settings and fill in actual values.
> > +  //
> > +  if (*BaudRate == 0) {
> > +    *BaudRate = PcdGet32 (PcdSerialBaudRate);
> > +  }
> > +  SerialBaudRate = (UINT32) *BaudRate;
> > +
> > +  if (*DataBits == 0) {
> > +    LcrData = (UINT8) (PcdGet8 (PcdSerialLineControl) & 0x3);
> > +    *DataBits = LcrData + 5;
> > +  } else {
> > +    if ((*DataBits < 5) || (*DataBits > 8)) {
> > +      return RETURN_INVALID_PARAMETER;
> > +    }
> > +    //
> > +    // Map 5..8 to 0..3
> > +    //
> > +    LcrData = (UINT8) (*DataBits - (UINT8) 5);
> > +  }
> > +
> > +  if (*Parity == DefaultParity) {
> > +    LcrParity = (UINT8) ((PcdGet8 (PcdSerialLineControl) >> 3) & 0x7);
> > +    switch (LcrParity) {
> > +      case 0:
> > +        *Parity = NoParity;
> > +        break;
> > +
> > +      case 3:
> > +        *Parity = EvenParity;
> > +        break;
> > +
> > +      case 1:
> > +        *Parity = OddParity;
> > +        break;
> > +
> > +      case 7:
> > +        *Parity = SpaceParity;
> > +        break;
> > +
> > +      case 5:
> > +        *Parity = MarkParity;
> > +        break;
> > +
> > +      default:
> > +        break;
> > +    }
> > +  } else {
> > +    switch (*Parity) {
> > +      case NoParity:
> > +        LcrParity = 0;
> > +        break;
> > +
> > +      case EvenParity:
> > +        LcrParity = 3;
> > +        break;
> > +
> > +      case OddParity:
> > +        LcrParity = 1;
> > +        break;
> > +
> > +      case SpaceParity:
> > +        LcrParity = 7;
> > +        break;
> > +
> > +      case MarkParity:
> > +        LcrParity = 5;
> > +        break;
> > +
> > +      default:
> > +        return RETURN_INVALID_PARAMETER;
> > +    }
> > +  }
> > +
> > +  if (*StopBits == DefaultStopBits) {
> > +    LcrStop = (UINT8) ((PcdGet8 (PcdSerialLineControl) >> 2) & 0x1);
> > +    switch (LcrStop) {
> > +      case 0:
> > +        *StopBits = OneStopBit;
> > +        break;
> > +
> > +      case 1:
> > +        if (*DataBits == 5) {
> > +          *StopBits = OneFiveStopBits;
> > +        } else {
> > +          *StopBits = TwoStopBits;
> > +        }
> > +        break;
> > +
> > +      default:
> > +        break;
> > +    }
> > +  } else {
> > +    switch (*StopBits) {
> > +      case OneStopBit:
> > +        LcrStop = 0;
> > +        break;
> > +
> > +      case OneFiveStopBits:
> > +      case TwoStopBits:
> > +        LcrStop = 1;
> > +        break;
> > +
> > +      default:
> > +        return RETURN_INVALID_PARAMETER;
> > +    }
> > +  }
> > +
> > +  //
> > +  // Calculate divisor for baud generator
> > +  //    Ref_Clk_Rate / Baud_Rate / 16
> > +  //
> > +  Divisor = SerialClock / (SerialBaudRate * 16);
> > +  if ((SerialClock % (SerialBaudRate * 16)) >= SerialBaudRate * 8) {
> > +    Divisor++;
> > +  }
> > +
> > +  //
> > +  // Configure baud rate
> > +  //
> > +  SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR,
> B_UART_LCR_DLAB);
> > +  SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_HIGH, (UINT8)
> (Divisor >> 8));
> > +  SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_LOW, (UINT8)
> (Divisor & 0xff));
> > +
> > +  //
> > +  // Clear DLAB and configure Data Bits, Parity, and Stop Bits.
> > +  // Strip reserved bits from line control value
> > +  //
> > +  Lcr = (UINT8) ((LcrParity << 3) | (LcrStop << 2) | LcrData);
> > +  SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8) (Lcr &
> 0x3F));
> > +
> > +  return RETURN_SUCCESS;
> > +}
> > +
> > diff --git
> a/Silicon/NXP/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
> b/Silicon/NXP/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
> > new file mode 100644
> > index 0000000000..45ae9dc0af
> > --- /dev/null
> > +++ b/Silicon/NXP/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
> > @@ -0,0 +1,39 @@
> > +## @file
> > +#  SerialPortLib instance for 16550 UART.
> > +#
> > +#  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> > +#  Copyright 2020 NXP
> > +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +##
> > +
> > +[Defines]
> > +  INF_VERSION                    = 0x00010005
> > +  BASE_NAME                      = BaseSerialPortLib16550
> > +  MODULE_UNI_FILE                = BaseSerialPortLib16550.uni
> > +  FILE_GUID                      = 9E7C00CF-355A-4d4e-BF60-0428CFF95540
> > +  MODULE_TYPE                    = BASE
> > +  VERSION_STRING                 = 1.1
> > +  LIBRARY_CLASS                  = SerialPortLib
> > +
> > +[Packages]
> > +  MdePkg/MdePkg.dec
> > +  MdeModulePkg/MdeModulePkg.dec
> > +
> > +[LibraryClasses]
> > +  PcdLib
> > +  IoLib
> > +  SocLib
> > +
> > +[Sources]
> > +  BaseSerialPortLib16550.c
> > +
> > +[FixedPcd]
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseHardwareFlowControl  ##
> CONSUMES
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialDetectCable             ##
> SOMETIMES_CONSUMES
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase            ##
> CONSUMES
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialBaudRate                ##
> CONSUMES
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialLineControl             ##
> CONSUMES
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialFifoControl             ##
> CONSUMES
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialExtendedTxFifoSize      ##
> CONSUMES
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterStride          ##
> CONSUMES
> > diff --git
> a/Silicon/NXP/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.uni
> b/Silicon/NXP/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.uni
> > new file mode 100644
> > index 0000000000..2fefe85cf8
> > --- /dev/null
> > +++ b/Silicon/NXP/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.uni
> > @@ -0,0 +1,17 @@
> > +// /** @file
> > +// SerialPortLib instance for 16550 UART.
> > +//
> > +// SerialPortLib instance for 16550 UART.
> > +//
> > +// Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> > +// Copyright 2020 NXP
> > +//
> > +// SPDX-License-Identifier: BSD-2-Clause-Patent
> > +//
> > +// **/
> > +
> > +
> > +#string STR_MODULE_ABSTRACT             #language en-US "SerialPortLib
> instance for 16550 UART"
> > +
> > +#string STR_MODULE_DESCRIPTION          #language en-US "SerialPortLib
> instance for 16550 UART."
> > +
> > diff --git a/Silicon/NXP/Library/DUartPortLib/DUart.h
> b/Silicon/NXP/Library/DUartPortLib/DUart.h
> > deleted file mode 100644
> > index c71e2ce55d..0000000000
> > --- a/Silicon/NXP/Library/DUartPortLib/DUart.h
> > +++ /dev/null
> > @@ -1,122 +0,0 @@
> > -/** DUart.h
> > -*  Header defining the DUART constants (Base addresses, sizes, flags)
> > -*
> > -*  Based on Serial I/O Port library headers available in PL011Uart.h
> > -*
> > -*  Copyright (c) 2011-2012, ARM Limited. All rights reserved.
> > -*  Copyright (c) 2016, Freescale Semiconductor, Inc. All rights reserved.
> > -*  Copyright 2017 NXP
> > -*
> > -*  SPDX-License-Identifier: BSD-2-Clause-Patent
> > -*
> > -**/
> > -
> > -#ifndef DUART_H_
> > -#define DUART_H_
> > -
> > -// FIFO Control Register
> > -#define DUART_FCR_FIFO_EN          0x01 /* Fifo enable */
> > -#define DUART_FCR_CLEAR_RCVR       0x02 /* Clear the RCVR FIFO */
> > -#define DUART_FCR_CLEAR_XMIT       0x04 /* Clear the XMIT FIFO */
> > -#define DUART_FCR_DMA_SELECT       0x08 /* For DMA applications */
> > -#define DUART_FCR_TRIGGER_MASK     0xC0 /* Mask for the FIFO trigger
> range */
> > -#define DUART_FCR_TRIGGER_1        0x00 /* Mask for trigger set at 1 */
> > -#define DUART_FCR_TRIGGER_4        0x40 /* Mask for trigger set at 4 */
> > -#define DUART_FCR_TRIGGER_8        0x80 /* Mask for trigger set at 8 */
> > -#define DUART_FCR_TRIGGER_14       0xC0 /* Mask for trigger set at 14 */
> > -#define DUART_FCR_RXSR             0x02 /* Receiver soft reset */
> > -#define DUART_FCR_TXSR             0x04 /* Transmitter soft reset */
> > -
> > -// Modem Control Register
> > -#define DUART_MCR_DTR              0x01 /* Reserved  */
> > -#define DUART_MCR_RTS              0x02 /* RTS   */
> > -#define DUART_MCR_OUT1             0x04 /* Reserved */
> > -#define DUART_MCR_OUT2             0x08 /* Reserved */
> > -#define DUART_MCR_LOOP             0x10 /* Enable loopback test mode */
> > -#define DUART_MCR_AFE              0x20 /* AFE (Auto Flow Control) */
> > -#define DUART_MCR_DMA_EN           0x04
> > -#define DUART_MCR_TX_DFR           0x08
> > -
> > -// Line Control Register
> > -/*
> > -* Note: if the word length is 5 bits (DUART_LCR_WLEN5), then setting
> > -* DUART_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
> > -*/
> > -#define DUART_LCR_WLS_MSK          0x03 /* character length select mask */
> > -#define DUART_LCR_WLS_5            0x00 /* 5 bit character length */
> > -#define DUART_LCR_WLS_6            0x01 /* 6 bit character length */
> > -#define DUART_LCR_WLS_7            0x02 /* 7 bit character length */
> > -#define DUART_LCR_WLS_8            0x03 /* 8 bit character length */
> > -#define DUART_LCR_STB              0x04 /* # stop Bits, off=1, on=1.5 or 2) */
> > -#define DUART_LCR_PEN              0x08 /* Parity eneble */
> > -#define DUART_LCR_EPS              0x10 /* Even Parity Select */
> > -#define DUART_LCR_STKP             0x20 /* Stick Parity */
> > -#define DUART_LCR_SBRK             0x40 /* Set Break */
> > -#define DUART_LCR_BKSE             0x80 /* Bank select enable */
> > -#define DUART_LCR_DLAB             0x80 /* Divisor latch access bit */
> > -
> > -// Line Status Register
> > -#define DUART_LSR_DR               0x01 /* Data ready */
> > -#define DUART_LSR_OE               0x02 /* Overrun */
> > -#define DUART_LSR_PE               0x04 /* Parity error */
> > -#define DUART_LSR_FE               0x08 /* Framing error */
> > -#define DUART_LSR_BI               0x10 /* Break */
> > -#define DUART_LSR_THRE             0x20 /* Xmit holding register empty */
> > -#define DUART_LSR_TEMT             0x40 /* Xmitter empty */
> > -#define DUART_LSR_ERR              0x80 /* Error */
> > -
> > -// Modem Status Register
> > -#define DUART_MSR_DCTS             0x01 /* Delta CTS */
> > -#define DUART_MSR_DDSR             0x02 /* Reserved */
> > -#define DUART_MSR_TERI             0x04 /* Reserved */
> > -#define DUART_MSR_DDCD             0x08 /* Reserved */
> > -#define DUART_MSR_CTS              0x10 /* Clear to Send */
> > -#define DUART_MSR_DSR              0x20 /* Reserved */
> > -#define DUART_MSR_RI               0x40 /* Reserved */
> > -#define DUART_MSR_DCD              0x80 /* Reserved */
> > -
> > -// Interrupt Identification Register
> > -#define DUART_IIR_NO_INT           0x01 /* No interrupts pending */
> > -#define DUART_IIR_ID               0x06 /* Mask for the interrupt ID */
> > -#define DUART_IIR_MSI              0x00 /* Modem status interrupt */
> > -#define DUART_IIR_THRI             0x02 /* Transmitter holding register empty */
> > -#define DUART_IIR_RDI              0x04 /* Receiver data interrupt */
> > -#define DUART_IIR_RLSI             0x06 /* Receiver line status interrupt */
> > -
> > -//  Interrupt Enable Register
> > -#define DUART_IER_MSI              0x08 /* Enable Modem status interrupt */
> > -#define DUART_IER_RLSI             0x04 /* Enable receiver line status interrupt
> */
> > -#define DUART_IER_THRI             0x02 /* Enable Transmitter holding register
> int. */
> > -#define DUART_IER_RDI              0x01 /* Enable receiver data interrupt */
> > -
> > -// LCR defaults
> > -#define DUART_LCR_8N1              0x03
> > -#define DUART_LCRVAL               DUART_LCR_8N1          /* 8 data, 1 stop, no
> parity */
> > -#define DUART_MCRVAL               (DUART_MCR_DTR | \
> > -                                   DUART_MCR_RTS)         /* RTS/DTR */
> > -#define DUART_FCRVAL               (DUART_FCR_FIFO_EN | \
> > -                                   DUART_FCR_RXSR |    \
> > -                                   DUART_FCR_TXSR)        /* Clear & enable FIFOs */
> > -
> > -#define URBR         0x0
> > -#define UTHR         0x0
> > -#define UDLB         0x0
> > -#define UDMB         0x1
> > -#define UIER         0x1
> > -#define UIIR         0x2
> > -#define UFCR         0x2
> > -#define UAFR         0x2
> > -#define ULCR         0x3
> > -#define UMCR         0x4
> > -#define ULSR         0x5
> > -#define UMSR         0x6
> > -#define USCR         0x7
> > -#define UDSR         0x10
> > -
> > -extern
> > -UINT64
> > -GetBusFrequency (
> > -  VOID
> > -  );
> > -
> > -#endif /* DUART_H_ */
> > diff --git a/Silicon/NXP/Library/DUartPortLib/DUartPortLib.c
> b/Silicon/NXP/Library/DUartPortLib/DUartPortLib.c
> > deleted file mode 100644
> > index c3c738d3cc..0000000000
> > --- a/Silicon/NXP/Library/DUartPortLib/DUartPortLib.c
> > +++ /dev/null
> > @@ -1,364 +0,0 @@
> > -/** DuartPortLib.c
> > -  DUART (NS16550) library functions
> > -
> > -  Based on Serial I/O Port library functions available in PL011SerialPortLib.c
> > -
> > -  Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
> > -  Copyright (c) 2012 - 2013, ARM Ltd. All rights reserved.<BR>
> > -  Copyright (c) 2016, Freescale Semiconductor, Inc. All rights reserved.
> > -  Copyright 2017 NXP
> > -
> > -  SPDX-License-Identifier: BSD-2-Clause-Patent
> > -
> > -**/
> > -
> > -#include <Base.h>
> > -#include <Library/IoLib.h>
> > -#include <Library/PcdLib.h>
> > -#include <Library/SerialPortLib.h>
> > -
> > -#include "DUart.h"
> > -
> > -STATIC CONST UINT32 mInvalidControlBits =
> (EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | \
> > -                                           EFI_SERIAL_DATA_TERMINAL_READY);
> > -
> > -/**
> > -  Assert or deassert the control signals on a serial port.
> > -  The following control signals are set according their bit settings :
> > -  . Request to Send
> > -  . Data Terminal Ready
> > -
> > -  @param[in]  Control     The following bits are taken into account :
> > -                          . EFI_SERIAL_REQUEST_TO_SEND : assert/deassert the
> > -                            "Request To Send" control signal if this bit is
> > -                            equal to one/zero.
> > -                          . EFI_SERIAL_DATA_TERMINAL_READY : assert/deassert
> > -                            the "Data Terminal Ready" control signal if this
> > -                            bit is equal to one/zero.
> > -                          . EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE : enable/disable
> > -                            the hardware loopback if this bit is equal to
> > -                            one/zero.
> > -                          . EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE : not supported.
> > -                          . EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE : enable/
> > -                            disable the hardware flow control based on CTS (Clear
> > -                            To Send) and RTS (Ready To Send) control signals.
> > -
> > -  @retval  EFI_SUCCESS      The new control bits were set on the device.
> > -  @retval  EFI_UNSUPPORTED  The device does not support this operation.
> > -
> > -**/
> > -EFI_STATUS
> > -EFIAPI
> > -SerialPortSetControl (
> > -  IN  UINT32  Control
> > -  )
> > -{
> > -  UINT32  McrBits;
> > -  UINTN   UartBase;
> > -
> > -  UartBase = (UINTN)PcdGet64 (PcdSerialRegisterBase);
> > -
> > -  if (Control & (mInvalidControlBits)) {
> > -    return EFI_UNSUPPORTED;
> > -  }
> > -
> > -  McrBits = MmioRead8 (UartBase + UMCR);
> > -
> > -  if (Control & EFI_SERIAL_REQUEST_TO_SEND) {
> > -    McrBits |= DUART_MCR_RTS;
> > -  } else {
> > -    McrBits &= ~DUART_MCR_RTS;
> > -  }
> > -
> > -  if (Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) {
> > -    McrBits |= DUART_MCR_LOOP;
> > -  } else {
> > -    McrBits &= ~DUART_MCR_LOOP;
> > -  }
> > -
> > -  if (Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {
> > -    McrBits |= DUART_MCR_AFE;
> > -  } else {
> > -    McrBits &= ~DUART_MCR_AFE;
> > -  }
> > -
> > -  MmioWrite32 (UartBase + UMCR, McrBits);
> > -
> > -  return EFI_SUCCESS;
> > -}
> > -
> > -/**
> > -  Retrieve the status of the control bits on a serial device.
> > -
> > -  @param[out]  Control     Status of the control bits on a serial device :
> > -
> > -                         . EFI_SERIAL_DATA_CLEAR_TO_SEND,
> > -                           EFI_SERIAL_DATA_SET_READY,
> > -                           EFI_SERIAL_RING_INDICATE,
> > -                           EFI_SERIAL_CARRIER_DETECT,
> > -                           EFI_SERIAL_REQUEST_TO_SEND,
> > -                           EFI_SERIAL_DATA_TERMINAL_READY
> > -                           are all related to the DTE (Data Terminal Equipment)
> > -                           and DCE (Data Communication Equipment) modes of
> > -                           operation of the serial device.
> > -                         . EFI_SERIAL_INPUT_BUFFER_EMPTY : equal to one if the
> > -                           receive buffer is empty, 0 otherwise.
> > -                         . EFI_SERIAL_OUTPUT_BUFFER_EMPTY : equal to one if the
> > -                           transmit buffer is empty, 0 otherwise.
> > -                         . EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE : equal to one if
> > -                           the hardware loopback is enabled (the ouput feeds the
> > -                           receive buffer), 0 otherwise.
> > -                         . EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE : equal to one if
> > -                           a loopback is accomplished by software, 0 otherwise.
> > -                         . EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE : equal to
> > -                           one if the hardware flow control based on CTS (Clear
> > -                           To Send) and RTS (Ready To Send) control signals is
> > -                           enabled, 0 otherwise.
> > -
> > -  @retval EFI_SUCCESS      The control bits were read from the serial device.
> > -
> > -**/
> > -EFI_STATUS
> > -EFIAPI
> > -SerialPortGetControl (
> > -  OUT  UINT32   *Control
> > -  )
> > -{
> > -  UINT32        MsrRegister;
> > -  UINT32        McrRegister;
> > -  UINT32        LsrRegister;
> > -  UINTN         UartBase;
> > -
> > -  UartBase = (UINTN)PcdGet64 (PcdSerialRegisterBase);
> > -
> > -  MsrRegister = MmioRead8 (UartBase + UMSR);
> > -  McrRegister = MmioRead8 (UartBase + UMCR);
> > -  LsrRegister = MmioRead8 (UartBase + ULSR);
> > -
> > -  *Control = 0;
> > -
> > -  if ((MsrRegister & DUART_MSR_CTS) == DUART_MSR_CTS) {
> > -    *Control |= EFI_SERIAL_CLEAR_TO_SEND;
> > -  }
> > -
> > -  if ((McrRegister & DUART_MCR_RTS) == DUART_MCR_RTS) {
> > -    *Control |= EFI_SERIAL_REQUEST_TO_SEND;
> > -  }
> > -
> > -  if ((LsrRegister & DUART_LSR_TEMT) == DUART_LSR_TEMT) {
> > -    *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
> > -  }
> > -
> > -  if ((McrRegister & DUART_MCR_AFE) == DUART_MCR_AFE) {
> > -    *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
> > -  }
> > -
> > -  if ((McrRegister & DUART_MCR_LOOP) == DUART_MCR_LOOP) {
> > -    *Control |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;
> > -  }
> > -
> > -  return EFI_SUCCESS;
> > -}
> > -
> > -/*
> > - * Return Baud divisor on basis of Baudrate
> > - */
> > -UINT32
> > -CalculateBaudDivisor (
> > -  IN UINT64 BaudRate
> > -  )
> > -{
> > -  UINTN DUartClk;
> > -  UINTN FreqSystemBus;
> > -
> > -  FreqSystemBus = GetBusFrequency ();
> > -  DUartClk = FreqSystemBus/PcdGet32(PcdPlatformFreqDiv);
> > -
> > -  return ((DUartClk)/(BaudRate * 16));
> > -}
> > -
> > -/*
> > -   Initialise the serial port to the specified settings.
> > -   All unspecified settings will be set to the default values.
> > -
> > -   @return    Always return EFI_SUCCESS or EFI_INVALID_PARAMETER.
> > -
> > - **/
> > -VOID
> > -EFIAPI
> > -DuartInitializePort (
> > -  IN  UINT64  BaudRate
> > -  )
> > -{
> > -  UINTN   UartBase;
> > -  UINT32  BaudDivisor;
> > -
> > -  UartBase = (UINTN)PcdGet64 (PcdSerialRegisterBase);
> > -  BaudDivisor = CalculateBaudDivisor (BaudRate);
> > -
> > -
> > -  while (!(MmioRead8 (UartBase + ULSR) & DUART_LSR_TEMT));
> > -
> > -  //
> > -  // Enable and assert interrupt when new data is available on
> > -  // external device,
> > -  // setup data format, setup baud divisor
> > -  //
> > -  MmioWrite8 (UartBase + UIER, 0x1);
> > -  MmioWrite8 (UartBase + ULCR, DUART_LCR_BKSE | DUART_LCRVAL);
> > -  MmioWrite8 (UartBase + UDLB, 0);
> > -  MmioWrite8 (UartBase + UDMB, 0);
> > -  MmioWrite8 (UartBase + ULCR, DUART_LCRVAL);
> > -  MmioWrite8 (UartBase + UMCR, DUART_MCRVAL);
> > -  MmioWrite8 (UartBase + UFCR, DUART_FCRVAL);
> > -  MmioWrite8 (UartBase + ULCR, DUART_LCR_BKSE | DUART_LCRVAL);
> > -  MmioWrite8 (UartBase + UDLB, BaudDivisor & 0xff);
> > -  MmioWrite8 (UartBase + UDMB, (BaudDivisor >> 8) & 0xff);
> > -  MmioWrite8 (UartBase + ULCR, DUART_LCRVAL);
> > -
> > -  return;
> > -}
> > -
> > -/**
> > -  Programmed hardware of Serial port.
> > -
> > -  @return    Always return EFI_SUCCESS.
> > -
> > -**/
> > -EFI_STATUS
> > -EFIAPI
> > -SerialPortInitialize (
> > -  VOID
> > -  )
> > -{
> > -  UINT64  BaudRate;
> > -  BaudRate = (UINTN)PcdGet64 (PcdUartDefaultBaudRate);
> > -
> > -
> > -  DuartInitializePort (BaudRate);
> > -
> > -  return EFI_SUCCESS;
> > -}
> > -
> > -/**
> > -  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
> > -  )
> > -{
> > -  UINT8         *Final;
> > -  UINTN         UartBase;
> > -
> > -  Final = &Buffer[NumberOfBytes];
> > -  UartBase = (UINTN)PcdGet64 (PcdSerialRegisterBase);
> > -
> > -  while (Buffer < Final) {
> > -    while ((MmioRead8 (UartBase + ULSR) & DUART_LSR_THRE) == 0);
> > -    MmioWrite8 (UartBase + UTHR, *Buffer++);
> > -  }
> > -
> > -  return NumberOfBytes;
> > -}
> > -
> > -/**
> > -  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
> > -  )
> > -{
> > -  UINTN   Count;
> > -  UINTN   UartBase;
> > -
> > -  UartBase = (UINTN)PcdGet64 (PcdSerialRegisterBase);
> > -
> > -  for (Count = 0; Count < NumberOfBytes; Count++, Buffer++) {
> > -     // Loop while waiting for a new char(s) to arrive in the
> > -     // RxFIFO
> > -    while ((MmioRead8 (UartBase + ULSR) & DUART_LSR_DR) == 0);
> > -
> > -    *Buffer = MmioRead8 (UartBase + URBR);
> > -  }
> > -
> > -  return NumberOfBytes;
> > -}
> > -
> > -/**
> > -  Check to see if any data is available to be read from the debug device.
> > -
> > -  @retval EFI_SUCCESS       At least one byte of data is available to be read
> > -  @retval EFI_NOT_READY     No data is available to be read
> > -  @retval EFI_DEVICE_ERROR  The serial device is not functioning properly
> > -
> > -**/
> > -BOOLEAN
> > -EFIAPI
> > -SerialPortPoll (
> > -  VOID
> > -  )
> > -{
> > -  UINTN   UartBase;
> > -
> > -  UartBase = (UINTN)PcdGet64 (PcdSerialRegisterBase);
> > -
> > -  return ((MmioRead8 (UartBase + ULSR) & DUART_LSR_DR) != 0);
> > -}
> > -
> > -/**
> > -  Set new attributes to LS1043a.
> > -
> > -  @param  BaudRate                The baud rate of the serial device. If the baud
> rate is not supported,
> > -                                  the speed will be reduced down to the nearest supported
> one and the
> > -                                  variable's value will be updated accordingly.
> > -  @param  ReceiveFifoDepth        The number of characters the device will
> buffer on input. If the specified
> > -                                  value is not supported, the variable's value will be reduced
> down to the
> > -                                  nearest supported one.
> > -  @param  Timeout                 If applicable, the number of microseconds the
> device will wait
> > -                                  before timing out a Read or a Write operation.
> > -  @param  Parity                  If applicable, this is the EFI_PARITY_TYPE that is
> computed or checked
> > -                                  as each character is transmitted or received. If the device
> does not
> > -                                  support parity, the value is the default parity value.
> > -  @param  DataBits                The number of data bits in each character
> > -  @param  StopBits                If applicable, the EFI_STOP_BITS_TYPE number of
> stop bits per character.
> > -                                  If the device does not support stop bits, the value is the
> default stop
> > -                                  bit value.
> > -
> > -  @retval EFI_SUCCESS             All attributes were set correctly on the serial
> device.
> > -
> > -**/
> > -EFI_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
> > -  )
> > -{
> > -  DuartInitializePort (*BaudRate);
> > -
> > -  return EFI_SUCCESS;
> > -}
> > diff --git a/Silicon/NXP/Library/DUartPortLib/DUartPortLib.inf
> b/Silicon/NXP/Library/DUartPortLib/DUartPortLib.inf
> > deleted file mode 100644
> > index 7a2fa619b0..0000000000
> > --- a/Silicon/NXP/Library/DUartPortLib/DUartPortLib.inf
> > +++ /dev/null
> > @@ -1,34 +0,0 @@
> > -#  DUartPortLib.inf
> > -#
> > -#  Component description file for DUartPortLib module
> > -#
> > -#  Copyright (c) 2013, Freescale Ltd. All rights reserved.
> > -#  Copyright 2017 NXP
> > -#
> > -#  SPDX-License-Identifier: BSD-2-Clause-Patent
> > -#
> > -
> > -[Defines]
> > -  INF_VERSION                    = 0x0001001A
> > -  BASE_NAME                      = DUartPortLib
> > -  FILE_GUID                      = c42dfe79-8de5-429e-a055-2d0a58591498
> > -  MODULE_TYPE                    = BASE
> > -  VERSION_STRING                 = 1.0
> > -  LIBRARY_CLASS                  = SerialPortLib
> > -
> > -[Sources.common]
> > -  DUartPortLib.c
> > -
> > -[LibraryClasses]
> > -  PcdLib
> > -  SocLib
> > -
> > -[Packages]
> > -  MdeModulePkg/MdeModulePkg.dec
> > -  MdePkg/MdePkg.dec
> > -  Silicon/NXP/NxpQoriqLs.dec
> > -
> > -[Pcd]
> > -  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase
> > -  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
> > -  gNxpQoriqLsTokenSpaceGuid.PcdPlatformFreqDiv
> > --
> > 2.17.1
> >

  reply	other threads:[~2020-02-10  5:48 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-07 12:43 [PATCH 00/19] ADD LX2160ARDB Platform Support Pankaj Bansal
2020-02-07 12:43 ` [PATCH 01/19] Silicon/NXP: Add I2c lib Pankaj Bansal
2020-02-08 17:13   ` Leif Lindholm
2020-02-09 11:49     ` [edk2-devel] " Ard Biesheuvel
2020-02-07 12:43 ` [PATCH 02/19] Silicon/NXP: changes to use I2clib in i2cdxe Pankaj Bansal
2020-02-08 17:23   ` Leif Lindholm
2020-02-07 12:43 ` [PATCH 03/19] NXP/LS1043aRdb: Move Soc specific components to soc files Pankaj Bansal
2020-02-08 17:27   ` Leif Lindholm
2020-02-07 12:43 ` [PATCH 04/19] Silicon/NXP: Remove DuartLib and use BaseSerialPortLib16550 Pankaj Bansal
2020-02-08 17:46   ` Leif Lindholm
2020-02-10  5:48     ` Pankaj Bansal [this message]
2020-02-12 23:27       ` Leif Lindholm
2020-02-07 12:43 ` [PATCH 05/19] NXP/BaseSerialPortLib16550: remove SerialPortInitalize functionality Pankaj Bansal
2020-02-07 12:43 ` [PATCH 06/19] Silicon/NXP: remove print information from Soc lib Pankaj Bansal
2020-02-10 17:09   ` [EXTERNAL] " Leif Lindholm
2020-02-07 12:43 ` [PATCH 07/19] Silicon/NXP: remove not needed components Pankaj Bansal
2020-02-10 17:11   ` Leif Lindholm
2020-02-11  7:24     ` Pankaj Bansal
2020-02-20 19:05       ` Leif Lindholm
2020-02-07 12:43 ` [PATCH 08/19] Silicon/NXP: Remove unnecessary PCDs Pankaj Bansal
2020-02-10 17:32   ` Leif Lindholm
2020-02-11  8:45     ` Pankaj Bansal
2020-02-20 18:56       ` Leif Lindholm
2020-02-07 12:43 ` [PATCH 09/19] Silicon/NXP: Move dsc file Pankaj Bansal
2020-02-11 11:35   ` Leif Lindholm
2020-02-07 12:43 ` [PATCH 10/19] Platform/NXP: rename the ArmPlatformLib as per ArmPlatformPkg Pankaj Bansal
2020-02-11 11:40   ` Leif Lindholm
2020-02-07 12:43 ` [PATCH 11/19] Silicon/NXP: Add Chassis Lib for Chassis2 Pankaj Bansal
2020-02-11 12:28   ` Leif Lindholm
2020-02-07 12:43 ` [PATCH 12/19] Silicon/NXP/LS1043A: Add SocLib Pankaj Bansal
2020-02-11 12:38   ` Leif Lindholm
2020-02-07 12:43 ` [PATCH 13/19] Silicon/NXP: Move RAM retrieval from SocLib Pankaj Bansal
2020-02-11 13:28   ` Leif Lindholm
2020-02-07 12:43 ` [PATCH 14/19] Silicon/NXP/LS1043A: Replce SocLib Pankaj Bansal
2020-02-11 13:35   ` Leif Lindholm
2020-02-12  9:37     ` Pankaj Bansal
2020-02-12 22:50       ` Leif Lindholm
2020-02-13 11:00         ` Pankaj Bansal
2020-02-20 18:45           ` Leif Lindholm
2020-02-07 12:43 ` [PATCH 15/19] Platform/NXP/LS1043ARDB: introduce PEI Phase Pankaj Bansal
2020-02-12 20:24   ` Leif Lindholm
2020-02-07 12:43 ` [PATCH 16/19] Silicon/NXP: Add Pl011 Serial port lib Pankaj Bansal
2020-02-12 20:26   ` Leif Lindholm
2020-02-07 12:43 ` [PATCH 17/19] Silicon/NXP: Add Chassis3V2 Pankaj Bansal
2020-02-12 20:33   ` Leif Lindholm
2020-02-07 12:43 ` [PATCH 18/19] Silicon/NXP: Add LX2160A SocLib Pankaj Bansal
2020-02-12 21:39   ` Leif Lindholm
2020-02-07 12:43 ` [PATCH 19/19] Platform/NXP: Add LX2160ARDBPKG Pankaj Bansal
2020-02-12 21:36   ` Leif Lindholm

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=VI1PR0401MB2496690823259E1779E5E823F1190@VI1PR0401MB2496.eurprd04.prod.outlook.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox