OvmfPkg/LoongArchVirt: Add reset system library

This library provides interface related to restart and shudown the
LoongArch64 virtual machine.

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>
Co-authored-by: Xianglai Li <lixianglai@loongson.cn>
Co-authored-by: Bibo Mao <maobibo@loongson.cn>
diff --git a/OvmfPkg/LoongArchVirt/Library/ResetSystemAcpiLib/BaseResetSystemAcpiGed.c b/OvmfPkg/LoongArchVirt/Library/ResetSystemAcpiLib/BaseResetSystemAcpiGed.c
new file mode 100644
index 0000000..a88ed2a
--- /dev/null
+++ b/OvmfPkg/LoongArchVirt/Library/ResetSystemAcpiLib/BaseResetSystemAcpiGed.c
@@ -0,0 +1,151 @@
+/** @file

+  Base ResetSystem library implementation.

+

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

+

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

+

+**/

+

+#include <Library/DebugLib.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/QemuFwCfgLib.h>

+#include "ResetSystemAcpiGed.h"

+

+/**

+  Get configuration item data by the firmware configuration file name.

+

+  @param[in]  Name - Name of file to look up.

+

+  @return    VOID*       The Pointer of Value of Firmware Configuration item read.

+**/

+STATIC

+VOID *

+GetFwCfgData (

+  CONST CHAR8  *Name

+  )

+{

+  FIRMWARE_CONFIG_ITEM  FwCfgItem;

+  EFI_STATUS            Status;

+  UINTN                 FwCfgSize;

+  VOID                  *Data;

+

+  Status = QemuFwCfgFindFile (Name, &FwCfgItem, &FwCfgSize);

+  if (EFI_ERROR (Status)) {

+    DEBUG ((DEBUG_ERROR, "%a %d read  %s error Status %d \n", __func__, __LINE__, Name, Status));

+    return NULL;

+  }

+

+  Data = AllocatePool (FwCfgSize);

+  if (Data == NULL) {

+    return NULL;

+  }

+

+  QemuFwCfgSelectItem (FwCfgItem);

+  QemuFwCfgReadBytes (FwCfgSize, Data);

+

+  return Data;

+}

+

+/**

+  Find the power manager related info from ACPI table

+

+  @retval EFI_SUCCESS     Successfully find out all the required information.

+  @retval EFI_NOT_FOUND   Failed to find the required info.

+**/

+STATIC

+EFI_STATUS

+GetPowerManagerByParseAcpiInfo (

+  VOID

+  )

+{

+  EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE     *Fadt       = NULL;

+  EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER  *Rsdp       = NULL;

+  EFI_ACPI_DESCRIPTION_HEADER                   *Xsdt       = NULL;

+  EFI_ACPI_DESCRIPTION_HEADER                   *Rsdt       = NULL;

+  VOID                                          *AcpiTables = NULL;

+  UINT32                                        *Entry32    = NULL;

+  UINTN                                         Entry32Num;

+  UINT32                                        *Signature = NULL;

+  UINTN                                         Idx;

+

+  Rsdp = GetFwCfgData ("etc/acpi/rsdp");

+  if (Rsdp == NULL) {

+    DEBUG ((DEBUG_ERROR, "%a %d read etc/acpi/rsdp error \n", __func__, __LINE__));

+    return EFI_NOT_FOUND;

+  }

+

+  AcpiTables = GetFwCfgData ("etc/acpi/tables");

+  if (AcpiTables == NULL) {

+    DEBUG ((DEBUG_ERROR, "%a %d read etc/acpi/tables error \n", __func__, __LINE__));

+    FreePool (Rsdp);

+    return EFI_NOT_FOUND;

+  }

+

+  Rsdt       = (EFI_ACPI_DESCRIPTION_HEADER *)((UINTN)AcpiTables +  Rsdp->RsdtAddress);

+  Entry32    = (UINT32 *)(Rsdt + 1);

+  Entry32Num = (Rsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) >> 2;

+  for (Idx = 0; Idx < Entry32Num; Idx++) {

+    Signature = (UINT32 *)((UINTN)Entry32[Idx] + (UINTN)AcpiTables);

+    if (*Signature == EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {

+      Fadt = (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature;

+      DEBUG ((DEBUG_INFO, "Found Fadt in Rsdt\n"));

+      goto Done;

+    }

+  }

+

+  Xsdt       = (EFI_ACPI_DESCRIPTION_HEADER *)((UINTN)AcpiTables +  Rsdp->XsdtAddress);

+  Entry32    = (UINT32 *)(Xsdt + 1);

+  Entry32Num = (Xsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) >> 2;

+  for (Idx = 0; Idx < Entry32Num; Idx++) {

+    Signature = (UINT32 *)((UINTN)Entry32[Idx] + (UINTN)AcpiTables);

+    if (*Signature == EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {

+      Fadt = (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature;

+      DEBUG ((DEBUG_INFO, "Found Fadt in Xsdt\n"));

+      goto Done;

+    }

+  }

+

+  FreePool (Rsdp);

+  FreePool (AcpiTables);

+  DEBUG ((DEBUG_ERROR, " Fadt Not Found\n"));

+  return EFI_NOT_FOUND;

+

+Done:

+  mPowerManager.ResetRegAddr        = Fadt->ResetReg.Address;

+  mPowerManager.ResetValue          = Fadt->ResetValue;

+  mPowerManager.SleepControlRegAddr = Fadt->SleepControlReg.Address;

+  mPowerManager.SleepStatusRegAddr  = Fadt->SleepStatusReg.Address;

+

+  FreePool (Rsdp);

+  FreePool (AcpiTables);

+

+  return EFI_SUCCESS;

+}

+

+/**

+  The constructor function to initialize mPowerManager.

+

+  @retval EFI_SUCCESS     Initialize mPowerManager success.

+  @retval EFI_NOT_FOUND   Failed to initialize mPowerManager.

+**/

+EFI_STATUS

+EFI_API

+ResetSystemLibConstructor (

+  IN EFI_HANDLE        ImageHandle,

+  IN EFI_SYSTEM_TABLE  *SystemTable

+  )

+{

+  EFI_STATUS  Status;

+

+  Status = GetPowerManagerByParseAcpiInfo ();

+  if (EFI_ERROR (Status)) {

+    DEBUG ((DEBUG_INFO, "%a:%d\n", __func__, __LINE__));

+  }

+

+  ASSERT (mPowerManager.SleepControlRegAddr);

+  ASSERT (mPowerManager.SleepStatusRegAddr);

+  ASSERT (mPowerManager.ResetRegAddr);

+

+  return Status;

+}

diff --git a/OvmfPkg/LoongArchVirt/Library/ResetSystemAcpiLib/BaseResetSystemAcpiGedLib.inf b/OvmfPkg/LoongArchVirt/Library/ResetSystemAcpiLib/BaseResetSystemAcpiGedLib.inf
new file mode 100644
index 0000000..f63915d
--- /dev/null
+++ b/OvmfPkg/LoongArchVirt/Library/ResetSystemAcpiLib/BaseResetSystemAcpiGedLib.inf
@@ -0,0 +1,35 @@
+## @file

+#  Base library instance for ResetSystem library class for LoongArch

+#

+#  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                      = ResetSystemLib

+  FILE_GUID                      = BA521997-9016-32B5-65DF-EA5F560A3837

+  MODULE_TYPE                    = BASE

+  VERSION_STRING                 = 1.0

+  LIBRARY_CLASS                  = ResetSystemLib|SEC PEI_CORE PEIM DXE_CORE

+  CONSTRUCTOR                    = ResetSystemLibConstructor

+

+#

+#  VALID_ARCHITECTURES           = LOONGARCH64

+#

+

+[Sources]

+  BaseResetSystemAcpiGed.c

+  ResetSystemAcpiGed.c

+

+[Packages]

+  MdeModulePkg/MdeModulePkg.dec

+  MdePkg/MdePkg.dec

+  OvmfPkg/OvmfPkg.dec

+

+[LibraryClasses]

+  DebugLib

+  MemoryAllocationLib

+  QemuFwCfgLib

diff --git a/OvmfPkg/LoongArchVirt/Library/ResetSystemAcpiLib/DxeResetSystemAcpiGed.c b/OvmfPkg/LoongArchVirt/Library/ResetSystemAcpiLib/DxeResetSystemAcpiGed.c
new file mode 100644
index 0000000..4aea6de
--- /dev/null
+++ b/OvmfPkg/LoongArchVirt/Library/ResetSystemAcpiLib/DxeResetSystemAcpiGed.c
@@ -0,0 +1,262 @@
+/** @file

+  Dxe ResetSystem library implementation.

+

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

+

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

+

+**/

+

+#include <Base.h>

+#include <Library/DebugLib.h>

+#include <Library/DxeServicesTableLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/UefiLib.h>

+#include <Library/UefiRuntimeLib.h> // EfiConvertPointer()

+#include "ResetSystemAcpiGed.h"

+

+/**

+  Modifies the attributes to Runtime type for a page size memory region.

+

+  @param  BaseAddress            Specified start address

+

+  @retval EFI_SUCCESS           The attributes were set for the memory region.

+  @retval EFI_INVALID_PARAMETER Length is zero.

+  @retval EFI_UNSUPPORTED       The processor does not support one or more bytes of the memory

+                                resource range specified by BaseAddress and Length.

+  @retval EFI_UNSUPPORTED       The bit mask of attributes is not support for the memory resource

+                                range specified by BaseAddress and Length.

+  @retval EFI_ACCESS_DEFINED    The attributes for the memory resource range specified by

+                                BaseAddress and Length cannot be modified.

+  @retval EFI_OUT_OF_RESOURCES  There are not enough system resources to modify the attributes of

+                                the memory resource range.

+  @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol is

+                                not available yet.

+**/

+STATIC

+EFI_STATUS

+SetMemoryAttributesRunTime (

+  UINTN  Address

+  )

+{

+  EFI_STATUS                       Status;

+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR  Descriptor;

+

+  Address &= ~EFI_PAGE_MASK;

+

+  Status = gDS->GetMemorySpaceDescriptor (Address, &Descriptor);

+  if (EFI_ERROR (Status)) {

+    DEBUG ((DEBUG_INFO, "%a: GetMemorySpaceDescriptor failed\n", __func__));

+    return Status;

+  }

+

+  if (Descriptor.GcdMemoryType == EfiGcdMemoryTypeNonExistent) {

+    Status = gDS->AddMemorySpace (

+                    EfiGcdMemoryTypeMemoryMappedIo,

+                    Address,

+                    EFI_PAGE_SIZE,

+                    EFI_MEMORY_UC | EFI_MEMORY_RUNTIME

+                    );

+    if (EFI_ERROR (Status)) {

+      DEBUG ((DEBUG_INFO, "%a: AddMemorySpace failed\n", __func__));

+      return Status;

+    }

+

+    Status = gDS->SetMemorySpaceAttributes (

+                    Address,

+                    EFI_PAGE_SIZE,

+                    EFI_MEMORY_RUNTIME

+                    );

+    if (EFI_ERROR (Status)) {

+      DEBUG ((DEBUG_INFO, "%a:%d SetMemorySpaceAttributes failed\n", __func__, __LINE__));

+      return Status;

+    }

+  } else if (!(Descriptor.Attributes & EFI_MEMORY_RUNTIME)) {

+    Status = gDS->SetMemorySpaceAttributes (

+                    Address,

+                    EFI_PAGE_SIZE,

+                    Descriptor.Attributes | EFI_MEMORY_RUNTIME

+                    );

+

+    if (EFI_ERROR (Status)) {

+      DEBUG ((DEBUG_INFO, "%a:%d SetMemorySpaceAttributes failed\n", __func__, __LINE__));

+      return Status;

+    }

+  }

+

+  return EFI_SUCCESS;

+}

+

+/**

+  Find the power manager related info from ACPI table

+

+  @retval RETURN_SUCCESS     Successfully find out all the required information.

+  @retval RETURN_NOT_FOUND   Failed to find the required info.

+**/

+STATIC

+EFI_STATUS

+GetPowerManagerByParseAcpiInfo (

+  VOID

+  )

+{

+  EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE     *Fadt    = NULL;

+  EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER  *Rsdp    = NULL;

+  EFI_ACPI_DESCRIPTION_HEADER                   *Xsdt    = NULL;

+  EFI_ACPI_DESCRIPTION_HEADER                   *Rsdt    = NULL;

+  UINT32                                        *Entry32 = NULL;

+  UINTN                                         Entry32Num;

+  UINT32                                        *Signature = NULL;

+  UINTN                                         Idx;

+  EFI_STATUS                                    Status;

+

+  Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID **)&Rsdp);

+  if (EFI_ERROR (Status)) {

+    Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **)&Rsdp);

+  }

+

+  if (EFI_ERROR (Status) || (Rsdp == NULL)) {

+    DEBUG ((DEBUG_ERROR, "EFI_ERROR or Rsdp == NULL\n"));

+    return RETURN_NOT_FOUND;

+  }

+

+  Rsdt       = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->RsdtAddress;

+  Entry32    = (UINT32 *)(UINTN)(Rsdt + 1);

+  Entry32Num = (Rsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) >> 2;

+  for (Idx = 0; Idx < Entry32Num; Idx++) {

+    Signature = (UINT32 *)(UINTN)Entry32[Idx];

+    if (*Signature == EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {

+      Fadt = (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature;

+      DEBUG ((DEBUG_INFO, "Found Fadt in Rsdt\n"));

+      goto Done;

+    }

+  }

+

+  Xsdt       = (EFI_ACPI_DESCRIPTION_HEADER *)Rsdp->XsdtAddress;

+  Entry32    = (UINT32 *)(Xsdt + 1);

+  Entry32Num = (Xsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) >> 2;

+  for (Idx = 0; Idx < Entry32Num; Idx++) {

+    Signature = (UINT32 *)(UINTN)Entry32[Idx];

+    if (*Signature == EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {

+      Fadt = (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature;

+      DEBUG ((DEBUG_INFO, "Found Fadt in Xsdt\n"));

+      goto Done;

+    }

+  }

+

+  DEBUG ((DEBUG_ERROR, " Fadt Not Found\n"));

+  return RETURN_NOT_FOUND;

+

+Done:

+  mPowerManager.ResetRegAddr        = Fadt->ResetReg.Address;

+  mPowerManager.ResetValue          = Fadt->ResetValue;

+  mPowerManager.SleepControlRegAddr = Fadt->SleepControlReg.Address;

+  mPowerManager.SleepStatusRegAddr  = Fadt->SleepStatusReg.Address;

+  return RETURN_SUCCESS;

+}

+

+/**

+  This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE

+  event. It converts a pointer to a new virtual address.

+

+  @param[in] Event        Event whose notification function is being invoked.

+  @param[in] Context      Pointer to the notification function's context

+**/

+STATIC

+VOID

+ResetSystemLibAddressChangeEvent (

+  IN EFI_EVENT  Event,

+  IN VOID       *Context

+  )

+{

+  EfiConvertPointer (0, (VOID **)&mPowerManager.SleepControlRegAddr);

+  EfiConvertPointer (0, (VOID **)&mPowerManager.SleepStatusRegAddr);

+  EfiConvertPointer (0, (VOID **)&mPowerManager.ResetRegAddr);

+}

+

+/**

+  Notification function of ACPI Table change.

+

+  This is a notification function registered on ACPI Table change event.

+  It saves the Century address stored in ACPI FADT table.

+

+  @param  Event        Event whose notification function is being invoked.

+  @param  Context      Pointer to the notification function's context.

+**/

+STATIC

+VOID

+AcpiNotificationEvent (

+  IN EFI_EVENT  Event,

+  IN VOID       *Context

+  )

+{

+  EFI_STATUS  Status;

+

+  Status = GetPowerManagerByParseAcpiInfo ();

+  if (EFI_ERROR (Status)) {

+    return;

+  }

+

+  DEBUG ((DEBUG_INFO, "%a: sleepControl %llx\n", __func__, mPowerManager.SleepControlRegAddr));

+  ASSERT (mPowerManager.SleepControlRegAddr);

+  Status =  SetMemoryAttributesRunTime (mPowerManager.SleepControlRegAddr);

+  if (EFI_ERROR (Status)) {

+    DEBUG ((DEBUG_INFO, "%a:%d\n", __func__, __LINE__));

+    return;

+  }

+

+  DEBUG ((DEBUG_INFO, "%a: sleepStatus %llx\n", __func__, mPowerManager.SleepStatusRegAddr));

+  ASSERT (mPowerManager.SleepStatusRegAddr);

+  Status =  SetMemoryAttributesRunTime (mPowerManager.SleepStatusRegAddr);

+  if (EFI_ERROR (Status)) {

+    DEBUG ((DEBUG_INFO, "%a:%d\n", __func__, __LINE__));

+    return;

+  }

+

+  DEBUG ((DEBUG_INFO, "%a: ResetReg %llx\n", __func__, mPowerManager.ResetRegAddr));

+  ASSERT (mPowerManager.ResetRegAddr);

+  Status =  SetMemoryAttributesRunTime (mPowerManager.ResetRegAddr);

+  if (EFI_ERROR (Status)) {

+    DEBUG ((DEBUG_INFO, "%a:%d\n", __func__, __LINE__));

+  }

+

+  return;

+}

+

+/**

+  The constructor function to Register ACPI Table change event and Address Change Event.

+

+  @retval EFI_SUCCESS   The constructor always returns RETURN_SUCCESS.

+**/

+EFI_STATUS

+EFIAPI

+ResetSystemLibConstructor (

+  IN EFI_HANDLE        ImageHandle,

+  IN EFI_SYSTEM_TABLE  *SystemTable

+  )

+{

+  EFI_STATUS  Status;

+  EFI_EVENT   Event;

+  EFI_EVENT   ResetSystemVirtualNotifyEvent;

+

+  Status = gBS->CreateEventEx (

+                  EVT_NOTIFY_SIGNAL,

+                  TPL_CALLBACK,

+                  AcpiNotificationEvent,

+                  NULL,

+                  &gEfiAcpiTableGuid,

+                  &Event

+                  );

+

+  //

+  // Register SetVirtualAddressMap () notify function

+  //

+  Status = gBS->CreateEvent (

+                  EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,

+                  TPL_NOTIFY,

+                  ResetSystemLibAddressChangeEvent,

+                  NULL,

+                  &ResetSystemVirtualNotifyEvent

+                  );

+  ASSERT_EFI_ERROR (Status);

+  return Status;

+}

diff --git a/OvmfPkg/LoongArchVirt/Library/ResetSystemAcpiLib/DxeResetSystemAcpiGedLib.inf b/OvmfPkg/LoongArchVirt/Library/ResetSystemAcpiLib/DxeResetSystemAcpiGedLib.inf
new file mode 100644
index 0000000..9815e2f
--- /dev/null
+++ b/OvmfPkg/LoongArchVirt/Library/ResetSystemAcpiLib/DxeResetSystemAcpiGedLib.inf
@@ -0,0 +1,41 @@
+## @file

+#  DXE library instance for ResetSystem library class for LoongArch.

+#

+#  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                      = ResetSystemLib

+  FILE_GUID                      = F05197D5-5827-AA61-FB2D-BC69259F17A9

+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER

+  VERSION_STRING                 = 1.0

+  LIBRARY_CLASS                  = ResetSystemLib|DXE_DRIVER DXE_RUNTIME_DRIVER SMM_CORE DXE_SMM_DRIVER UEFI_DRIVER UEFI_APPLICATION

+  CONSTRUCTOR                    = ResetSystemLibConstructor

+

+#

+#  VALID_ARCHITECTURES           = LOONGARCH64

+#

+

+[Sources]

+  DxeResetSystemAcpiGed.c

+  ResetSystemAcpiGed.c

+

+[Packages]

+  MdeModulePkg/MdeModulePkg.dec

+  MdePkg/MdePkg.dec

+  OvmfPkg/OvmfPkg.dec

+

+[LibraryClasses]

+  DebugLib

+  DxeServicesTableLib

+  UefiBootServicesTableLib

+  UefiLib

+  UefiRuntimeLib

+

+[Guids]

+  gEfiAcpi10TableGuid                           ## PRODUCES           ## SystemTable

+  gEfiAcpiTableGuid                             ## PRODUCES           ## SystemTable

diff --git a/OvmfPkg/LoongArchVirt/Library/ResetSystemAcpiLib/ResetSystemAcpiGed.c b/OvmfPkg/LoongArchVirt/Library/ResetSystemAcpiLib/ResetSystemAcpiGed.c
new file mode 100644
index 0000000..105382d
--- /dev/null
+++ b/OvmfPkg/LoongArchVirt/Library/ResetSystemAcpiLib/ResetSystemAcpiGed.c
@@ -0,0 +1,125 @@
+/** @file

+  ResetSystem library implementation.

+

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

+

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

+

+**/

+

+#include <Library/BaseLib.h>        // CpuDeadLoop()

+#include <Library/DebugLib.h>

+#include <Library/IoLib.h>

+#include <Library/ResetSystemLib.h> // ResetCold()

+#include "ResetSystemAcpiGed.h"

+

+POWER_MANAGER  mPowerManager;

+

+/**

+  Calling this function causes a system-wide reset. This sets

+  all circuitry within the system to its initial state. This type of reset

+  is asynchronous to system operation and operates without regard to

+  cycle boundaries.

+

+  System reset should not return, if it returns, it means the system does

+  not support cold reset.

+**/

+STATIC VOID

+AcpiGedReset (

+  VOID

+  )

+{

+  MmioWrite8 (

+    (UINTN)mPowerManager.ResetRegAddr,

+    mPowerManager.ResetValue

+    );

+

+  CpuDeadLoop ();

+}

+

+/**

+  This function causes the system to enter a power state equivalent

+    to the ACPI S5 states.

+

+ * */

+STATIC VOID

+AcpiGedShutdown (

+  VOID

+  )

+{

+  MmioWrite8 (

+    (UINTN)mPowerManager.SleepControlRegAddr,

+    (1 << 5) /* enable bit */ |

+    (5 << 2) /* typ == S5  */

+    );

+

+  CpuDeadLoop ();

+}

+

+/**

+  This function causes a system-wide reset (cold reset), in which

+  all circuitry within the system returns to its initial state. This type of

+  reset is asynchronous to system operation and operates without regard to

+  cycle boundaries.

+

+  If this function returns, it means that the system does not support cold

+  reset.

+**/

+VOID EFIAPI

+ResetCold (

+  VOID

+  )

+{

+  AcpiGedReset ();

+}

+

+/**

+  This function causes a system-wide initialization (warm reset), in which all

+  processors are set to their initial state. Pending cycles are not corrupted.

+

+  If this function returns, it means that the system does not support warm

+  reset.

+**/

+VOID EFIAPI

+ResetWarm (

+  VOID

+  )

+{

+  AcpiGedReset ();

+}

+

+/**

+  This function causes a systemwide reset. The exact type of the reset is

+  defined by the EFI_GUID that follows the Null-terminated Unicode string passed

+  into ResetData. If the platform does not recognize the EFI_GUID in ResetData

+  the platform must pick a supported reset type to perform.The platform may

+  optionally log the parameters from any non-normal reset that occurs.

+

+  @param[in]  DataSize   The size, in bytes, of ResetData.

+  @param[in]  ResetData  The data buffer starts with a Null-terminated string,

+                         followed by the EFI_GUID.

+**/

+VOID

+EFIAPI

+ResetPlatformSpecific (

+  IN UINTN  DataSize,

+  IN VOID   *ResetData

+  )

+{

+  AcpiGedReset ();

+}

+

+/**

+  This function causes the system to enter a power state equivalent

+  to the ACPI G2/S5 or G3 states.

+

+  If this function returns, it means that the system does not support shut down

+  reset.

+**/

+VOID EFIAPI

+ResetShutdown (

+  VOID

+  )

+{

+  AcpiGedShutdown ();

+}

diff --git a/OvmfPkg/LoongArchVirt/Library/ResetSystemAcpiLib/ResetSystemAcpiGed.h b/OvmfPkg/LoongArchVirt/Library/ResetSystemAcpiLib/ResetSystemAcpiGed.h
new file mode 100644
index 0000000..06e2572
--- /dev/null
+++ b/OvmfPkg/LoongArchVirt/Library/ResetSystemAcpiLib/ResetSystemAcpiGed.h
@@ -0,0 +1,23 @@
+/** @file

+  ResetSystem lib head file.

+

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

+

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

+

+**/

+

+#ifndef RESET_SYSTEM_ACPI_GED_H_

+#define RESET_SYSTEM_ACPI_GED_H_

+

+#include <Base.h>

+

+typedef struct {

+  UINT64    SleepControlRegAddr;

+  UINT64    SleepStatusRegAddr;

+  UINT64    ResetRegAddr;

+  UINT8     ResetValue;

+} POWER_MANAGER;

+

+extern POWER_MANAGER  mPowerManager;

+#endif // RESET_SYSTEM_ACPI_GED_H_