3 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
16 Tiano PEIM to provide the platform recovery functionality.
20 #include "PlatformEarlyInit.h"
22 #define PEI_FVMAIN_COMPACT_GUID \
23 {0x4A538818, 0x5AE0, 0x4eb2, 0xB2, 0xEB, 0x48, 0x8b, 0x23, 0x65, 0x70, 0x22};
25 EFI_GUID FvMainCompactFileGuid
= PEI_FVMAIN_COMPACT_GUID
;
32 PlatformRecoveryModule (
33 IN CONST EFI_PEI_SERVICES
**PeiServices
,
34 IN EFI_PEI_RECOVERY_MODULE_PPI
*This
45 UINT32 CapsuleImageSize
;
46 UINT32 SequenceNumber
;
48 UINT32 OffsetToSplitInformation
;
49 UINT32 OffsetToCapsuleBody
;
50 UINT32 OffsetToOemDefinedHeader
;
51 UINT32 OffsetToAuthorInformation
;
52 UINT32 OffsetToRevisionInformation
;
53 UINT32 OffsetToShortDescription
;
54 UINT32 OffsetToLongDescription
;
55 UINT32 OffsetToApplicableDevices
;
56 } OLD_EFI_CAPSULE_HEADER
;
59 static EFI_PEI_RECOVERY_MODULE_PPI mRecoveryPpi
= {
60 PlatformRecoveryModule
63 static EFI_PEI_PPI_DESCRIPTOR mRecoveryPpiList
= {
64 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
65 &gEfiPeiRecoveryModulePpiGuid
,
70 Provide the functionality of the Recovery Module.
72 @param PeiServices General purpose services available to every PEIM.
74 @retval Status EFI_SUCCESS if the interface could be successfully
80 PeimInitializeRecovery (
81 IN CONST EFI_PEI_SERVICES
**PeiServices
86 Status
= (*PeiServices
)->InstallPpi (
95 Provide the functionality of the Ea Recovery Module.
97 @param PeiServices General purpose services available to every PEIM.
98 @param This Pointer to PEI_RECOVERY_MODULE_INTERFACE.
100 @retval EFI_SUCCESS If the interface could be successfully
102 @retval EFI_UNSUPPORTED Not supported.
107 PlatformRecoveryModule (
108 IN CONST EFI_PEI_SERVICES
**PeiServices
,
109 IN EFI_PEI_RECOVERY_MODULE_PPI
*This
113 EFI_PEI_DEVICE_RECOVERY_MODULE_PPI
*DeviceRecoveryModule
;
114 UINTN NumberOfImageProviders
;
115 BOOLEAN ProviderAvailable
;
116 UINTN NumberRecoveryCapsules
;
117 UINTN RecoveryCapsuleSize
;
120 EFI_PHYSICAL_ADDRESS Address
;
122 OLD_EFI_CAPSULE_HEADER
*CapsuleHeader
;
123 EFI_PEI_HOB_POINTERS Hob
;
124 EFI_PEI_HOB_POINTERS HobOld
;
125 EFI_HOB_CAPSULE_VOLUME
*CapsuleHob
;
127 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
130 BOOLEAN FoundCapsule
;
131 static EFI_GUID mEfiCapsuleHeaderGuid
= EFI_CAPSULE_GUID
;
132 EFI_PEI_STALL_PPI
*StallPpi
;
134 (*PeiServices
)->ReportStatusCode (
137 EFI_SOFTWARE_PEI_MODULE
| EFI_SW_PEIM_PC_RECOVERY_BEGIN
,
143 Status
= (**PeiServices
).LocatePpi (
145 &gEfiPeiStallPpiGuid
,
150 ASSERT_EFI_ERROR (Status
);
161 Status
= EFI_SUCCESS
;
164 ProviderAvailable
= TRUE
;
166 NumberOfImageProviders
= 0;
168 DeviceRecoveryModule
= NULL
;
170 FoundCapsule
= FALSE
;
173 DEBUG ((EFI_D_ERROR
| EFI_D_LOAD
, "Recovery Entry\n"));
176 // Search the platform for some recovery capsule if the DXE IPL
177 // discovered a recovery condition and has requested a load.
179 while (ProviderAvailable
== TRUE
) {
181 Status
= (*PeiServices
)->LocatePpi (
183 &gEfiPeiDeviceRecoveryModulePpiGuid
,
186 &DeviceRecoveryModule
189 if (!EFI_ERROR (Status
)) {
190 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Device Recovery PPI located\n"));
191 NumberOfImageProviders
++;
193 Status
= DeviceRecoveryModule
->GetNumberRecoveryCapsules (
194 (EFI_PEI_SERVICES
**)PeiServices
,
195 DeviceRecoveryModule
,
196 &NumberRecoveryCapsules
199 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Number Of Recovery Capsules: %d\n", NumberRecoveryCapsules
));
201 if (NumberRecoveryCapsules
== 0) {
207 ProviderAvailable
= FALSE
;
212 // If there is an image provider, get the capsule ID
214 if (ProviderAvailable
) {
215 RecoveryCapsuleSize
= 0;
217 Status
= DeviceRecoveryModule
->GetRecoveryCapsuleInfo (
218 (EFI_PEI_SERVICES
**)PeiServices
,
219 DeviceRecoveryModule
,
221 &RecoveryCapsuleSize
,
225 if (EFI_ERROR (Status
)) {
229 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Recovery Capsule Size: %d\n", RecoveryCapsuleSize
));
232 // Only support the 2 capsule types known
233 // Future enhancement is to rank-order the selection
235 if ((!CompareGuid (&DeviceId
, &gRecoveryOnFatIdeDiskGuid
)) &&
236 (!CompareGuid (&DeviceId
, &gRecoveryOnFatFloppyDiskGuid
)) &&
237 (!CompareGuid (&DeviceId
, &gRecoveryOnDataCdGuid
)) &&
238 (!CompareGuid (&DeviceId
, &gRecoveryOnFatUsbDiskGuid
))
240 return EFI_UNSUPPORTED
;
244 Status
= (*PeiServices
)->AllocatePages (
247 (RecoveryCapsuleSize
- 1) / 0x1000 + 1,
251 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "AllocatePage Returns: %r\n", Status
));
253 if (EFI_ERROR(Status
)) {
257 Buffer
= (UINT8
*) (UINTN
) Address
;
259 (*PeiServices
)->ReportStatusCode (
262 EFI_SOFTWARE_PEI_MODULE
| EFI_SW_PEIM_PC_CAPSULE_LOAD
,
268 Status
= DeviceRecoveryModule
->LoadRecoveryCapsule (
269 (EFI_PEI_SERVICES
**)PeiServices
,
270 DeviceRecoveryModule
,
275 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "LoadRecoveryCapsule Returns: %r\n", Status
));
277 if (EFI_ERROR (Status
)) {
282 // Update FV Hob if found
284 Status
= (*PeiServices
)->GetHobList (PeiServices
, &Hob
.Raw
);
285 HobOld
.Raw
= Hob
.Raw
;
286 while (!END_OF_HOB_LIST (Hob
)) {
287 if (Hob
.Header
->HobType
== EFI_HOB_TYPE_FV
) {
288 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Hob FV Length: %x\n", Hob
.FirmwareVolume
->Length
));
290 // BUGBUG Why is it a FV hob if it is greater than 0x50000?
292 if (Hob
.FirmwareVolume
->Length
> 0x50000) {
295 // This looks like the Hob we are interested in
297 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Hob Updated\n"));
298 Hob
.FirmwareVolume
->BaseAddress
= (UINTN
) Buffer
;
299 Hob
.FirmwareVolume
->Length
= RecoveryCapsuleSize
;
302 Hob
.Raw
= GET_NEXT_HOB (Hob
);
305 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)Buffer
;
306 CapsuleHeader
= (OLD_EFI_CAPSULE_HEADER
*)Buffer
;
309 // Check if top of file is a capsule
311 if (CompareGuid ((EFI_GUID
*)CapsuleHeader
, &mEfiCapsuleHeaderGuid
)) {
313 } else if (FvHeader
->Signature
== EFI_FVH_SIGNATURE
) {
315 // Assume the Firmware volume is a "FVMAIN" image
322 // build FV Hob if it is not built before
325 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "FV Hob is not found, Build FV Hob then..\n"));
338 Status
= (*PeiServices
)->CreateHob (
341 sizeof (EFI_HOB_CAPSULE_VOLUME
),
344 if (EFI_ERROR (Status
)) {
347 CapsuleHob
->BaseAddress
= (UINT64
)((UINTN
)CapsuleHeader
+ (UINTN
)CapsuleHeader
->OffsetToCapsuleBody
);
348 CapsuleHob
->Length
= (UINT64
)((UINTN
)CapsuleHeader
->CapsuleImageSize
-(UINTN
)CapsuleHeader
->OffsetToCapsuleBody
);
349 (*PeiServices
)->ReportStatusCode (
352 EFI_SOFTWARE_PEI_MODULE
| EFI_SW_PEIM_PC_CAPSULE_START
,
359 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Recovery Module Returning: %r\n", Status
));