Re: [edk2-devel] [PATCH v6 28/36] OvmfPkg/LoongArchVirt: Add the early serial port output library

2024-01-09 Thread maobibo




On 2024/1/5 下午5:45, Chao Li wrote:

Add a early serial port output library into LoongArchVirt that named
EarlyFdtSerialPortLib16550, this library is referenced from
MdeModulePkg.

This library is used in the PEI phase. Since the serial port address can
not be saved in memory of the LoongArch QEMU virtual machine in the PEI
phase, the serial prot base address will be obtained from the FDT before
each output.

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4584

Cc: Ard Biesheuvel 
Cc: Jiewen Yao 
Cc: Jordan Justen 
Cc: Gerd Hoffmann 
Cc: Bibo Mao 
Cc: Dongyan Qian 
Signed-off-by: Chao Li 
Co-authored-by: Xianglai Li 
---
  .../EarlyFdtSerialPortLib16550.c  | 815 ++
  .../EarlyFdtSerialPortLib16550.inf|  46 +
  2 files changed, 861 insertions(+)
  create mode 100644 
OvmfPkg/LoongArchVirt/Library/EarlyFdtSerialPortLib16550/EarlyFdtSerialPortLib16550.c
  create mode 100644 
OvmfPkg/LoongArchVirt/Library/EarlyFdtSerialPortLib16550/EarlyFdtSerialPortLib16550.inf

diff --git 
a/OvmfPkg/LoongArchVirt/Library/EarlyFdtSerialPortLib16550/EarlyFdtSerialPortLib16550.c
 
b/OvmfPkg/LoongArchVirt/Library/EarlyFdtSerialPortLib16550/EarlyFdtSerialPortLib16550.c
new file mode 100644
index 00..8cc108501c
--- /dev/null
+++ 
b/OvmfPkg/LoongArchVirt/Library/EarlyFdtSerialPortLib16550/EarlyFdtSerialPortLib16550.c
@@ -0,0 +1,815 @@
+/** @file
+  16550 UART Serial Port library functions
+
+  Copyright (c) 2024, Loongson Technology Corporation Limited. All rights 
reserved.
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+//
+// PCI Defintions.
+//
+#define PCI_BRIDGE_32_BIT_IO_SPACE  0x01
+
+//
+// 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_LOW0// 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_DLABBIT7
+#define R_UART_MCR 4
+#define B_UART_MCR_DTRCBIT0
+#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_TEMTBIT6
+#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
+
+/**
+  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  BaseThe 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
+  )
+{
+  if (PcdGetBool (PcdSerialUseMmio)) {
+if (PcdGet8 (PcdSerialRegisterAccessWidth) == 32) {
+  return (UINT8)MmioRead32 (Base + Offset * PcdGet32 
(PcdSerialRegisterStride));
+}
+
+return MmioRead8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride));
+  } else {
+return IoRead8 (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  BaseThe 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
+  )
+{
+  if (PcdGetBool (PcdSerialUseMmio)) {
+if (PcdGet8 (PcdSerialRegisterAccessWidth) == 32) {
+  return (UINT8)MmioWrite32 (Base + Offset * PcdGet32 
(PcdSerialRegisterStride), (UINT8)Value);
+}
+
+return MmioWrite8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride), 
Value);
+  } else {
+return IoWrite8 (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 
P

[edk2-devel] [PATCH v6 28/36] OvmfPkg/LoongArchVirt: Add the early serial port output library

2024-01-05 Thread Chao Li
Add a early serial port output library into LoongArchVirt that named
EarlyFdtSerialPortLib16550, this library is referenced from
MdeModulePkg.

This library is used in the PEI phase. Since the serial port address can
not be saved in memory of the LoongArch QEMU virtual machine in the PEI
phase, the serial prot base address will be obtained from the FDT before
each output.

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4584

Cc: Ard Biesheuvel 
Cc: Jiewen Yao 
Cc: Jordan Justen 
Cc: Gerd Hoffmann 
Cc: Bibo Mao 
Cc: Dongyan Qian 
Signed-off-by: Chao Li 
Co-authored-by: Xianglai Li 
---
 .../EarlyFdtSerialPortLib16550.c  | 815 ++
 .../EarlyFdtSerialPortLib16550.inf|  46 +
 2 files changed, 861 insertions(+)
 create mode 100644 
OvmfPkg/LoongArchVirt/Library/EarlyFdtSerialPortLib16550/EarlyFdtSerialPortLib16550.c
 create mode 100644 
OvmfPkg/LoongArchVirt/Library/EarlyFdtSerialPortLib16550/EarlyFdtSerialPortLib16550.inf

diff --git 
a/OvmfPkg/LoongArchVirt/Library/EarlyFdtSerialPortLib16550/EarlyFdtSerialPortLib16550.c
 
b/OvmfPkg/LoongArchVirt/Library/EarlyFdtSerialPortLib16550/EarlyFdtSerialPortLib16550.c
new file mode 100644
index 00..8cc108501c
--- /dev/null
+++ 
b/OvmfPkg/LoongArchVirt/Library/EarlyFdtSerialPortLib16550/EarlyFdtSerialPortLib16550.c
@@ -0,0 +1,815 @@
+/** @file
+  16550 UART Serial Port library functions
+
+  Copyright (c) 2024, Loongson Technology Corporation Limited. All rights 
reserved.
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+//
+// PCI Defintions.
+//
+#define PCI_BRIDGE_32_BIT_IO_SPACE  0x01
+
+//
+// 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_LOW0// 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_DLABBIT7
+#define R_UART_MCR 4
+#define B_UART_MCR_DTRCBIT0
+#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_TEMTBIT6
+#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
+
+/**
+  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  BaseThe 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
+  )
+{
+  if (PcdGetBool (PcdSerialUseMmio)) {
+if (PcdGet8 (PcdSerialRegisterAccessWidth) == 32) {
+  return (UINT8)MmioRead32 (Base + Offset * PcdGet32 
(PcdSerialRegisterStride));
+}
+
+return MmioRead8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride));
+  } else {
+return IoRead8 (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  BaseThe 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
+  )
+{
+  if (PcdGetBool (PcdSerialUseMmio)) {
+if (PcdGet8 (PcdSerialRegisterAccessWidth) == 32) {
+  return (UINT8)MmioWrite32 (Base + Offset * PcdGet32 
(PcdSerialRegisterStride), (UINT8)Value);
+}
+
+return MmioWrite8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride), 
Value);
+  } else {
+return IoWrite8 (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 ena