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