ArmVirtPsciResetSystemPeiLib.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /** @file
  2. Reset System lib using PSCI hypervisor or secure monitor calls
  3. Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
  4. Copyright (c) 2013, ARM Ltd. All rights reserved.<BR>
  5. Copyright (c) 2014-2020, Linaro Ltd. All rights reserved.<BR>
  6. Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
  7. SPDX-License-Identifier: BSD-2-Clause-Patent
  8. **/
  9. #include <PiPei.h>
  10. #include <libfdt.h>
  11. #include <Library/ArmHvcLib.h>
  12. #include <Library/ArmSmcLib.h>
  13. #include <Library/BaseLib.h>
  14. #include <Library/DebugLib.h>
  15. #include <Library/HobLib.h>
  16. #include <Library/ResetSystemLib.h>
  17. #include <IndustryStandard/ArmStdSmc.h>
  18. typedef enum {
  19. PsciMethodUnknown,
  20. PsciMethodSmc,
  21. PsciMethodHvc,
  22. } PSCI_METHOD;
  23. STATIC
  24. PSCI_METHOD
  25. DiscoverPsciMethod (
  26. VOID
  27. )
  28. {
  29. VOID *DeviceTreeBase;
  30. INT32 Node, Prev;
  31. INT32 Len;
  32. CONST CHAR8 *Compatible;
  33. CONST CHAR8 *CompatibleItem;
  34. CONST VOID *Prop;
  35. DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
  36. ASSERT (fdt_check_header (DeviceTreeBase) == 0);
  37. //
  38. // Enumerate all FDT nodes looking for the PSCI node and capture the method
  39. //
  40. for (Prev = 0; ; Prev = Node) {
  41. Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
  42. if (Node < 0) {
  43. break;
  44. }
  45. Compatible = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len);
  46. if (Compatible == NULL) {
  47. continue;
  48. }
  49. //
  50. // Iterate over the NULL-separated items in the compatible string
  51. //
  52. for (CompatibleItem = Compatible; CompatibleItem < Compatible + Len;
  53. CompatibleItem += 1 + AsciiStrLen (CompatibleItem))
  54. {
  55. if (AsciiStrCmp (CompatibleItem, "arm,psci-0.2") != 0) {
  56. continue;
  57. }
  58. Prop = fdt_getprop (DeviceTreeBase, Node, "method", NULL);
  59. if (!Prop) {
  60. DEBUG ((
  61. DEBUG_ERROR,
  62. "%a: Missing PSCI method property\n",
  63. __FUNCTION__
  64. ));
  65. return PsciMethodUnknown;
  66. }
  67. if (AsciiStrnCmp (Prop, "hvc", 3) == 0) {
  68. return PsciMethodHvc;
  69. } else if (AsciiStrnCmp (Prop, "smc", 3) == 0) {
  70. return PsciMethodSmc;
  71. } else {
  72. DEBUG ((
  73. DEBUG_ERROR,
  74. "%a: Unknown PSCI method \"%a\"\n",
  75. __FUNCTION__,
  76. Prop
  77. ));
  78. return PsciMethodUnknown;
  79. }
  80. }
  81. }
  82. return PsciMethodUnknown;
  83. }
  84. STATIC
  85. VOID
  86. PerformPsciAction (
  87. IN UINTN Arg0
  88. )
  89. {
  90. ARM_SMC_ARGS ArmSmcArgs;
  91. ARM_HVC_ARGS ArmHvcArgs;
  92. ArmSmcArgs.Arg0 = Arg0;
  93. ArmHvcArgs.Arg0 = Arg0;
  94. switch (DiscoverPsciMethod ()) {
  95. case PsciMethodHvc:
  96. ArmCallHvc (&ArmHvcArgs);
  97. break;
  98. case PsciMethodSmc:
  99. ArmCallSmc (&ArmSmcArgs);
  100. break;
  101. default:
  102. DEBUG ((DEBUG_ERROR, "%a: no PSCI method defined\n", __FUNCTION__));
  103. ASSERT (FALSE);
  104. }
  105. }
  106. /**
  107. This function causes a system-wide reset (cold reset), in which
  108. all circuitry within the system returns to its initial state. This type of reset
  109. is asynchronous to system operation and operates without regard to
  110. cycle boundaries.
  111. If this function returns, it means that the system does not support cold reset.
  112. **/
  113. VOID
  114. EFIAPI
  115. ResetCold (
  116. VOID
  117. )
  118. {
  119. // Send a PSCI 0.2 SYSTEM_RESET command
  120. PerformPsciAction (ARM_SMC_ID_PSCI_SYSTEM_RESET);
  121. }
  122. /**
  123. This function causes a system-wide initialization (warm reset), in which all processors
  124. are set to their initial state. Pending cycles are not corrupted.
  125. If this function returns, it means that the system does not support warm reset.
  126. **/
  127. VOID
  128. EFIAPI
  129. ResetWarm (
  130. VOID
  131. )
  132. {
  133. // Map a warm reset into a cold reset
  134. ResetCold ();
  135. }
  136. /**
  137. This function causes the system to enter a power state equivalent
  138. to the ACPI G2/S5 or G3 states.
  139. If this function returns, it means that the system does not support shutdown reset.
  140. **/
  141. VOID
  142. EFIAPI
  143. ResetShutdown (
  144. VOID
  145. )
  146. {
  147. // Send a PSCI 0.2 SYSTEM_OFF command
  148. PerformPsciAction (ARM_SMC_ID_PSCI_SYSTEM_OFF);
  149. }
  150. /**
  151. This function causes a systemwide reset. The exact type of the reset is
  152. defined by the EFI_GUID that follows the Null-terminated Unicode string passed
  153. into ResetData. If the platform does not recognize the EFI_GUID in ResetData
  154. the platform must pick a supported reset type to perform.The platform may
  155. optionally log the parameters from any non-normal reset that occurs.
  156. @param[in] DataSize The size, in bytes, of ResetData.
  157. @param[in] ResetData The data buffer starts with a Null-terminated string,
  158. followed by the EFI_GUID.
  159. **/
  160. VOID
  161. EFIAPI
  162. ResetPlatformSpecific (
  163. IN UINTN DataSize,
  164. IN VOID *ResetData
  165. )
  166. {
  167. // Map the platform specific reset as reboot
  168. ResetCold ();
  169. }
  170. /**
  171. The ResetSystem function resets the entire platform.
  172. @param[in] ResetType The type of reset to perform.
  173. @param[in] ResetStatus The status code for the reset.
  174. @param[in] DataSize The size, in bytes, of ResetData.
  175. @param[in] ResetData For a ResetType of EfiResetCold, EfiResetWarm, or EfiResetShutdown
  176. the data buffer starts with a Null-terminated string, optionally
  177. followed by additional binary data. The string is a description
  178. that the caller may use to further indicate the reason for the
  179. system reset.
  180. **/
  181. VOID
  182. EFIAPI
  183. ResetSystem (
  184. IN EFI_RESET_TYPE ResetType,
  185. IN EFI_STATUS ResetStatus,
  186. IN UINTN DataSize,
  187. IN VOID *ResetData OPTIONAL
  188. )
  189. {
  190. switch (ResetType) {
  191. case EfiResetWarm:
  192. ResetWarm ();
  193. break;
  194. case EfiResetCold:
  195. ResetCold ();
  196. break;
  197. case EfiResetShutdown:
  198. ResetShutdown ();
  199. return;
  200. case EfiResetPlatformSpecific:
  201. ResetPlatformSpecific (DataSize, ResetData);
  202. return;
  203. default:
  204. return;
  205. }
  206. }