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