3 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available under
6 the terms and conditions of the BSD License that accompanies this distribution.
7 The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 Tiano PEIM to provide the platform recovery functionality.
25 #include "PlatformEarlyInit.h"
27 #define PEI_FVMAIN_COMPACT_GUID \
28 {0x4A538818, 0x5AE0, 0x4eb2, 0xB2, 0xEB, 0x48, 0x8b, 0x23, 0x65, 0x70, 0x22};
30 EFI_GUID FvMainCompactFileGuid
= PEI_FVMAIN_COMPACT_GUID
;
37 PlatformRecoveryModule (
38 IN CONST EFI_PEI_SERVICES
**PeiServices
,
39 IN EFI_PEI_RECOVERY_MODULE_PPI
*This
50 UINT32 CapsuleImageSize
;
51 UINT32 SequenceNumber
;
53 UINT32 OffsetToSplitInformation
;
54 UINT32 OffsetToCapsuleBody
;
55 UINT32 OffsetToOemDefinedHeader
;
56 UINT32 OffsetToAuthorInformation
;
57 UINT32 OffsetToRevisionInformation
;
58 UINT32 OffsetToShortDescription
;
59 UINT32 OffsetToLongDescription
;
60 UINT32 OffsetToApplicableDevices
;
61 } OLD_EFI_CAPSULE_HEADER
;
64 static EFI_PEI_RECOVERY_MODULE_PPI mRecoveryPpi
= {
65 PlatformRecoveryModule
68 static EFI_PEI_PPI_DESCRIPTOR mRecoveryPpiList
= {
69 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
70 &gEfiPeiRecoveryModulePpiGuid
,
75 Provide the functionality of the Recovery Module.
77 @param PeiServices General purpose services available to every PEIM.
79 @retval Status EFI_SUCCESS if the interface could be successfully
85 PeimInitializeRecovery (
86 IN CONST EFI_PEI_SERVICES
**PeiServices
91 Status
= (*PeiServices
)->InstallPpi (
100 Provide the functionality of the Ea Recovery Module.
102 @param PeiServices General purpose services available to every PEIM.
103 @param This Pointer to PEI_RECOVERY_MODULE_INTERFACE.
105 @retval EFI_SUCCESS If the interface could be successfully
107 @retval EFI_UNSUPPORTED Not supported.
112 PlatformRecoveryModule (
113 IN CONST EFI_PEI_SERVICES
**PeiServices
,
114 IN EFI_PEI_RECOVERY_MODULE_PPI
*This
118 EFI_PEI_DEVICE_RECOVERY_MODULE_PPI
*DeviceRecoveryModule
;
119 UINTN NumberOfImageProviders
;
120 BOOLEAN ProviderAvailable
;
121 UINTN NumberRecoveryCapsules
;
122 UINTN RecoveryCapsuleSize
;
125 EFI_PHYSICAL_ADDRESS Address
;
127 OLD_EFI_CAPSULE_HEADER
*CapsuleHeader
;
128 EFI_PEI_HOB_POINTERS Hob
;
129 EFI_PEI_HOB_POINTERS HobOld
;
130 EFI_HOB_CAPSULE_VOLUME
*CapsuleHob
;
132 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
135 BOOLEAN FoundCapsule
;
136 static EFI_GUID mEfiCapsuleHeaderGuid
= EFI_CAPSULE_GUID
;
137 EFI_PEI_STALL_PPI
*StallPpi
;
139 (*PeiServices
)->ReportStatusCode (
142 EFI_SOFTWARE_PEI_MODULE
| EFI_SW_PEIM_PC_RECOVERY_BEGIN
,
148 Status
= (**PeiServices
).LocatePpi (
150 &gEfiPeiStallPpiGuid
,
155 ASSERT_EFI_ERROR (Status
);
166 Status
= EFI_SUCCESS
;
169 ProviderAvailable
= TRUE
;
171 NumberOfImageProviders
= 0;
173 DeviceRecoveryModule
= NULL
;
175 FoundCapsule
= FALSE
;
178 DEBUG ((EFI_D_ERROR
| EFI_D_LOAD
, "Recovery Entry\n"));
181 // Search the platform for some recovery capsule if the DXE IPL
182 // discovered a recovery condition and has requested a load.
184 while (ProviderAvailable
== TRUE
) {
186 Status
= (*PeiServices
)->LocatePpi (
188 &gEfiPeiDeviceRecoveryModulePpiGuid
,
191 &DeviceRecoveryModule
194 if (!EFI_ERROR (Status
)) {
195 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Device Recovery PPI located\n"));
196 NumberOfImageProviders
++;
198 Status
= DeviceRecoveryModule
->GetNumberRecoveryCapsules (
199 (EFI_PEI_SERVICES
**)PeiServices
,
200 DeviceRecoveryModule
,
201 &NumberRecoveryCapsules
204 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Number Of Recovery Capsules: %d\n", NumberRecoveryCapsules
));
206 if (NumberRecoveryCapsules
== 0) {
212 ProviderAvailable
= FALSE
;
217 // If there is an image provider, get the capsule ID
219 if (ProviderAvailable
) {
220 RecoveryCapsuleSize
= 0;
222 Status
= DeviceRecoveryModule
->GetRecoveryCapsuleInfo (
223 (EFI_PEI_SERVICES
**)PeiServices
,
224 DeviceRecoveryModule
,
226 &RecoveryCapsuleSize
,
230 if (EFI_ERROR (Status
)) {
234 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Recovery Capsule Size: %d\n", RecoveryCapsuleSize
));
237 // Only support the 2 capsule types known
238 // Future enhancement is to rank-order the selection
240 if ((!CompareGuid (&DeviceId
, &gRecoveryOnFatIdeDiskGuid
)) &&
241 (!CompareGuid (&DeviceId
, &gRecoveryOnFatFloppyDiskGuid
)) &&
242 (!CompareGuid (&DeviceId
, &gRecoveryOnDataCdGuid
)) &&
243 (!CompareGuid (&DeviceId
, &gRecoveryOnFatUsbDiskGuid
))
245 return EFI_UNSUPPORTED
;
249 Status
= (*PeiServices
)->AllocatePages (
252 (RecoveryCapsuleSize
- 1) / 0x1000 + 1,
256 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "AllocatePage Returns: %r\n", Status
));
258 if (EFI_ERROR(Status
)) {
262 Buffer
= (UINT8
*) (UINTN
) Address
;
264 (*PeiServices
)->ReportStatusCode (
267 EFI_SOFTWARE_PEI_MODULE
| EFI_SW_PEIM_PC_CAPSULE_LOAD
,
273 Status
= DeviceRecoveryModule
->LoadRecoveryCapsule (
274 (EFI_PEI_SERVICES
**)PeiServices
,
275 DeviceRecoveryModule
,
280 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "LoadRecoveryCapsule Returns: %r\n", Status
));
282 if (EFI_ERROR (Status
)) {
287 // Update FV Hob if found
289 Status
= (*PeiServices
)->GetHobList (PeiServices
, &Hob
.Raw
);
290 HobOld
.Raw
= Hob
.Raw
;
291 while (!END_OF_HOB_LIST (Hob
)) {
292 if (Hob
.Header
->HobType
== EFI_HOB_TYPE_FV
) {
293 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Hob FV Length: %x\n", Hob
.FirmwareVolume
->Length
));
295 // BUGBUG Why is it a FV hob if it is greater than 0x50000?
297 if (Hob
.FirmwareVolume
->Length
> 0x50000) {
300 // This looks like the Hob we are interested in
302 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Hob Updated\n"));
303 Hob
.FirmwareVolume
->BaseAddress
= (UINTN
) Buffer
;
304 Hob
.FirmwareVolume
->Length
= RecoveryCapsuleSize
;
307 Hob
.Raw
= GET_NEXT_HOB (Hob
);
310 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)Buffer
;
311 CapsuleHeader
= (OLD_EFI_CAPSULE_HEADER
*)Buffer
;
314 // Check if top of file is a capsule
316 if (CompareGuid ((EFI_GUID
*)CapsuleHeader
, &mEfiCapsuleHeaderGuid
)) {
318 } else if (FvHeader
->Signature
== EFI_FVH_SIGNATURE
) {
320 // Assume the Firmware volume is a "FVMAIN" image
327 // build FV Hob if it is not built before
330 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "FV Hob is not found, Build FV Hob then..\n"));
343 Status
= (*PeiServices
)->CreateHob (
346 sizeof (EFI_HOB_CAPSULE_VOLUME
),
349 if (EFI_ERROR (Status
)) {
352 CapsuleHob
->BaseAddress
= (UINT64
)((UINTN
)CapsuleHeader
+ (UINTN
)CapsuleHeader
->OffsetToCapsuleBody
);
353 CapsuleHob
->Length
= (UINT64
)((UINTN
)CapsuleHeader
->CapsuleImageSize
-(UINTN
)CapsuleHeader
->OffsetToCapsuleBody
);
354 (*PeiServices
)->ReportStatusCode (
357 EFI_SOFTWARE_PEI_MODULE
| EFI_SW_PEIM_PC_CAPSULE_START
,
364 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Recovery Module Returning: %r\n", Status
));