[edk2-devel] [edk2-platforms][PATCH V5 13/15] Platform/Loongson: Add Reset System Lib.

xianglai posted 15 patches 2 months, 4 weeks ago
There is a newer version of this series
[edk2-devel] [edk2-platforms][PATCH V5 13/15] Platform/Loongson: Add Reset System Lib.
Posted by xianglai 2 months, 4 weeks ago
This library provides interfaces related to restart and shutdown.

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4054

Cc: Bibo Mao <maobibo@loongson.cn>
Cc: Chao Li <lichao@loongson.cn>
Cc: Leif Lindholm <quic_llindhol@quicinc.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Signed-off-by: xianglai li <lixianglai@loongson.cn>
---
 .../BaseResetSystemAcpiGed.c                  | 146 ++++++++++
 .../BaseResetSystemAcpiGedLib.inf             |  37 +++
 .../DxeResetSystemAcpiGed.c                   | 257 ++++++++++++++++++
 .../DxeResetSystemAcpiGedLib.inf              |  41 +++
 .../ResetSystemAcpiLib/ResetSystemAcpiGed.c   | 128 +++++++++
 .../ResetSystemAcpiLib/ResetSystemAcpiGed.h   |  23 ++
 6 files changed, 632 insertions(+)
 create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/BaseResetSystemAcpiGed.c
 create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/BaseResetSystemAcpiGedLib.inf
 create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/DxeResetSystemAcpiGed.c
 create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/DxeResetSystemAcpiGedLib.inf
 create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/ResetSystemAcpiGed.c
 create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/ResetSystemAcpiGed.h

diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/BaseResetSystemAcpiGed.c b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/BaseResetSystemAcpiGed.c
new file mode 100644
index 0000000000..0df629ffcd
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/BaseResetSystemAcpiGed.c
@@ -0,0 +1,146 @@
+/** @file
+  Base ResetSystem library implementation.
+
+  Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include "ResetSystemAcpiGed.h"
+#include <Library/QemuFwCfgLib.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.
+**/
+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 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;
+  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 RETURN_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 RETURN_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 RETURN_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 RETURN_SUCCESS;
+}
+
+/**
+  The constructor function to initialize mPowerManager.
+
+  @retval EFI_SUCCESS   initialize mPowerManager success.
+  @retval RETURN_NOT_FOUND   Failed to initialize mPowerManager.
+**/
+EFI_STATUS
+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",  __FUNCTION__, __LINE__));
+  }
+
+  ASSERT (mPowerManager.SleepControlRegAddr);
+  ASSERT (mPowerManager.SleepStatusRegAddr);
+  ASSERT (mPowerManager.ResetRegAddr);
+  return Status;
+}
diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/BaseResetSystemAcpiGedLib.inf b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/BaseResetSystemAcpiGedLib.inf
new file mode 100644
index 0000000000..120dd7dcff
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/BaseResetSystemAcpiGedLib.inf
@@ -0,0 +1,37 @@
+## @file
+#  Base library instance for ResetSystem library class for loongarhch
+#
+#  Copyright (c) 2022 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                      = 3d6faf60-804a-4ca9-a36a-1a92416919d0
+  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]
+  BaseLib
+  DebugLib
+  QemuFwCfgLib
+  MemoryAllocationLib
+  IoLib
diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/DxeResetSystemAcpiGed.c b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/DxeResetSystemAcpiGed.c
new file mode 100644
index 0000000000..ef48946ae4
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/DxeResetSystemAcpiGed.c
@@ -0,0 +1,257 @@
+/** @file
+  Dxe ResetSystem library implementation.
+
+  Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiRuntimeLib.h> // EfiConvertPointer()
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include "ResetSystemAcpiGed.h"
+#include <Library/UefiLib.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.
+**/
+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", __FUNCTION__));
+    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", __FUNCTION__));
+      return Status;
+    }
+
+    Status = gDS->SetMemorySpaceAttributes (
+                  Address,
+                  EFI_PAGE_SIZE,
+                  EFI_MEMORY_RUNTIME
+                  );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_INFO, "%a:%d SetMemorySpaceAttributes failed\n", __FUNCTION__, __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", __FUNCTION__, __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
+**/
+VOID
+EFIAPI
+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", __FUNCTION__, mPowerManager.SleepControlRegAddr));
+  ASSERT (mPowerManager.SleepControlRegAddr);
+  Status =  SetMemoryAttributesRunTime (mPowerManager.SleepControlRegAddr);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO, "%a:%d\n",  __FUNCTION__, __LINE__));
+    return ;
+  }
+
+  DEBUG ((DEBUG_INFO, "%a: sleepStatus %llx\n", __FUNCTION__, mPowerManager.SleepStatusRegAddr));
+  ASSERT (mPowerManager.SleepStatusRegAddr);
+  Status =  SetMemoryAttributesRunTime (mPowerManager.SleepStatusRegAddr);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO, "%a:%d\n",  __FUNCTION__, __LINE__));
+    return ;
+  }
+
+  DEBUG ((DEBUG_INFO, "%a: ResetReg %llx\n", __FUNCTION__, mPowerManager.ResetRegAddr));
+  ASSERT (mPowerManager.ResetRegAddr);
+  Status =  SetMemoryAttributesRunTime (mPowerManager.ResetRegAddr);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO, "%a:%d\n",  __FUNCTION__, __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/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/DxeResetSystemAcpiGedLib.inf b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/DxeResetSystemAcpiGedLib.inf
new file mode 100644
index 0000000000..48c7ea2dc3
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/DxeResetSystemAcpiGedLib.inf
@@ -0,0 +1,41 @@
+## @file
+#  DXE library instance for ResetSystem library class for loongarch.
+#
+#  Copyright (c) 2022 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                      = 3d6faf60-804a-4ca9-a36a-1a92416919d0
+  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]
+  BaseLib
+  DebugLib
+  DxeServicesTableLib
+  IoLib
+  UefiLib
+
+[Guids]
+  gEfiAcpi10TableGuid                           ## PRODUCES           ## SystemTable
+  gEfiAcpiTableGuid                             ## PRODUCES           ## SystemTable
diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/ResetSystemAcpiGed.c b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/ResetSystemAcpiGed.c
new file mode 100644
index 0000000000..d15cc70b4b
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/ResetSystemAcpiGed.c
@@ -0,0 +1,128 @@
+/** @file
+  ResetSystem library implementation.
+
+  Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Uefi.h>
+#include <PiPei.h>
+#include <Library/BaseLib.h>        // CpuDeadLoop()
+#include <Library/DebugLib.h>
+#include <Library/ResetSystemLib.h> // ResetCold()
+#include <Library/IoLib.h>
+#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/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/ResetSystemAcpiGed.h b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/ResetSystemAcpiGed.h
new file mode 100644
index 0000000000..e504e870f9
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/ResetSystemAcpiGed.h
@@ -0,0 +1,23 @@
+/** @file
+  ResetSystem lib head file.
+
+  Copyright (c) 2022 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_
-- 
2.31.1




-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#96283): https://edk2.groups.io/g/devel/message/96283
Mute This Topic: https://groups.io/mt/94955180/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [edk2-platforms][PATCH V5 13/15] Platform/Loongson: Add Reset System Lib.
Posted by Chao Li 2 months, 4 weeks ago
Reviewed-by: Chao Li <lichao@loongson.cn>

Thanks,
Chao
--------

On 11月 11 2022, at 5:12 下午, xianglai li <lixianglai@loongson.cn> wrote:
> This library provides interfaces related to restart and shutdown.
>
>
>
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4054
>
>
> Cc: Bibo Mao <maobibo@loongson.cn>
> Cc: Chao Li <lichao@loongson.cn>
> Cc: Leif Lindholm <quic_llindhol@quicinc.com>
> Cc: Liming Gao <gaoliming@byosoft.com.cn>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Signed-off-by: xianglai li <lixianglai@loongson.cn>
> ---
> .../BaseResetSystemAcpiGed.c | 146 ++++++++++
> .../BaseResetSystemAcpiGedLib.inf | 37 +++
> .../DxeResetSystemAcpiGed.c | 257 ++++++++++++++++++
> .../DxeResetSystemAcpiGedLib.inf | 41 +++
> .../ResetSystemAcpiLib/ResetSystemAcpiGed.c | 128 +++++++++
> .../ResetSystemAcpiLib/ResetSystemAcpiGed.h | 23 ++
> 6 files changed, 632 insertions(+)
> create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/BaseResetSystemAcpiGed.c
> create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/BaseResetSystemAcpiGedLib.inf
> create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/DxeResetSystemAcpiGed.c
> create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/DxeResetSystemAcpiGedLib.inf
> create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/ResetSystemAcpiGed.c
> create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/ResetSystemAcpiGed.h
>
>
> diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/BaseResetSystemAcpiGed.c b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/BaseResetSystemAcpiGed.c
> new file mode 100644
> index 0000000000..0df629ffcd
> --- /dev/null
> +++ b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/BaseResetSystemAcpiGed.c
> @@ -0,0 +1,146 @@
> +/** @file
> + Base ResetSystem library implementation.
> +
> + Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Base.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include "ResetSystemAcpiGed.h"
> +#include <Library/QemuFwCfgLib.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.
> +**/
> +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 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;
> + 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 RETURN_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 RETURN_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 RETURN_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 RETURN_SUCCESS;
> +}
> +
> +/**
> + The constructor function to initialize mPowerManager.
> +
> + @retval EFI_SUCCESS initialize mPowerManager success.
> + @retval RETURN_NOT_FOUND Failed to initialize mPowerManager.
> +**/
> +EFI_STATUS
> +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", __FUNCTION__, __LINE__));
> + }
> +
> + ASSERT (mPowerManager.SleepControlRegAddr);
> + ASSERT (mPowerManager.SleepStatusRegAddr);
> + ASSERT (mPowerManager.ResetRegAddr);
> + return Status;
> +}
> diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/BaseResetSystemAcpiGedLib.inf b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/BaseResetSystemAcpiGedLib.inf
> new file mode 100644
> index 0000000000..120dd7dcff
> --- /dev/null
> +++ b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/BaseResetSystemAcpiGedLib.inf
> @@ -0,0 +1,37 @@
> +## @file
> +# Base library instance for ResetSystem library class for loongarhch
> +#
> +# Copyright (c) 2022 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 = 3d6faf60-804a-4ca9-a36a-1a92416919d0
> + 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]
> + BaseLib
> + DebugLib
> + QemuFwCfgLib
> + MemoryAllocationLib
> + IoLib
> diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/DxeResetSystemAcpiGed.c b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/DxeResetSystemAcpiGed.c
> new file mode 100644
> index 0000000000..ef48946ae4
> --- /dev/null
> +++ b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/DxeResetSystemAcpiGed.c
> @@ -0,0 +1,257 @@
> +/** @file
> + Dxe ResetSystem library implementation.
> +
> + Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Base.h>
> +#include <Library/DebugLib.h>
> +#include <Library/UefiRuntimeLib.h> // EfiConvertPointer()
> +#include <Library/DxeServicesTableLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include "ResetSystemAcpiGed.h"
> +#include <Library/UefiLib.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.
> +**/
> +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", __FUNCTION__));
> + 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", __FUNCTION__));
> + return Status;
> + }
> +
> + Status = gDS->SetMemorySpaceAttributes (
> + Address,
> + EFI_PAGE_SIZE,
> + EFI_MEMORY_RUNTIME
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_INFO, "%a:%d SetMemorySpaceAttributes failed\n", __FUNCTION__, __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", __FUNCTION__, __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
> +**/
> +VOID
> +EFIAPI
> +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", __FUNCTION__, mPowerManager.SleepControlRegAddr));
> + ASSERT (mPowerManager.SleepControlRegAddr);
> + Status = SetMemoryAttributesRunTime (mPowerManager.SleepControlRegAddr);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_INFO, "%a:%d\n", __FUNCTION__, __LINE__));
> + return ;
> + }
> +
> + DEBUG ((DEBUG_INFO, "%a: sleepStatus %llx\n", __FUNCTION__, mPowerManager.SleepStatusRegAddr));
> + ASSERT (mPowerManager.SleepStatusRegAddr);
> + Status = SetMemoryAttributesRunTime (mPowerManager.SleepStatusRegAddr);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_INFO, "%a:%d\n", __FUNCTION__, __LINE__));
> + return ;
> + }
> +
> + DEBUG ((DEBUG_INFO, "%a: ResetReg %llx\n", __FUNCTION__, mPowerManager.ResetRegAddr));
> + ASSERT (mPowerManager.ResetRegAddr);
> + Status = SetMemoryAttributesRunTime (mPowerManager.ResetRegAddr);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_INFO, "%a:%d\n", __FUNCTION__, __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/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/DxeResetSystemAcpiGedLib.inf b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/DxeResetSystemAcpiGedLib.inf
> new file mode 100644
> index 0000000000..48c7ea2dc3
> --- /dev/null
> +++ b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/DxeResetSystemAcpiGedLib.inf
> @@ -0,0 +1,41 @@
> +## @file
> +# DXE library instance for ResetSystem library class for loongarch.
> +#
> +# Copyright (c) 2022 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 = 3d6faf60-804a-4ca9-a36a-1a92416919d0
> + 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]
> + BaseLib
> + DebugLib
> + DxeServicesTableLib
> + IoLib
> + UefiLib
> +
> +[Guids]
> + gEfiAcpi10TableGuid ## PRODUCES ## SystemTable
> + gEfiAcpiTableGuid ## PRODUCES ## SystemTable
> diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/ResetSystemAcpiGed.c b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/ResetSystemAcpiGed.c
> new file mode 100644
> index 0000000000..d15cc70b4b
> --- /dev/null
> +++ b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/ResetSystemAcpiGed.c
> @@ -0,0 +1,128 @@
> +/** @file
> + ResetSystem library implementation.
> +
> + Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Base.h>
> +#include <Uefi.h>
> +#include <PiPei.h>
> +#include <Library/BaseLib.h> // CpuDeadLoop()
> +#include <Library/DebugLib.h>
> +#include <Library/ResetSystemLib.h> // ResetCold()
> +#include <Library/IoLib.h>
> +#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/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/ResetSystemAcpiGed.h b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/ResetSystemAcpiGed.h
> new file mode 100644
> index 0000000000..e504e870f9
> --- /dev/null
> +++ b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/ResetSystemAcpiGed.h
> @@ -0,0 +1,23 @@
> +/** @file
> + ResetSystem lib head file.
> +
> + Copyright (c) 2022 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_
> --
> 2.31.1


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#96299): https://edk2.groups.io/g/devel/message/96299
Mute This Topic: https://groups.io/mt/94955180/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-