DxeResetSystemAcpiGed.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /** @file
  2. Dxe ResetSystem library implementation.
  3. Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <Base.h>
  7. #include <Library/DebugLib.h>
  8. #include <Library/UefiRuntimeLib.h> // EfiConvertPointer()
  9. #include <Library/DxeServicesTableLib.h>
  10. #include <Library/UefiBootServicesTableLib.h>
  11. #include "ResetSystemAcpiGed.h"
  12. #include <Library/UefiLib.h>
  13. /**
  14. Modifies the attributes to Runtime type for a page size memory region.
  15. @param BaseAddress Specified start address
  16. @retval EFI_SUCCESS The attributes were set for the memory region.
  17. @retval EFI_INVALID_PARAMETER Length is zero.
  18. @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
  19. resource range specified by BaseAddress and Length.
  20. @retval EFI_UNSUPPORTED The bit mask of attributes is not support for the memory resource
  21. range specified by BaseAddress and Length.
  22. @retval EFI_ACCESS_DEFINED The attributes for the memory resource range specified by
  23. BaseAddress and Length cannot be modified.
  24. @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
  25. the memory resource range.
  26. @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol is
  27. not available yet.
  28. **/
  29. EFI_STATUS
  30. SetMemoryAttributesRunTime (
  31. UINTN Address
  32. )
  33. {
  34. EFI_STATUS Status;
  35. EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;
  36. Address &= ~EFI_PAGE_MASK;
  37. Status = gDS->GetMemorySpaceDescriptor (Address, &Descriptor);
  38. if (EFI_ERROR (Status)) {
  39. DEBUG ((DEBUG_INFO, "%a: GetMemorySpaceDescriptor failed\n", __FUNCTION__));
  40. return Status;
  41. }
  42. if (Descriptor.GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
  43. Status = gDS->AddMemorySpace (
  44. EfiGcdMemoryTypeMemoryMappedIo,
  45. Address,
  46. EFI_PAGE_SIZE,
  47. EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
  48. );
  49. if (EFI_ERROR (Status)) {
  50. DEBUG ((DEBUG_INFO, "%a: AddMemorySpace failed\n", __FUNCTION__));
  51. return Status;
  52. }
  53. Status = gDS->SetMemorySpaceAttributes (
  54. Address,
  55. EFI_PAGE_SIZE,
  56. EFI_MEMORY_RUNTIME
  57. );
  58. if (EFI_ERROR (Status)) {
  59. DEBUG ((DEBUG_INFO, "%a:%d SetMemorySpaceAttributes failed\n", __FUNCTION__, __LINE__));
  60. return Status;
  61. }
  62. } else if (!(Descriptor.Attributes & EFI_MEMORY_RUNTIME)) {
  63. Status = gDS->SetMemorySpaceAttributes (
  64. Address,
  65. EFI_PAGE_SIZE,
  66. Descriptor.Attributes | EFI_MEMORY_RUNTIME
  67. );
  68. if (EFI_ERROR (Status)) {
  69. DEBUG ((DEBUG_INFO, "%a:%d SetMemorySpaceAttributes failed\n", __FUNCTION__, __LINE__));
  70. return Status;
  71. }
  72. }
  73. return EFI_SUCCESS;
  74. }
  75. /**
  76. Find the power manager related info from ACPI table
  77. @retval RETURN_SUCCESS Successfully find out all the required information.
  78. @retval RETURN_NOT_FOUND Failed to find the required info.
  79. **/
  80. STATIC EFI_STATUS
  81. GetPowerManagerByParseAcpiInfo (
  82. VOID
  83. )
  84. {
  85. EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt = NULL;
  86. EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp = NULL;
  87. EFI_ACPI_DESCRIPTION_HEADER *Xsdt = NULL;
  88. EFI_ACPI_DESCRIPTION_HEADER *Rsdt = NULL;
  89. UINT32 *Entry32 = NULL;
  90. UINTN Entry32Num;
  91. UINT32 *Signature = NULL;
  92. UINTN Idx;
  93. EFI_STATUS Status;
  94. Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID **)&Rsdp);
  95. if (EFI_ERROR (Status)) {
  96. Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **)&Rsdp);
  97. }
  98. if (EFI_ERROR (Status) || (Rsdp == NULL)) {
  99. DEBUG ((DEBUG_ERROR, "EFI_ERROR or Rsdp == NULL\n"));
  100. return RETURN_NOT_FOUND;
  101. }
  102. Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->RsdtAddress;
  103. Entry32 = (UINT32 *)(UINTN)(Rsdt + 1);
  104. Entry32Num = (Rsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) >> 2;
  105. for (Idx = 0; Idx < Entry32Num; Idx++) {
  106. Signature = (UINT32 *)(UINTN)Entry32[Idx];
  107. if (*Signature == EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
  108. Fadt = (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature;
  109. DEBUG ((DEBUG_INFO, "Found Fadt in Rsdt\n"));
  110. goto Done;
  111. }
  112. }
  113. Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)Rsdp->XsdtAddress;
  114. Entry32 = (UINT32 *)(Xsdt + 1);
  115. Entry32Num = (Xsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) >> 2;
  116. for (Idx = 0; Idx < Entry32Num; Idx++) {
  117. Signature = (UINT32 *)(UINTN)Entry32[Idx];
  118. if (*Signature == EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
  119. Fadt = (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature;
  120. DEBUG ((DEBUG_INFO, "Found Fadt in Xsdt\n"));
  121. goto Done;
  122. }
  123. }
  124. DEBUG ((DEBUG_ERROR, " Fadt Not Found\n"));
  125. return RETURN_NOT_FOUND;
  126. Done:
  127. mPowerManager.ResetRegAddr = Fadt->ResetReg.Address;
  128. mPowerManager.ResetValue = Fadt->ResetValue;
  129. mPowerManager.SleepControlRegAddr = Fadt->SleepControlReg.Address;
  130. mPowerManager.SleepStatusRegAddr = Fadt->SleepStatusReg.Address;
  131. return RETURN_SUCCESS;
  132. }
  133. /**
  134. This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
  135. event. It converts a pointer to a new virtual address.
  136. @param[in] Event Event whose notification function is being invoked.
  137. @param[in] Context Pointer to the notification function's context
  138. **/
  139. VOID
  140. EFIAPI
  141. ResetSystemLibAddressChangeEvent (
  142. IN EFI_EVENT Event,
  143. IN VOID *Context
  144. )
  145. {
  146. EfiConvertPointer (0, (VOID **)&mPowerManager.SleepControlRegAddr);
  147. EfiConvertPointer (0, (VOID **)&mPowerManager.SleepStatusRegAddr);
  148. EfiConvertPointer (0, (VOID **)&mPowerManager.ResetRegAddr);
  149. }
  150. /**
  151. Notification function of ACPI Table change.
  152. This is a notification function registered on ACPI Table change event.
  153. It saves the Century address stored in ACPI FADT table.
  154. @param Event Event whose notification function is being invoked.
  155. @param Context Pointer to the notification function's context.
  156. **/
  157. STATIC VOID
  158. AcpiNotificationEvent (
  159. IN EFI_EVENT Event,
  160. IN VOID *Context
  161. )
  162. {
  163. EFI_STATUS Status;
  164. Status = GetPowerManagerByParseAcpiInfo ();
  165. if (EFI_ERROR (Status)) {
  166. return ;
  167. }
  168. DEBUG ((DEBUG_INFO, "%a: sleepControl %llx\n", __FUNCTION__, mPowerManager.SleepControlRegAddr));
  169. ASSERT (mPowerManager.SleepControlRegAddr);
  170. Status = SetMemoryAttributesRunTime (mPowerManager.SleepControlRegAddr);
  171. if (EFI_ERROR (Status)) {
  172. DEBUG ((DEBUG_INFO, "%a:%d\n", __FUNCTION__, __LINE__));
  173. return ;
  174. }
  175. DEBUG ((DEBUG_INFO, "%a: sleepStatus %llx\n", __FUNCTION__, mPowerManager.SleepStatusRegAddr));
  176. ASSERT (mPowerManager.SleepStatusRegAddr);
  177. Status = SetMemoryAttributesRunTime (mPowerManager.SleepStatusRegAddr);
  178. if (EFI_ERROR (Status)) {
  179. DEBUG ((DEBUG_INFO, "%a:%d\n", __FUNCTION__, __LINE__));
  180. return ;
  181. }
  182. DEBUG ((DEBUG_INFO, "%a: ResetReg %llx\n", __FUNCTION__, mPowerManager.ResetRegAddr));
  183. ASSERT (mPowerManager.ResetRegAddr);
  184. Status = SetMemoryAttributesRunTime (mPowerManager.ResetRegAddr);
  185. if (EFI_ERROR (Status)) {
  186. DEBUG ((DEBUG_INFO, "%a:%d\n", __FUNCTION__, __LINE__));
  187. }
  188. return ;
  189. }
  190. /**
  191. The constructor function to Register ACPI Table change event and Address Change Event.
  192. @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS.
  193. **/
  194. EFI_STATUS
  195. EFIAPI
  196. ResetSystemLibConstructor (
  197. IN EFI_HANDLE ImageHandle,
  198. IN EFI_SYSTEM_TABLE *SystemTable
  199. )
  200. {
  201. EFI_STATUS Status;
  202. EFI_EVENT Event;
  203. EFI_EVENT ResetSystemVirtualNotifyEvent;
  204. Status = gBS->CreateEventEx (
  205. EVT_NOTIFY_SIGNAL,
  206. TPL_CALLBACK,
  207. AcpiNotificationEvent,
  208. NULL,
  209. &gEfiAcpiTableGuid,
  210. &Event
  211. );
  212. //
  213. // Register SetVirtualAddressMap () notify function
  214. //
  215. Status = gBS->CreateEvent (
  216. EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
  217. TPL_NOTIFY,
  218. ResetSystemLibAddressChangeEvent,
  219. NULL,
  220. &ResetSystemVirtualNotifyEvent
  221. );
  222. ASSERT_EFI_ERROR (Status);
  223. return Status;
  224. }