2 Implementation of Reset2, ResetFilter and ResetHandler PPIs.
4 Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "ResetSystem.h"
18 GLOBAL_REMOVE_IF_UNREFERENCED CHAR16
*mResetTypeStr
[] = {
19 L
"Cold", L
"Warm", L
"Shutdown", L
"PlatformSpecific"
22 EFI_PEI_RESET2_PPI mPpiReset2
= {
26 EFI_GUID
*mProcessingOrder
[] = {
27 &gEdkiiPlatformSpecificResetFilterPpiGuid
,
28 &gEdkiiPlatformSpecificResetNotificationPpiGuid
,
29 &gEdkiiPlatformSpecificResetHandlerPpiGuid
32 RESET_FILTER_INSTANCE mResetFilter
= {
37 &gEdkiiPlatformSpecificResetFilterPpiGuid
40 RESET_FILTER_INSTANCE mResetNotification
= {
45 &gEdkiiPlatformSpecificResetNotificationPpiGuid
48 RESET_FILTER_INSTANCE mResetHandler
= {
53 &gEdkiiPlatformSpecificResetHandlerPpiGuid
56 EFI_PEI_PPI_DESCRIPTOR mPpiListReset
[] = {
58 EFI_PEI_PPI_DESCRIPTOR_PPI
,
59 &gEfiPeiReset2PpiGuid
,
63 EFI_PEI_PPI_DESCRIPTOR_PPI
,
64 &gEdkiiPlatformSpecificResetFilterPpiGuid
,
65 &mResetFilter
.ResetFilter
68 EFI_PEI_PPI_DESCRIPTOR_PPI
,
69 &gEdkiiPlatformSpecificResetNotificationPpiGuid
,
70 &mResetNotification
.ResetFilter
73 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
74 &gEdkiiPlatformSpecificResetHandlerPpiGuid
,
75 &mResetHandler
.ResetFilter
80 Register a notification function to be called when ResetSystem() is called.
82 The RegisterResetNotify() function registers a notification function that is called when
83 ResetSystem() is called and prior to completing the reset of the platform.
84 The registered functions must not perform a platform reset themselves. These
85 notifications are intended only for the notification of components which may need some
86 special-purpose maintenance prior to the platform resetting.
87 The list of registered reset notification functions are processed if ResetSystem()is called
88 before ExitBootServices(). The list of registered reset notification functions is ignored if
89 ResetSystem() is called after ExitBootServices().
91 @param[in] This A pointer to the EFI_RESET_NOTIFICATION_PROTOCOL instance.
92 @param[in] ResetFunction Points to the function to be called when a ResetSystem() is executed.
94 @retval EFI_SUCCESS The reset notification function was successfully registered.
95 @retval EFI_INVALID_PARAMETER ResetFunction is NULL.
96 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to register the reset notification function.
97 @retval EFI_ALREADY_STARTED The reset notification function specified by ResetFunction has already been registered.
102 RegisterResetNotify (
103 IN EDKII_PLATFORM_SPECIFIC_RESET_FILTER_PPI
*This
,
104 IN EFI_RESET_SYSTEM ResetFunction
107 RESET_FILTER_INSTANCE
*ResetFilter
;
108 RESET_FILTER_LIST
*List
;
112 if (ResetFunction
== NULL
) {
113 return EFI_INVALID_PARAMETER
;
116 ResetFilter
= (RESET_FILTER_INSTANCE
*) This
;
117 ASSERT (CompareGuid (ResetFilter
->Guid
, &gEdkiiPlatformSpecificResetFilterPpiGuid
) ||
118 CompareGuid (ResetFilter
->Guid
, &gEdkiiPlatformSpecificResetNotificationPpiGuid
) ||
119 CompareGuid (ResetFilter
->Guid
, &gEdkiiPlatformSpecificResetHandlerPpiGuid
)
122 Hob
= GetFirstGuidHob (ResetFilter
->Guid
);
125 // When the GUIDed HOB doesn't exist, create it.
127 List
= (RESET_FILTER_LIST
*)BuildGuidHob (
129 sizeof (RESET_FILTER_LIST
) + sizeof (EFI_RESET_SYSTEM
) * PcdGet32 (PcdMaximumPeiResetNotifies
)
132 return EFI_OUT_OF_RESOURCES
;
134 List
->Signature
= RESET_FILTER_LIST_SIGNATURE
;
135 List
->Count
= PcdGet32 (PcdMaximumPeiResetNotifies
);
136 ZeroMem (List
->ResetFilters
, sizeof (EFI_RESET_SYSTEM
) * List
->Count
);
137 List
->ResetFilters
[0] = ResetFunction
;
140 List
= (RESET_FILTER_LIST
*)GET_GUID_HOB_DATA (Hob
);
141 ASSERT (List
->Signature
== RESET_FILTER_LIST_SIGNATURE
);
143 // Firstly check whether the ResetFunction is already registerred.
145 for (Index
= 0; Index
< List
->Count
; Index
++) {
146 if (List
->ResetFilters
[Index
] == ResetFunction
) {
150 if (Index
!= List
->Count
) {
151 return EFI_ALREADY_STARTED
;
155 // Secondly find the first free slot.
157 for (Index
= 0; Index
< List
->Count
; Index
++) {
158 if (List
->ResetFilters
[Index
] == NULL
) {
163 if (Index
== List
->Count
) {
164 return EFI_OUT_OF_RESOURCES
;
166 List
->ResetFilters
[Index
] = ResetFunction
;
172 Unregister a notification function.
174 The UnregisterResetNotify() function removes the previously registered
175 notification using RegisterResetNotify().
177 @param[in] This A pointer to the EFI_RESET_NOTIFICATION_PROTOCOL instance.
178 @param[in] ResetFunction The pointer to the ResetFunction being unregistered.
180 @retval EFI_SUCCESS The reset notification function was unregistered.
181 @retval EFI_INVALID_PARAMETER ResetFunction is NULL.
182 @retval EFI_INVALID_PARAMETER The reset notification function specified by ResetFunction was not previously
183 registered using RegisterResetNotify().
188 UnregisterResetNotify (
189 IN EDKII_PLATFORM_SPECIFIC_RESET_FILTER_PPI
*This
,
190 IN EFI_RESET_SYSTEM ResetFunction
194 RESET_FILTER_INSTANCE
*ResetFilter
;
195 RESET_FILTER_LIST
*List
;
199 if (ResetFunction
== NULL
) {
200 return EFI_INVALID_PARAMETER
;
203 ResetFilter
= (RESET_FILTER_INSTANCE
*)This
;
204 ASSERT (CompareGuid (ResetFilter
->Guid
, &gEdkiiPlatformSpecificResetFilterPpiGuid
) ||
205 CompareGuid (ResetFilter
->Guid
, &gEdkiiPlatformSpecificResetNotificationPpiGuid
) ||
206 CompareGuid (ResetFilter
->Guid
, &gEdkiiPlatformSpecificResetHandlerPpiGuid
)
209 Hob
= GetFirstGuidHob (ResetFilter
->Guid
);
211 return EFI_INVALID_PARAMETER
;
214 List
= (RESET_FILTER_LIST
*)GET_GUID_HOB_DATA (Hob
);
215 ASSERT (List
->Signature
== RESET_FILTER_LIST_SIGNATURE
);
216 for (Index
= 0; Index
< List
->Count
; Index
++) {
217 if (List
->ResetFilters
[Index
] == ResetFunction
) {
222 if (Index
== List
->Count
) {
223 return EFI_INVALID_PARAMETER
;
226 List
->ResetFilters
[Index
] = NULL
;
232 The PEIM's entry point.
234 It initializes the Reset2, ResetFilter and ResetHandler PPIs.
236 @param[in] FileHandle Handle of the file being invoked.
237 @param[in] PeiServices Describes the list of possible PEI Services.
239 @retval EFI_SUCCESS The entry point is executed successfully.
240 @retval EFI_ALREADY_STARTED The Reset2 PPI was already installed.
241 @retval others Status code returned from PeiServicesInstallPpi().
246 InitializeResetSystem (
247 IN EFI_PEI_FILE_HANDLE FileHandle
,
248 IN CONST EFI_PEI_SERVICES
**PeiServices
254 Status
= PeiServicesLocatePpi (&gEfiPeiReset2PpiGuid
, 0, NULL
, (VOID
**)&Ppi
);
255 if (Status
!= EFI_NOT_FOUND
) {
256 return EFI_ALREADY_STARTED
;
259 PeiServicesInstallPpi (mPpiListReset
);
265 Resets the entire platform.
267 @param[in] ResetType The type of reset to perform.
268 @param[in] ResetStatus The status code for the reset.
269 @param[in] DataSize The size, in bytes, of ResetData.
270 @param[in] ResetData For a ResetType of EfiResetCold, EfiResetWarm, or
271 EfiResetShutdown the data buffer starts with a Null-terminated
272 string, optionally followed by additional binary data.
273 The string is a description that the caller may use to further
274 indicate the reason for the system reset. ResetData is only
275 valid if ResetStatus is something other than EFI_SUCCESS
276 unless the ResetType is EfiResetPlatformSpecific
277 where a minimum amount of ResetData is always required.
278 For a ResetType of EfiResetPlatformSpecific the data buffer
279 also starts with a Null-terminated string that is followed
280 by an EFI_GUID that describes the specific type of reset to perform.
285 IN EFI_RESET_TYPE ResetType
,
286 IN EFI_STATUS ResetStatus
,
288 IN VOID
*ResetData OPTIONAL
293 RESET_FILTER_LIST
*List
;
295 UINT8 RecursionDepth
;
296 UINT8
*RecursionDepthPointer
;
299 // The recursion depth is stored in GUIDed HOB using gEfiCallerIdGuid.
301 Hob
= GetFirstGuidHob (&gEfiCallerIdGuid
);
304 RecursionDepthPointer
= BuildGuidDataHob (&gEfiCallerIdGuid
, &RecursionDepth
, sizeof (RecursionDepth
));
306 RecursionDepthPointer
= (UINT8
*)GET_GUID_HOB_DATA (Hob
);
309 // Only do REPORT_STATUS_CODE() on first call to ResetSystem()
311 if (*RecursionDepthPointer
== 0) {
313 // Indicate reset system PEI service is called.
315 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_SOFTWARE_PEI_SERVICE
| EFI_SW_PS_PC_RESET_SYSTEM
));
319 // Increase the call depth
321 (*RecursionDepthPointer
)++;
322 DEBUG ((DEBUG_INFO
, "PEI ResetSystem2: Reset call depth = %d.\n", *RecursionDepthPointer
));
324 if (*RecursionDepthPointer
<= MAX_RESET_NOTIFY_DEPTH
) {
326 // Iteratively call Reset Filters and Reset Handlers.
328 for (OrderIndex
= 0; OrderIndex
< ARRAY_SIZE (mProcessingOrder
); OrderIndex
++) {
329 Hob
= GetFirstGuidHob (mProcessingOrder
[OrderIndex
]);
331 List
= (RESET_FILTER_LIST
*)GET_GUID_HOB_DATA (Hob
);
332 ASSERT (List
->Signature
== RESET_FILTER_LIST_SIGNATURE
);
334 for (Index
= 0; Index
< List
->Count
; Index
++) {
335 if (List
->ResetFilters
[Index
] != NULL
) {
336 List
->ResetFilters
[Index
] (ResetType
, ResetStatus
, DataSize
, ResetData
);
342 ASSERT (ResetType
< ARRAY_SIZE (mResetTypeStr
));
343 DEBUG ((DEBUG_ERROR
, "PEI ResetSystem2: Maximum reset call depth is met. Use the current reset type: %s!\n", mResetTypeStr
[ResetType
]));
355 case EfiResetShutdown
:
359 case EfiResetPlatformSpecific
:
360 ResetPlatformSpecific (DataSize
, ResetData
);
368 // Given we should have reset getting here would be bad