OvmfPkg/LoongArchVirt: Add serial port hook library

Add a serial port hook library in LoongArchVirt named
Fdt16550SerialProtHookLib, this library is referenced from ArmVirtPkg.

LoongArch QEMU virtual machine uses register of LOONGARCH_CSR_KS1 to
transfer serial port base addres from the PEI phase to the DXE phase.

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

Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Bibo Mao <maobibo@loongson.cn>
Cc: Dongyan Qian <qiandongyan@loongson.cn>
Signed-off-by: Chao Li <lichao@loongson.cn>
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
diff --git a/OvmfPkg/LoongArchVirt/Library/Fdt16550SerialPortHookLib/EarlyFdt16550SerialPortHookLib.c b/OvmfPkg/LoongArchVirt/Library/Fdt16550SerialPortHookLib/EarlyFdt16550SerialPortHookLib.c
new file mode 100644
index 0000000..9f1fcc9
--- /dev/null
+++ b/OvmfPkg/LoongArchVirt/Library/Fdt16550SerialPortHookLib/EarlyFdt16550SerialPortHookLib.c
@@ -0,0 +1,52 @@
+/** @file

+  PEI Phase Early Platform Hook Library instance for 16550 Uart.

+

+  Copyright (c) 2020 - 2023, Arm Ltd. All rights reserved.<BR>

+  Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>

+

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#include <Library/BaseLib.h>

+#include <Library/FdtSerialPortAddressLib.h>

+#include <Library/PcdLib.h>

+#include <Library/PlatformHookLib.h>

+#include <Register/LoongArch64/Csr.h>

+

+/** Platform hook to retrieve the 16550 UART base address from the platform

+    Device tree and store it in the reigster LOONGARCH_CSR_KS1.

+

+  @retval RETURN_SUCCESS            Success.

+  @retval RETURN_INVALID_PARAMETER  A parameter was invalid.

+  @retval RETURN_NOT_FOUND          Serial port information not found.

+

+**/

+RETURN_STATUS

+EFIAPI

+PlatformHookSerialPortInitialize (

+  VOID

+  )

+{

+  RETURN_STATUS  Status;

+  VOID           *DeviceTreeBase;

+  UINT64         SerialConsoleAddress;

+

+  if (PcdGet64 (PcdSerialRegisterBase) != 0) {

+    return RETURN_SUCCESS;

+  }

+

+  DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);

+  if (DeviceTreeBase == NULL) {

+    return RETURN_NOT_FOUND;

+  }

+

+  Status = FdtSerialGetConsolePort (DeviceTreeBase, &SerialConsoleAddress);

+  if (RETURN_ERROR (Status)) {

+    return Status;

+  }

+

+  CsrWrite (LOONGARCH_CSR_KS1, (UINTN)SerialConsoleAddress);

+

+  return RETURN_SUCCESS;

+}

diff --git a/OvmfPkg/LoongArchVirt/Library/Fdt16550SerialPortHookLib/EarlyFdt16550SerialPortHookLib.inf b/OvmfPkg/LoongArchVirt/Library/Fdt16550SerialPortHookLib/EarlyFdt16550SerialPortHookLib.inf
new file mode 100644
index 0000000..084cd18
--- /dev/null
+++ b/OvmfPkg/LoongArchVirt/Library/Fdt16550SerialPortHookLib/EarlyFdt16550SerialPortHookLib.inf
@@ -0,0 +1,35 @@
+## @file

+#  PEI Phase Early Platform Hook Library instance for 16550 Uart.

+#

+#  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>

+#  Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>

+#

+#  SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+[Defines]

+  INF_VERSION                    = 1.29

+  BASE_NAME                      = EarlyFdt16550SerialPortHookLib

+  MODULE_UNI_FILE                = Fdt16550SerialPortHookLib.uni

+  FILE_GUID                      = 6A5FEBCB-C676-A7C1-A96C-B79D4860EEC5

+  MODULE_TYPE                    = PEIM

+  VERSION_STRING                 = 1.0

+  LIBRARY_CLASS                  = PlatformHookLib|SEC PEI_CORE PEIM

+

+[Sources]

+  EarlyFdt16550SerialPortHookLib.c

+

+[LibraryClasses]

+  BaseLib

+  PcdLib

+

+[Packages]

+  EmbeddedPkg/EmbeddedPkg.dec

+  MdeModulePkg/MdeModulePkg.dec

+  MdePkg/MdePkg.dec

+  OvmfPkg/OvmfPkg.dec

+

+[Pcd]

+  gUefiOvmfPkgTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress

+  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase

diff --git a/OvmfPkg/LoongArchVirt/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.c b/OvmfPkg/LoongArchVirt/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.c
new file mode 100644
index 0000000..baaa7ae
--- /dev/null
+++ b/OvmfPkg/LoongArchVirt/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.c
@@ -0,0 +1,38 @@
+/** @file

+  Platform Hook Library instance for 16550 Uart.

+

+  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>

+  Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>

+

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#include <Library/BaseLib.h>

+#include <Library/PcdLib.h>

+#include <Register/LoongArch64/Csr.h>

+

+/** Platform hook to retrieve the 16550 UART base address from register

+    LOONGARCH_CSR_KS1 that caches the UART base address from early boot

+    stage and store it in  PcdSerialRegisterBase.

+

+  @retval RETURN_SUCCESS    Success.

+  @retval RETURN_NOT_FOUND  Serial Port information not found.

+

+**/

+RETURN_STATUS

+EFIAPI

+PlatformHookSerialPortInitialize (

+  VOID

+  )

+{

+  UINT64  *UartBase;

+

+  if (PcdGet64 (PcdSerialRegisterBase) != 0) {

+    return RETURN_SUCCESS;

+  }

+

+  *UartBase = CsrRead (LOONGARCH_CSR_KS1);

+

+  return (RETURN_STATUS)PcdSet64S (PcdSerialRegisterBase, (UINTN)*UartBase);

+}

diff --git a/OvmfPkg/LoongArchVirt/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.inf b/OvmfPkg/LoongArchVirt/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.inf
new file mode 100644
index 0000000..b5fc03a
--- /dev/null
+++ b/OvmfPkg/LoongArchVirt/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.inf
@@ -0,0 +1,33 @@
+## @file

+#  Platform Hook Library instance for 16550 Uart.

+#

+#  Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>

+#  Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>

+#

+#  SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+[Defines]

+  INF_VERSION                    = 1.29

+  BASE_NAME                      = Fdt16550SerialPortHookLib

+  MODULE_UNI_FILE                = Fdt16550SerialPortHookLib.uni

+  FILE_GUID                      = 808335DB-220E-A353-887C-9AA1B7D433A1

+  MODULE_TYPE                    = BASE

+  VERSION_STRING                 = 1.0

+  LIBRARY_CLASS                  = PlatformHookLib|DXE_CORE DXE_DRIVER UEFI_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION

+  CONSTRUCTOR                    = PlatformHookSerialPortInitialize

+

+[Sources]

+  Fdt16550SerialPortHookLib.c

+

+[LibraryClasses]

+  BaseLib

+  PcdLib

+

+[Packages]

+  MdePkg/MdePkg.dec

+  MdeModulePkg/MdeModulePkg.dec

+

+[Pcd]

+  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase

diff --git a/OvmfPkg/LoongArchVirt/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.uni b/OvmfPkg/LoongArchVirt/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.uni
new file mode 100644
index 0000000..92eb2ed
--- /dev/null
+++ b/OvmfPkg/LoongArchVirt/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.uni
@@ -0,0 +1,14 @@
+// /** @file

+// Platform Hook Library instance for 16550 Uart.

+//

+//

+// Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>

+// Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>

+//

+// SPDX-License-Identifier: BSD-2-Clause-Patent

+//

+// **/

+

+#string STR_MODULE_ABSTRACT     #language en-US "Platform Hook Library instance for 16550 Uart."

+

+#string STR_MODULE_DESCRIPTION  #language en-US "Platform Hook Library instance for 16550 Uart."