]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/ResetSystemPei/ResetSystem.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Universal / ResetSystemPei / ResetSystem.c
CommitLineData
052c98ce
RN
1/** @file\r
2 Implementation of Reset2, ResetFilter and ResetHandler PPIs.\r
3\r
3bb9b1fa 4 Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>\r
052c98ce 5\r
9d510e61 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
052c98ce
RN
7\r
8**/\r
9\r
10#include "ResetSystem.h"\r
11\r
1436aea4 12GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mResetTypeStr[] = {\r
052c98ce
RN
13 L"Cold", L"Warm", L"Shutdown", L"PlatformSpecific"\r
14};\r
15\r
1436aea4 16EFI_PEI_RESET2_PPI mPpiReset2 = {\r
052c98ce
RN
17 ResetSystem2\r
18};\r
19\r
1436aea4 20EFI_GUID *mProcessingOrder[] = {\r
052c98ce 21 &gEdkiiPlatformSpecificResetFilterPpiGuid,\r
ce2697ab 22 &gEdkiiPlatformSpecificResetNotificationPpiGuid,\r
052c98ce
RN
23 &gEdkiiPlatformSpecificResetHandlerPpiGuid\r
24};\r
25\r
1436aea4 26RESET_FILTER_INSTANCE mResetFilter = {\r
052c98ce
RN
27 {\r
28 RegisterResetNotify,\r
29 UnregisterResetNotify\r
30 },\r
31 &gEdkiiPlatformSpecificResetFilterPpiGuid\r
32};\r
33\r
1436aea4 34RESET_FILTER_INSTANCE mResetNotification = {\r
ce2697ab
BB
35 {\r
36 RegisterResetNotify,\r
37 UnregisterResetNotify\r
38 },\r
39 &gEdkiiPlatformSpecificResetNotificationPpiGuid\r
40};\r
41\r
1436aea4 42RESET_FILTER_INSTANCE mResetHandler = {\r
052c98ce
RN
43 {\r
44 RegisterResetNotify,\r
45 UnregisterResetNotify\r
46 },\r
47 &gEdkiiPlatformSpecificResetHandlerPpiGuid\r
48};\r
49\r
1436aea4 50EFI_PEI_PPI_DESCRIPTOR mPpiListReset[] = {\r
052c98ce
RN
51 {\r
52 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
53 &gEfiPeiReset2PpiGuid,\r
54 &mPpiReset2\r
55 },\r
56 {\r
57 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
58 &gEdkiiPlatformSpecificResetFilterPpiGuid,\r
59 &mResetFilter.ResetFilter\r
60 },\r
ce2697ab
BB
61 {\r
62 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
63 &gEdkiiPlatformSpecificResetNotificationPpiGuid,\r
64 &mResetNotification.ResetFilter\r
65 },\r
052c98ce
RN
66 {\r
67 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
68 &gEdkiiPlatformSpecificResetHandlerPpiGuid,\r
69 &mResetHandler.ResetFilter\r
70 }\r
71};\r
72\r
73/**\r
74 Register a notification function to be called when ResetSystem() is called.\r
75\r
76 The RegisterResetNotify() function registers a notification function that is called when\r
77 ResetSystem() is called and prior to completing the reset of the platform.\r
78 The registered functions must not perform a platform reset themselves. These\r
79 notifications are intended only for the notification of components which may need some\r
80 special-purpose maintenance prior to the platform resetting.\r
81 The list of registered reset notification functions are processed if ResetSystem()is called\r
82 before ExitBootServices(). The list of registered reset notification functions is ignored if\r
83 ResetSystem() is called after ExitBootServices().\r
84\r
85 @param[in] This A pointer to the EFI_RESET_NOTIFICATION_PROTOCOL instance.\r
86 @param[in] ResetFunction Points to the function to be called when a ResetSystem() is executed.\r
87\r
88 @retval EFI_SUCCESS The reset notification function was successfully registered.\r
89 @retval EFI_INVALID_PARAMETER ResetFunction is NULL.\r
90 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to register the reset notification function.\r
91 @retval EFI_ALREADY_STARTED The reset notification function specified by ResetFunction has already been registered.\r
92\r
93**/\r
94EFI_STATUS\r
95EFIAPI\r
96RegisterResetNotify (\r
1436aea4
MK
97 IN EDKII_PLATFORM_SPECIFIC_RESET_FILTER_PPI *This,\r
98 IN EFI_RESET_SYSTEM ResetFunction\r
052c98ce
RN
99 )\r
100{\r
1436aea4
MK
101 RESET_FILTER_INSTANCE *ResetFilter;\r
102 RESET_FILTER_LIST *List;\r
103 VOID *Hob;\r
104 UINTN Index;\r
052c98ce
RN
105\r
106 if (ResetFunction == NULL) {\r
107 return EFI_INVALID_PARAMETER;\r
108 }\r
109\r
1436aea4
MK
110 ResetFilter = (RESET_FILTER_INSTANCE *)This;\r
111 ASSERT (\r
112 CompareGuid (ResetFilter->Guid, &gEdkiiPlatformSpecificResetFilterPpiGuid) ||\r
113 CompareGuid (ResetFilter->Guid, &gEdkiiPlatformSpecificResetNotificationPpiGuid) ||\r
114 CompareGuid (ResetFilter->Guid, &gEdkiiPlatformSpecificResetHandlerPpiGuid)\r
115 );\r
052c98ce
RN
116\r
117 Hob = GetFirstGuidHob (ResetFilter->Guid);\r
118 if (Hob == NULL) {\r
119 //\r
120 // When the GUIDed HOB doesn't exist, create it.\r
121 //\r
122 List = (RESET_FILTER_LIST *)BuildGuidHob (\r
123 ResetFilter->Guid,\r
124 sizeof (RESET_FILTER_LIST) + sizeof (EFI_RESET_SYSTEM) * PcdGet32 (PcdMaximumPeiResetNotifies)\r
125 );\r
126 if (List == NULL) {\r
127 return EFI_OUT_OF_RESOURCES;\r
128 }\r
1436aea4 129\r
052c98ce
RN
130 List->Signature = RESET_FILTER_LIST_SIGNATURE;\r
131 List->Count = PcdGet32 (PcdMaximumPeiResetNotifies);\r
132 ZeroMem (List->ResetFilters, sizeof (EFI_RESET_SYSTEM) * List->Count);\r
133 List->ResetFilters[0] = ResetFunction;\r
134 return EFI_SUCCESS;\r
135 } else {\r
136 List = (RESET_FILTER_LIST *)GET_GUID_HOB_DATA (Hob);\r
137 ASSERT (List->Signature == RESET_FILTER_LIST_SIGNATURE);\r
138 //\r
139 // Firstly check whether the ResetFunction is already registerred.\r
140 //\r
141 for (Index = 0; Index < List->Count; Index++) {\r
142 if (List->ResetFilters[Index] == ResetFunction) {\r
143 break;\r
144 }\r
145 }\r
1436aea4 146\r
052c98ce
RN
147 if (Index != List->Count) {\r
148 return EFI_ALREADY_STARTED;\r
149 }\r
150\r
151 //\r
152 // Secondly find the first free slot.\r
153 //\r
154 for (Index = 0; Index < List->Count; Index++) {\r
155 if (List->ResetFilters[Index] == NULL) {\r
156 break;\r
157 }\r
158 }\r
159\r
160 if (Index == List->Count) {\r
161 return EFI_OUT_OF_RESOURCES;\r
162 }\r
1436aea4 163\r
052c98ce
RN
164 List->ResetFilters[Index] = ResetFunction;\r
165 return EFI_SUCCESS;\r
166 }\r
167}\r
168\r
169/**\r
170 Unregister a notification function.\r
171\r
172 The UnregisterResetNotify() function removes the previously registered\r
173 notification using RegisterResetNotify().\r
174\r
175 @param[in] This A pointer to the EFI_RESET_NOTIFICATION_PROTOCOL instance.\r
176 @param[in] ResetFunction The pointer to the ResetFunction being unregistered.\r
177\r
178 @retval EFI_SUCCESS The reset notification function was unregistered.\r
179 @retval EFI_INVALID_PARAMETER ResetFunction is NULL.\r
180 @retval EFI_INVALID_PARAMETER The reset notification function specified by ResetFunction was not previously\r
181 registered using RegisterResetNotify().\r
182\r
183**/\r
184EFI_STATUS\r
185EFIAPI\r
186UnregisterResetNotify (\r
1436aea4
MK
187 IN EDKII_PLATFORM_SPECIFIC_RESET_FILTER_PPI *This,\r
188 IN EFI_RESET_SYSTEM ResetFunction\r
052c98ce
RN
189 )\r
190{\r
1436aea4
MK
191 RESET_FILTER_INSTANCE *ResetFilter;\r
192 RESET_FILTER_LIST *List;\r
193 VOID *Hob;\r
194 UINTN Index;\r
052c98ce
RN
195\r
196 if (ResetFunction == NULL) {\r
197 return EFI_INVALID_PARAMETER;\r
198 }\r
199\r
200 ResetFilter = (RESET_FILTER_INSTANCE *)This;\r
1436aea4
MK
201 ASSERT (\r
202 CompareGuid (ResetFilter->Guid, &gEdkiiPlatformSpecificResetFilterPpiGuid) ||\r
ce2697ab 203 CompareGuid (ResetFilter->Guid, &gEdkiiPlatformSpecificResetNotificationPpiGuid) ||\r
052c98ce 204 CompareGuid (ResetFilter->Guid, &gEdkiiPlatformSpecificResetHandlerPpiGuid)\r
1436aea4 205 );\r
052c98ce
RN
206\r
207 Hob = GetFirstGuidHob (ResetFilter->Guid);\r
208 if (Hob == NULL) {\r
209 return EFI_INVALID_PARAMETER;\r
210 }\r
211\r
212 List = (RESET_FILTER_LIST *)GET_GUID_HOB_DATA (Hob);\r
213 ASSERT (List->Signature == RESET_FILTER_LIST_SIGNATURE);\r
214 for (Index = 0; Index < List->Count; Index++) {\r
215 if (List->ResetFilters[Index] == ResetFunction) {\r
216 break;\r
217 }\r
218 }\r
219\r
220 if (Index == List->Count) {\r
221 return EFI_INVALID_PARAMETER;\r
222 }\r
223\r
224 List->ResetFilters[Index] = NULL;\r
225 return EFI_SUCCESS;\r
226}\r
227\r
052c98ce
RN
228/**\r
229 The PEIM's entry point.\r
230\r
231 It initializes the Reset2, ResetFilter and ResetHandler PPIs.\r
232\r
233 @param[in] FileHandle Handle of the file being invoked.\r
234 @param[in] PeiServices Describes the list of possible PEI Services.\r
d1102dba 235\r
052c98ce
RN
236 @retval EFI_SUCCESS The entry point is executed successfully.\r
237 @retval EFI_ALREADY_STARTED The Reset2 PPI was already installed.\r
238 @retval others Status code returned from PeiServicesInstallPpi().\r
239\r
240**/\r
241EFI_STATUS\r
242EFIAPI\r
243InitializeResetSystem (\r
244 IN EFI_PEI_FILE_HANDLE FileHandle,\r
245 IN CONST EFI_PEI_SERVICES **PeiServices\r
246 )\r
247{\r
248 EFI_STATUS Status;\r
249 VOID *Ppi;\r
250\r
251 Status = PeiServicesLocatePpi (&gEfiPeiReset2PpiGuid, 0, NULL, (VOID **)&Ppi);\r
252 if (Status != EFI_NOT_FOUND) {\r
253 return EFI_ALREADY_STARTED;\r
254 }\r
255\r
256 PeiServicesInstallPpi (mPpiListReset);\r
257\r
258 return Status;\r
259}\r
260\r
261/**\r
262 Resets the entire platform.\r
263\r
264 @param[in] ResetType The type of reset to perform.\r
265 @param[in] ResetStatus The status code for the reset.\r
266 @param[in] DataSize The size, in bytes, of ResetData.\r
267 @param[in] ResetData For a ResetType of EfiResetCold, EfiResetWarm, or\r
268 EfiResetShutdown the data buffer starts with a Null-terminated\r
269 string, optionally followed by additional binary data.\r
270 The string is a description that the caller may use to further\r
3bb9b1fa 271 indicate the reason for the system reset.\r
052c98ce
RN
272 For a ResetType of EfiResetPlatformSpecific the data buffer\r
273 also starts with a Null-terminated string that is followed\r
274 by an EFI_GUID that describes the specific type of reset to perform.\r
275**/\r
276VOID\r
277EFIAPI\r
278ResetSystem2 (\r
1436aea4
MK
279 IN EFI_RESET_TYPE ResetType,\r
280 IN EFI_STATUS ResetStatus,\r
281 IN UINTN DataSize,\r
282 IN VOID *ResetData OPTIONAL\r
052c98ce
RN
283 )\r
284{\r
1436aea4
MK
285 VOID *Hob;\r
286 UINTN Index;\r
287 RESET_FILTER_LIST *List;\r
288 UINTN OrderIndex;\r
289 UINT8 RecursionDepth;\r
290 UINT8 *RecursionDepthPointer;\r
052c98ce
RN
291\r
292 //\r
293 // The recursion depth is stored in GUIDed HOB using gEfiCallerIdGuid.\r
294 //\r
295 Hob = GetFirstGuidHob (&gEfiCallerIdGuid);\r
296 if (Hob == NULL) {\r
1436aea4 297 RecursionDepth = 0;\r
052c98ce
RN
298 RecursionDepthPointer = BuildGuidDataHob (&gEfiCallerIdGuid, &RecursionDepth, sizeof (RecursionDepth));\r
299 } else {\r
300 RecursionDepthPointer = (UINT8 *)GET_GUID_HOB_DATA (Hob);\r
301 }\r
1436aea4 302\r
052c98ce
RN
303 //\r
304 // Only do REPORT_STATUS_CODE() on first call to ResetSystem()\r
305 //\r
306 if (*RecursionDepthPointer == 0) {\r
307 //\r
308 // Indicate reset system PEI service is called.\r
309 //\r
310 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_SERVICE | EFI_SW_PS_PC_RESET_SYSTEM));\r
311 }\r
312\r
313 //\r
314 // Increase the call depth\r
315 //\r
316 (*RecursionDepthPointer)++;\r
317 DEBUG ((DEBUG_INFO, "PEI ResetSystem2: Reset call depth = %d.\n", *RecursionDepthPointer));\r
318\r
319 if (*RecursionDepthPointer <= MAX_RESET_NOTIFY_DEPTH) {\r
320 //\r
321 // Iteratively call Reset Filters and Reset Handlers.\r
322 //\r
323 for (OrderIndex = 0; OrderIndex < ARRAY_SIZE (mProcessingOrder); OrderIndex++) {\r
324 Hob = GetFirstGuidHob (mProcessingOrder[OrderIndex]);\r
325 if (Hob != NULL) {\r
326 List = (RESET_FILTER_LIST *)GET_GUID_HOB_DATA (Hob);\r
327 ASSERT (List->Signature == RESET_FILTER_LIST_SIGNATURE);\r
328\r
329 for (Index = 0; Index < List->Count; Index++) {\r
330 if (List->ResetFilters[Index] != NULL) {\r
1436aea4 331 List->ResetFilters[Index](ResetType, ResetStatus, DataSize, ResetData);\r
052c98ce
RN
332 }\r
333 }\r
334 }\r
335 }\r
336 } else {\r
337 ASSERT (ResetType < ARRAY_SIZE (mResetTypeStr));\r
338 DEBUG ((DEBUG_ERROR, "PEI ResetSystem2: Maximum reset call depth is met. Use the current reset type: %s!\n", mResetTypeStr[ResetType]));\r
339 }\r
340\r
341 switch (ResetType) {\r
1436aea4
MK
342 case EfiResetWarm:\r
343 ResetWarm ();\r
344 break;\r
052c98ce 345\r
1436aea4
MK
346 case EfiResetCold:\r
347 ResetCold ();\r
348 break;\r
052c98ce 349\r
1436aea4
MK
350 case EfiResetShutdown:\r
351 ResetShutdown ();\r
352 return;\r
052c98ce 353\r
1436aea4
MK
354 case EfiResetPlatformSpecific:\r
355 ResetPlatformSpecific (DataSize, ResetData);\r
356 return;\r
052c98ce 357\r
1436aea4
MK
358 default:\r
359 return;\r
052c98ce
RN
360 }\r
361\r
362 //\r
363 // Given we should have reset getting here would be bad\r
364 //\r
365 ASSERT (FALSE);\r
366}\r