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