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