2 Implementation of Reset2, ResetFilter and ResetHandler PPIs.
4 Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "ResetSystem.h"
12 GLOBAL_REMOVE_IF_UNREFERENCED CHAR16
*mResetTypeStr
[] = {
13 L
"Cold", L
"Warm", L
"Shutdown", L
"PlatformSpecific"
16 EFI_PEI_RESET2_PPI mPpiReset2
= {
20 EFI_GUID
*mProcessingOrder
[] = {
21 &gEdkiiPlatformSpecificResetFilterPpiGuid
,
22 &gEdkiiPlatformSpecificResetNotificationPpiGuid
,
23 &gEdkiiPlatformSpecificResetHandlerPpiGuid
26 RESET_FILTER_INSTANCE mResetFilter
= {
31 &gEdkiiPlatformSpecificResetFilterPpiGuid
34 RESET_FILTER_INSTANCE mResetNotification
= {
39 &gEdkiiPlatformSpecificResetNotificationPpiGuid
42 RESET_FILTER_INSTANCE mResetHandler
= {
47 &gEdkiiPlatformSpecificResetHandlerPpiGuid
50 EFI_PEI_PPI_DESCRIPTOR mPpiListReset
[] = {
52 EFI_PEI_PPI_DESCRIPTOR_PPI
,
53 &gEfiPeiReset2PpiGuid
,
57 EFI_PEI_PPI_DESCRIPTOR_PPI
,
58 &gEdkiiPlatformSpecificResetFilterPpiGuid
,
59 &mResetFilter
.ResetFilter
62 EFI_PEI_PPI_DESCRIPTOR_PPI
,
63 &gEdkiiPlatformSpecificResetNotificationPpiGuid
,
64 &mResetNotification
.ResetFilter
67 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
68 &gEdkiiPlatformSpecificResetHandlerPpiGuid
,
69 &mResetHandler
.ResetFilter
74 Register a notification function to be called when ResetSystem() is called.
76 The RegisterResetNotify() function registers a notification function that is called when
77 ResetSystem() is called and prior to completing the reset of the platform.
78 The registered functions must not perform a platform reset themselves. These
79 notifications are intended only for the notification of components which may need some
80 special-purpose maintenance prior to the platform resetting.
81 The list of registered reset notification functions are processed if ResetSystem()is called
82 before ExitBootServices(). The list of registered reset notification functions is ignored if
83 ResetSystem() is called after ExitBootServices().
85 @param[in] This A pointer to the EFI_RESET_NOTIFICATION_PROTOCOL instance.
86 @param[in] ResetFunction Points to the function to be called when a ResetSystem() is executed.
88 @retval EFI_SUCCESS The reset notification function was successfully registered.
89 @retval EFI_INVALID_PARAMETER ResetFunction is NULL.
90 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to register the reset notification function.
91 @retval EFI_ALREADY_STARTED The reset notification function specified by ResetFunction has already been registered.
97 IN EDKII_PLATFORM_SPECIFIC_RESET_FILTER_PPI
*This
,
98 IN EFI_RESET_SYSTEM ResetFunction
101 RESET_FILTER_INSTANCE
*ResetFilter
;
102 RESET_FILTER_LIST
*List
;
106 if (ResetFunction
== NULL
) {
107 return EFI_INVALID_PARAMETER
;
110 ResetFilter
= (RESET_FILTER_INSTANCE
*)This
;
112 CompareGuid (ResetFilter
->Guid
, &gEdkiiPlatformSpecificResetFilterPpiGuid
) ||
113 CompareGuid (ResetFilter
->Guid
, &gEdkiiPlatformSpecificResetNotificationPpiGuid
) ||
114 CompareGuid (ResetFilter
->Guid
, &gEdkiiPlatformSpecificResetHandlerPpiGuid
)
117 Hob
= GetFirstGuidHob (ResetFilter
->Guid
);
120 // When the GUIDed HOB doesn't exist, create it.
122 List
= (RESET_FILTER_LIST
*)BuildGuidHob (
124 sizeof (RESET_FILTER_LIST
) + sizeof (EFI_RESET_SYSTEM
) * PcdGet32 (PcdMaximumPeiResetNotifies
)
127 return EFI_OUT_OF_RESOURCES
;
130 List
->Signature
= RESET_FILTER_LIST_SIGNATURE
;
131 List
->Count
= PcdGet32 (PcdMaximumPeiResetNotifies
);
132 ZeroMem (List
->ResetFilters
, sizeof (EFI_RESET_SYSTEM
) * List
->Count
);
133 List
->ResetFilters
[0] = ResetFunction
;
136 List
= (RESET_FILTER_LIST
*)GET_GUID_HOB_DATA (Hob
);
137 ASSERT (List
->Signature
== RESET_FILTER_LIST_SIGNATURE
);
139 // Firstly check whether the ResetFunction is already registerred.
141 for (Index
= 0; Index
< List
->Count
; Index
++) {
142 if (List
->ResetFilters
[Index
] == ResetFunction
) {
147 if (Index
!= List
->Count
) {
148 return EFI_ALREADY_STARTED
;
152 // Secondly find the first free slot.
154 for (Index
= 0; Index
< List
->Count
; Index
++) {
155 if (List
->ResetFilters
[Index
] == NULL
) {
160 if (Index
== List
->Count
) {
161 return EFI_OUT_OF_RESOURCES
;
164 List
->ResetFilters
[Index
] = ResetFunction
;
170 Unregister a notification function.
172 The UnregisterResetNotify() function removes the previously registered
173 notification using RegisterResetNotify().
175 @param[in] This A pointer to the EFI_RESET_NOTIFICATION_PROTOCOL instance.
176 @param[in] ResetFunction The pointer to the ResetFunction being unregistered.
178 @retval EFI_SUCCESS The reset notification function was unregistered.
179 @retval EFI_INVALID_PARAMETER ResetFunction is NULL.
180 @retval EFI_INVALID_PARAMETER The reset notification function specified by ResetFunction was not previously
181 registered using RegisterResetNotify().
186 UnregisterResetNotify (
187 IN EDKII_PLATFORM_SPECIFIC_RESET_FILTER_PPI
*This
,
188 IN EFI_RESET_SYSTEM ResetFunction
191 RESET_FILTER_INSTANCE
*ResetFilter
;
192 RESET_FILTER_LIST
*List
;
196 if (ResetFunction
== NULL
) {
197 return EFI_INVALID_PARAMETER
;
200 ResetFilter
= (RESET_FILTER_INSTANCE
*)This
;
202 CompareGuid (ResetFilter
->Guid
, &gEdkiiPlatformSpecificResetFilterPpiGuid
) ||
203 CompareGuid (ResetFilter
->Guid
, &gEdkiiPlatformSpecificResetNotificationPpiGuid
) ||
204 CompareGuid (ResetFilter
->Guid
, &gEdkiiPlatformSpecificResetHandlerPpiGuid
)
207 Hob
= GetFirstGuidHob (ResetFilter
->Guid
);
209 return EFI_INVALID_PARAMETER
;
212 List
= (RESET_FILTER_LIST
*)GET_GUID_HOB_DATA (Hob
);
213 ASSERT (List
->Signature
== RESET_FILTER_LIST_SIGNATURE
);
214 for (Index
= 0; Index
< List
->Count
; Index
++) {
215 if (List
->ResetFilters
[Index
] == ResetFunction
) {
220 if (Index
== List
->Count
) {
221 return EFI_INVALID_PARAMETER
;
224 List
->ResetFilters
[Index
] = NULL
;
229 The PEIM's entry point.
231 It initializes the Reset2, ResetFilter and ResetHandler PPIs.
233 @param[in] FileHandle Handle of the file being invoked.
234 @param[in] PeiServices Describes the list of possible PEI Services.
236 @retval EFI_SUCCESS The entry point is executed successfully.
237 @retval EFI_ALREADY_STARTED The Reset2 PPI was already installed.
238 @retval others Status code returned from PeiServicesInstallPpi().
243 InitializeResetSystem (
244 IN EFI_PEI_FILE_HANDLE FileHandle
,
245 IN CONST EFI_PEI_SERVICES
**PeiServices
251 Status
= PeiServicesLocatePpi (&gEfiPeiReset2PpiGuid
, 0, NULL
, (VOID
**)&Ppi
);
252 if (Status
!= EFI_NOT_FOUND
) {
253 return EFI_ALREADY_STARTED
;
256 PeiServicesInstallPpi (mPpiListReset
);
262 Resets the entire platform.
264 @param[in] ResetType The type of reset to perform.
265 @param[in] ResetStatus The status code for the reset.
266 @param[in] DataSize The size, in bytes, of ResetData.
267 @param[in] ResetData For a ResetType of EfiResetCold, EfiResetWarm, or
268 EfiResetShutdown the data buffer starts with a Null-terminated
269 string, optionally followed by additional binary data.
270 The string is a description that the caller may use to further
271 indicate the reason for the system reset.
272 For a ResetType of EfiResetPlatformSpecific the data buffer
273 also starts with a Null-terminated string that is followed
274 by an EFI_GUID that describes the specific type of reset to perform.
279 IN EFI_RESET_TYPE ResetType
,
280 IN EFI_STATUS ResetStatus
,
282 IN VOID
*ResetData OPTIONAL
287 RESET_FILTER_LIST
*List
;
289 UINT8 RecursionDepth
;
290 UINT8
*RecursionDepthPointer
;
293 // The recursion depth is stored in GUIDed HOB using gEfiCallerIdGuid.
295 Hob
= GetFirstGuidHob (&gEfiCallerIdGuid
);
298 RecursionDepthPointer
= BuildGuidDataHob (&gEfiCallerIdGuid
, &RecursionDepth
, sizeof (RecursionDepth
));
300 RecursionDepthPointer
= (UINT8
*)GET_GUID_HOB_DATA (Hob
);
304 // Only do REPORT_STATUS_CODE() on first call to ResetSystem()
306 if (*RecursionDepthPointer
== 0) {
308 // Indicate reset system PEI service is called.
310 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_SOFTWARE_PEI_SERVICE
| EFI_SW_PS_PC_RESET_SYSTEM
));
314 // Increase the call depth
316 (*RecursionDepthPointer
)++;
317 DEBUG ((DEBUG_INFO
, "PEI ResetSystem2: Reset call depth = %d.\n", *RecursionDepthPointer
));
319 if (*RecursionDepthPointer
<= MAX_RESET_NOTIFY_DEPTH
) {
321 // Iteratively call Reset Filters and Reset Handlers.
323 for (OrderIndex
= 0; OrderIndex
< ARRAY_SIZE (mProcessingOrder
); OrderIndex
++) {
324 Hob
= GetFirstGuidHob (mProcessingOrder
[OrderIndex
]);
326 List
= (RESET_FILTER_LIST
*)GET_GUID_HOB_DATA (Hob
);
327 ASSERT (List
->Signature
== RESET_FILTER_LIST_SIGNATURE
);
329 for (Index
= 0; Index
< List
->Count
; Index
++) {
330 if (List
->ResetFilters
[Index
] != NULL
) {
331 List
->ResetFilters
[Index
](ResetType
, ResetStatus
, DataSize
, ResetData
);
337 ASSERT (ResetType
< ARRAY_SIZE (mResetTypeStr
));
338 DEBUG ((DEBUG_ERROR
, "PEI ResetSystem2: Maximum reset call depth is met. Use the current reset type: %s!\n", mResetTypeStr
[ResetType
]));
350 case EfiResetShutdown
:
354 case EfiResetPlatformSpecific
:
355 ResetPlatformSpecific (DataSize
, ResetData
);
363 // Given we should have reset getting here would be bad