4 Caution: This module requires additional review when modified.
5 This module will have external input - capsule image.
6 This external input must be validated carefully to avoid security issue like
7 buffer overflow, integer overflow.
9 ProcessRecoveryCapsule(), ProcessFmpCapsuleImage(), ProcessRecoveryImage(),
10 ValidateFmpCapsule() will receive untrusted input and do basic validation.
12 Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
13 SPDX-License-Identifier: BSD-2-Clause-Patent
18 // The package level header files this module uses
23 // The protocols, PPI and GUID defintions for this module
25 #include <Ppi/MasterBootMode.h>
26 #include <Ppi/BootInRecoveryMode.h>
27 #include <Ppi/RecoveryModule.h>
28 #include <Ppi/DeviceRecoveryModule.h>
29 #include <Ppi/FirmwareVolumeInfo.h>
30 #include <Guid/FirmwareFileSystem2.h>
31 #include <Guid/FmpCapsule.h>
32 #include <Guid/EdkiiSystemFmpCapsule.h>
35 // The Library classes this module consumes
37 #include <Library/DebugLib.h>
38 #include <Library/PeimEntryPoint.h>
39 #include <Library/PeiServicesLib.h>
40 #include <Library/HobLib.h>
41 #include <Library/BaseMemoryLib.h>
42 #include <Library/MemoryAllocationLib.h>
43 #include <Library/PcdLib.h>
45 #include "RecoveryModuleLoadPei.h"
48 Loads a DXE capsule from some media into memory and updates the HOB table
49 with the DXE firmware volume information.
51 @param[in] PeiServices General-purpose services that are available to every PEIM.
52 @param[in] This Indicates the EFI_PEI_RECOVERY_MODULE_PPI instance.
54 @retval EFI_SUCCESS The capsule was loaded correctly.
55 @retval EFI_DEVICE_ERROR A device error occurred.
56 @retval EFI_NOT_FOUND A recovery DXE capsule cannot be found.
62 IN EFI_PEI_SERVICES
**PeiServices
,
63 IN EFI_PEI_RECOVERY_MODULE_PPI
*This
66 EFI_PEI_RECOVERY_MODULE_PPI mRecoveryPpi
= {
70 EFI_PEI_PPI_DESCRIPTOR mRecoveryPpiList
= {
71 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
72 &gEfiPeiRecoveryModulePpiGuid
,
77 Parse Config data file to get the updated data array.
79 @param[in] DataBuffer Config raw file buffer.
80 @param[in] BufferSize Size of raw buffer.
81 @param[in, out] ConfigHeader Pointer to the config header.
82 @param[in, out] RecoveryArray Pointer to the config of recovery data.
84 @retval EFI_NOT_FOUND No config data is found.
85 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
86 @retval EFI_SUCCESS Parse the config file successfully.
90 ParseRecoveryDataFile (
93 IN OUT CONFIG_HEADER
*ConfigHeader
,
94 IN OUT RECOVERY_CONFIG_DATA
**RecoveryArray
98 Return if this FMP is a system FMP or a device FMP, based upon FmpImageInfo.
100 @param[in] FmpImageHeader A pointer to EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
102 @return TRUE It is a system FMP.
103 @return FALSE It is a device FMP.
107 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*FmpImageHeader
114 Guid
= PcdGetPtr(PcdSystemFmpCapsuleImageTypeIdGuid
);
115 Count
= PcdGetSize(PcdSystemFmpCapsuleImageTypeIdGuid
) / sizeof(GUID
);
117 for (Index
= 0; Index
< Count
; Index
++, Guid
++) {
118 if (CompareGuid(&FmpImageHeader
->UpdateImageTypeId
, Guid
)) {
127 Return if this CapsuleGuid is a FMP capsule GUID or not.
129 @param[in] CapsuleGuid A pointer to EFI_GUID
131 @return TRUE It is a FMP capsule GUID.
132 @return FALSE It is not a FMP capsule GUID.
136 IN EFI_GUID
*CapsuleGuid
139 if (CompareGuid(&gEfiFmpCapsuleGuid
, CapsuleGuid
)) {
147 This function assumes the input Capusule image already passes basic check in
148 ValidateFmpCapsule().
150 Criteria of system FMP capsule is:
151 1) FmpCapsuleHeader->EmbeddedDriverCount is 0.
152 2) FmpCapsuleHeader->PayloadItemCount is not 0.
153 3) All ImageHeader->UpdateImageTypeId matches PcdSystemFmpCapsuleImageTypeIdGuid.
155 @param[in] CapsuleHeader Points to a capsule header.
157 @retval TRUE Input capsule is a correct system FMP capsule.
158 @retval FALSE Input capsule is not a correct system FMP capsule.
161 IsSystemFmpCapsuleImage (
162 IN EFI_CAPSULE_HEADER
*CapsuleHeader
165 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
166 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
167 UINT64
*ItemOffsetList
;
171 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
173 if (FmpCapsuleHeader
->EmbeddedDriverCount
!= 0) {
177 if (FmpCapsuleHeader
->PayloadItemCount
== 0) {
181 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
183 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
185 for (Index
= 0; Index
< ItemNum
; Index
++) {
186 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
187 if (!IsSystemFmpImage(ImageHeader
)) {
196 Validate if it is valid capsule header
198 This function assumes the caller provided correct CapsuleHeader pointer
201 This function validates the fields in EFI_CAPSULE_HEADER.
203 @param[in] CapsuleHeader Points to a capsule header.
204 @param[in] CapsuleSize Size of the whole capsule image.
208 IsValidCapsuleHeader (
209 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
210 IN UINT64 CapsuleSize
213 if (CapsuleHeader
->CapsuleImageSize
!= CapsuleSize
) {
216 if (CapsuleHeader
->HeaderSize
>= CapsuleHeader
->CapsuleImageSize
) {
223 Validate Fmp capsules layout.
225 Caution: This function may receive untrusted input.
227 This function assumes the caller validated the capsule by using
228 IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.
229 The capsule buffer size is CapsuleHeader->CapsuleImageSize.
231 This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
232 and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
234 @param[in] CapsuleHeader Points to a capsule header.
235 @param[out] IsSystemFmp If it is a system FMP.
236 @param[out] EmbeddedDriverCount The EmbeddedDriverCount in the FMP capsule.
238 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
239 @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.
243 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
244 OUT BOOLEAN
*IsSystemFmp
, OPTIONAL
245 OUT UINT16
*EmbeddedDriverCount OPTIONAL
248 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
250 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
252 UINT64
*ItemOffsetList
;
255 UINTN FmpCapsuleSize
;
256 UINTN FmpCapsuleHeaderSize
;
258 UINTN FmpImageHeaderSize
;
260 if (CapsuleHeader
->HeaderSize
>= CapsuleHeader
->CapsuleImageSize
) {
261 DEBUG((DEBUG_ERROR
, "HeaderSize(0x%x) >= CapsuleImageSize(0x%x)\n", CapsuleHeader
->HeaderSize
, CapsuleHeader
->CapsuleImageSize
));
262 return EFI_INVALID_PARAMETER
;
265 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
266 EndOfCapsule
= (UINT8
*) CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
;
267 FmpCapsuleSize
= (UINTN
)EndOfCapsule
- (UINTN
)FmpCapsuleHeader
;
269 if (FmpCapsuleSize
< sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
)) {
270 DEBUG((DEBUG_ERROR
, "FmpCapsuleSize(0x%x) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\n", FmpCapsuleSize
));
271 return EFI_INVALID_PARAMETER
;
274 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
275 if (FmpCapsuleHeader
->Version
!= EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
276 DEBUG((DEBUG_ERROR
, "FmpCapsuleHeader->Version(0x%x) != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION\n", FmpCapsuleHeader
->Version
));
277 return EFI_INVALID_PARAMETER
;
279 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
282 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
284 if ((FmpCapsuleSize
- sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
))/sizeof(UINT64
) < ItemNum
) {
285 DEBUG((DEBUG_ERROR
, "ItemNum(0x%x) too big\n", ItemNum
));
286 return EFI_INVALID_PARAMETER
;
288 FmpCapsuleHeaderSize
= sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
) + sizeof(UINT64
)*ItemNum
;
290 // Check ItemOffsetList
291 for (Index
= 0; Index
< ItemNum
; Index
++) {
292 if (ItemOffsetList
[Index
] >= FmpCapsuleSize
) {
293 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) >= FmpCapsuleSize(0x%x)\n", Index
, ItemOffsetList
[Index
], FmpCapsuleSize
));
294 return EFI_INVALID_PARAMETER
;
296 if (ItemOffsetList
[Index
] < FmpCapsuleHeaderSize
) {
297 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) < FmpCapsuleHeaderSize(0x%x)\n", Index
, ItemOffsetList
[Index
], FmpCapsuleHeaderSize
));
298 return EFI_INVALID_PARAMETER
;
301 // All the address in ItemOffsetList must be stored in ascending order
304 if (ItemOffsetList
[Index
] <= ItemOffsetList
[Index
- 1]) {
305 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) < ItemOffsetList[%d](0x%x)\n", Index
, ItemOffsetList
[Index
], Index
, ItemOffsetList
[Index
- 1]));
306 return EFI_INVALID_PARAMETER
;
311 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
312 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
313 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
314 if (Index
== ItemNum
- 1) {
315 EndOfPayload
= (UINT8
*)((UINTN
)EndOfCapsule
- (UINTN
)FmpCapsuleHeader
);
317 EndOfPayload
= (UINT8
*)(UINTN
)ItemOffsetList
[Index
+1];
319 FmpImageSize
= (UINTN
)EndOfPayload
- ItemOffsetList
[Index
];
321 if (FmpImageSize
< OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
)) {
322 DEBUG((DEBUG_ERROR
, "FmpImageSize(0x%lx) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER\n", FmpImageSize
));
323 return EFI_INVALID_PARAMETER
;
325 FmpImageHeaderSize
= sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
);
326 if ((ImageHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) ||
327 (ImageHeader
->Version
< 1)) {
328 DEBUG((DEBUG_ERROR
, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader
->Version
));
329 return EFI_INVALID_PARAMETER
;
331 if (ImageHeader
->Version
< EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
332 FmpImageHeaderSize
= OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
336 if (FmpImageSize
!= (UINT64
)FmpImageHeaderSize
+ (UINT64
)ImageHeader
->UpdateImageSize
+ (UINT64
)ImageHeader
->UpdateVendorCodeSize
) {
337 DEBUG((DEBUG_ERROR
, "FmpImageSize(0x%lx) mismatch, UpdateImageSize(0x%x) UpdateVendorCodeSize(0x%x)\n", FmpImageSize
, ImageHeader
->UpdateImageSize
, ImageHeader
->UpdateVendorCodeSize
));
338 return EFI_INVALID_PARAMETER
;
344 // No driver & payload element in FMP
346 EndOfPayload
= (UINT8
*)(FmpCapsuleHeader
+ 1);
347 if (EndOfPayload
!= EndOfCapsule
) {
348 DEBUG((DEBUG_ERROR
, "EndOfPayload(0x%x) mismatch, EndOfCapsule(0x%x)\n", EndOfPayload
, EndOfCapsule
));
349 return EFI_INVALID_PARAMETER
;
351 return EFI_UNSUPPORTED
;
355 // Check in system FMP capsule
357 if (IsSystemFmp
!= NULL
) {
358 *IsSystemFmp
= IsSystemFmpCapsuleImage(CapsuleHeader
);
361 if (EmbeddedDriverCount
!= NULL
) {
362 *EmbeddedDriverCount
= FmpCapsuleHeader
->EmbeddedDriverCount
;
369 Recovery module entrypoint
371 @param[in] FileHandle Handle of the file being invoked.
372 @param[in] PeiServices Describes the list of possible PEI Services.
374 @return EFI_SUCCESS Recovery module is initialized.
378 InitializeRecoveryModule (
379 IN EFI_PEI_FILE_HANDLE FileHandle
,
380 IN CONST EFI_PEI_SERVICES
**PeiServices
386 BootMode
= GetBootModeHob();
387 ASSERT(BootMode
== BOOT_IN_RECOVERY_MODE
);
389 Status
= (**PeiServices
).InstallPpi (PeiServices
, &mRecoveryPpiList
);
390 ASSERT_EFI_ERROR (Status
);
396 Create hob and install FvInfo PPI for recovery capsule.
398 @param[in] FvImage Points to the DXE FV image.
399 @param[in] FvImageSize The length of the DXE FV image in bytes.
401 @retval EFI_SUCESS Create hob and install FvInfo PPI successfully.
402 @retval EFI_VOLUME_CORRUPTED The input data is not an FV.
403 @retval EFI_OUT_OF_RESOURCES No enough resource to process the input data.
407 CreateHobForRecoveryCapsule (
412 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
418 // FvImage should be at its required alignment.
420 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) FvImage
;
422 // Validate FV Header, if not as expected, return
424 if (ReadUnaligned32 (&FvHeader
->Signature
) != EFI_FVH_SIGNATURE
) {
425 DEBUG((DEBUG_ERROR
, "CreateHobForRecoveryCapsule (Fv Signature Error)\n"));
426 return EFI_VOLUME_CORRUPTED
;
429 // If EFI_FVB2_WEAK_ALIGNMENT is set in the volume header then the first byte of the volume
430 // can be aligned on any power-of-two boundary. A weakly aligned volume can not be moved from
431 // its initial linked location and maintain its alignment.
433 if ((ReadUnaligned32 (&FvHeader
->Attributes
) & EFI_FVB2_WEAK_ALIGNMENT
) != EFI_FVB2_WEAK_ALIGNMENT
) {
435 // Get FvHeader alignment
437 FvAlignment
= 1 << ((ReadUnaligned32 (&FvHeader
->Attributes
) & EFI_FVB2_ALIGNMENT
) >> 16);
439 // FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value.
441 if (FvAlignment
< 8) {
445 // Allocate the aligned buffer for the FvImage.
447 if ((UINTN
) FvHeader
% FvAlignment
!= 0) {
448 DEBUG((DEBUG_INFO
, "CreateHobForRecoveryCapsule (FvHeader 0x%lx is not aligned)\n", (UINT64
)(UINTN
)FvHeader
));
449 FvLength
= ReadUnaligned64 (&FvHeader
->FvLength
);
450 NewFvBuffer
= AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN
) FvLength
), FvAlignment
);
451 if (NewFvBuffer
== NULL
) {
452 DEBUG((DEBUG_ERROR
, "CreateHobForRecoveryCapsule (Not enough resource to allocate 0x%lx bytes)\n", FvLength
));
453 return EFI_OUT_OF_RESOURCES
;
455 CopyMem (NewFvBuffer
, FvHeader
, (UINTN
) FvLength
);
456 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) NewFvBuffer
;
460 BuildFvHob((UINT64
)(UINTN
)FvHeader
, FvHeader
->FvLength
);
461 DEBUG((DEBUG_INFO
, "BuildFvHob (FV in recovery) - 0x%lx - 0x%lx\n", (UINT64
)(UINTN
)FvHeader
, FvHeader
->FvLength
));
463 PeiServicesInstallFvInfoPpi(
464 &FvHeader
->FileSystemGuid
,
466 (UINT32
)FvHeader
->FvLength
,
475 Create recovery context based upon System Firmware image and config file.
477 @param[in] SystemFirmwareImage Points to the System Firmware image.
478 @param[in] SystemFirmwareImageSize The length of the System Firmware image in bytes.
479 @param[in] ConfigImage Points to the config file image.
480 @param[in] ConfigImageSize The length of the config file image in bytes.
482 @retval EFI_SUCESS Process Recovery Image successfully.
486 IN VOID
*SystemFirmwareImage
,
487 IN UINTN SystemFirmwareImageSize
,
488 IN VOID
*ConfigImage
,
489 IN UINTN ConfigImageSize
493 RECOVERY_CONFIG_DATA
*ConfigData
;
494 RECOVERY_CONFIG_DATA
*RecoveryConfigData
;
495 CONFIG_HEADER ConfigHeader
;
498 if (ConfigImage
== NULL
) {
499 DEBUG((DEBUG_INFO
, "RecoverImage (NoConfig)\n"));
500 Status
= CreateHobForRecoveryCapsule(
502 SystemFirmwareImageSize
508 ZeroMem (&ConfigHeader
, sizeof(ConfigHeader
));
509 Status
= ParseRecoveryDataFile (
515 DEBUG((DEBUG_INFO
, "ParseRecoveryDataFile - %r\n", Status
));
516 if (EFI_ERROR(Status
)) {
519 DEBUG((DEBUG_INFO
, "ConfigHeader.NumOfRecovery - 0x%x\n", ConfigHeader
.NumOfRecovery
));
520 DEBUG((DEBUG_INFO
, "PcdEdkiiSystemFirmwareFileGuid - %g\n", PcdGetPtr(PcdEdkiiSystemFirmwareFileGuid
)));
523 RecoveryConfigData
= ConfigData
;
524 while (Index
< ConfigHeader
.NumOfRecovery
) {
525 if (CompareGuid(&RecoveryConfigData
->FileGuid
, PcdGetPtr(PcdEdkiiSystemFirmwareFileGuid
))) {
526 DEBUG((DEBUG_INFO
, "FileGuid - %g (processing)\n", &RecoveryConfigData
->FileGuid
));
527 Status
= CreateHobForRecoveryCapsule (
528 (UINT8
*)SystemFirmwareImage
+ RecoveryConfigData
->ImageOffset
,
529 RecoveryConfigData
->Length
532 // Shall updates be serialized so that if a recovery FV is not successfully completed,
533 // the remaining updates won't be performed.
535 if (EFI_ERROR (Status
)) {
539 DEBUG((DEBUG_INFO
, "FileGuid - %g (ignored)\n", &RecoveryConfigData
->FileGuid
));
543 RecoveryConfigData
++;
550 Process recovery image.
552 Caution: This function may receive untrusted input.
554 @param[in] Image Points to the recovery image.
555 @param[in] Length The length of the recovery image in bytes.
557 @retval EFI_SUCESS Process Recovery Image successfully.
558 @retval EFI_SECURITY_VIOLATION Recovery image is not processed due to security violation.
561 ProcessRecoveryImage (
566 UINT32 LastAttemptVersion
;
567 UINT32 LastAttemptStatus
;
569 VOID
*SystemFirmwareImage
;
570 UINTN SystemFirmwareImageSize
;
572 UINTN ConfigImageSize
;
573 VOID
*AuthenticatedImage
;
574 UINTN AuthenticatedImageSize
;
576 AuthenticatedImage
= NULL
;
577 AuthenticatedImageSize
= 0;
579 Status
= CapsuleAuthenticateSystemFirmware(Image
, Length
, TRUE
, &LastAttemptVersion
, &LastAttemptStatus
, &AuthenticatedImage
, &AuthenticatedImageSize
);
580 if (EFI_ERROR(Status
)) {
581 DEBUG((DEBUG_INFO
, "CapsuleAuthenticateSystemFirmware - %r\n", Status
));
585 ExtractSystemFirmwareImage(AuthenticatedImage
, AuthenticatedImageSize
, &SystemFirmwareImage
, &SystemFirmwareImageSize
);
586 ExtractConfigImage(AuthenticatedImage
, AuthenticatedImageSize
, &ConfigImage
, &ConfigImageSize
);
588 Status
= RecoverImage(SystemFirmwareImage
, SystemFirmwareImageSize
, ConfigImage
, ConfigImageSize
);
589 if (EFI_ERROR(Status
)) {
590 DEBUG((DEBUG_INFO
, "RecoverImage - %r\n", Status
));
598 Process Firmware management protocol data capsule.
600 Caution: This function may receive untrusted input.
602 This function assumes the caller validated the capsule by using
603 ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
604 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
605 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
607 @param[in] CapsuleHeader Points to a capsule header.
608 @param[in] IsSystemFmp If this capsule is a system FMP capsule.
610 @retval EFI_SUCESS Process Capsule Image successfully.
611 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
612 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
613 @retval EFI_OUT_OF_RESOURCES Not enough memory.
616 ProcessFmpCapsuleImage (
617 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
618 IN BOOLEAN IsSystemFmp
622 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
623 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
625 UINT64
*ItemOffsetList
;
629 return EFI_UNSUPPORTED
;
632 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
633 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
635 for (ItemIndex
= 0; ItemIndex
< FmpCapsuleHeader
->PayloadItemCount
; ItemIndex
++) {
636 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[ItemIndex
]);
637 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
638 Image
= (UINT8
*)(ImageHeader
+ 1);
641 // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1, only match ImageTypeId.
642 // Header should exclude UpdateHardwareInstance field
644 Image
= (UINT8
*)ImageHeader
+ OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
647 Status
= ProcessRecoveryImage (Image
, ImageHeader
->UpdateImageSize
);
648 if (EFI_ERROR(Status
)) {
657 Process recovery capsule image.
659 Caution: This function may receive untrusted input.
661 @param[in] CapsuleBuffer The capsule image buffer.
662 @param[in] CapsuleSize The size of the capsule image in bytes.
664 @retval EFI_SUCCESS The recovery capsule is processed.
665 @retval EFI_SECURITY_VIOLATION The recovery capsule is not process because of security violation.
666 @retval EFI_NOT_FOUND The recovery capsule is not process because of unrecognization.
670 ProcessRecoveryCapsule (
671 IN VOID
*CapsuleBuffer
,
677 EFI_CAPSULE_HEADER
*CapsuleHeader
;
679 CapsuleHeader
= CapsuleBuffer
;
680 if (!IsValidCapsuleHeader (CapsuleHeader
, CapsuleSize
)) {
681 DEBUG((DEBUG_ERROR
, "CapsuleImageSize incorrect\n"));
682 return EFI_SECURITY_VIOLATION
;
686 // Check FMP capsule layout
688 if (IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
689 DEBUG((DEBUG_INFO
, "CreateHobForRecoveryCapsule\n"));
691 DEBUG((DEBUG_INFO
, "ProcessCapsuleImage for FmpCapsule ...\n"));
692 DEBUG((DEBUG_INFO
, "ValidateFmpCapsule ...\n"));
693 Status
= ValidateFmpCapsule(CapsuleHeader
, &IsSystemFmp
, NULL
);
694 DEBUG((DEBUG_INFO
, "ValidateFmpCapsule - %r\n", Status
));
695 if (EFI_ERROR(Status
)) {
700 // Process EFI FMP Capsule
702 DEBUG((DEBUG_INFO
, "ProcessFmpCapsuleImage ...\n"));
703 Status
= ProcessFmpCapsuleImage(CapsuleHeader
, IsSystemFmp
);
704 DEBUG((DEBUG_INFO
, "ProcessFmpCapsuleImage - %r\n", Status
));
706 DEBUG((DEBUG_INFO
, "CreateHobForRecoveryCapsule Done\n"));
710 return EFI_UNSUPPORTED
;
714 Loads a DXE capsule from some media into memory and updates the HOB table
715 with the DXE firmware volume information.
717 @param[in] PeiServices General-purpose services that are available to every PEIM.
718 @param[in] This Indicates the EFI_PEI_RECOVERY_MODULE_PPI instance.
720 @retval EFI_SUCCESS The capsule was loaded correctly.
721 @retval EFI_DEVICE_ERROR A device error occurred.
722 @retval EFI_NOT_FOUND A recovery DXE capsule cannot be found.
727 LoadRecoveryCapsule (
728 IN EFI_PEI_SERVICES
**PeiServices
,
729 IN EFI_PEI_RECOVERY_MODULE_PPI
*This
733 EFI_PEI_DEVICE_RECOVERY_MODULE_PPI
*DeviceRecoveryPpi
;
734 UINTN NumberRecoveryCapsules
;
736 UINTN CapsuleInstance
;
738 EFI_GUID CapsuleType
;
741 DEBUG((DEBUG_INFO
| DEBUG_LOAD
, "Recovery Entry\n"));
743 for (Instance
= 0; ; Instance
++) {
744 Status
= PeiServicesLocatePpi (
745 &gEfiPeiDeviceRecoveryModulePpiGuid
,
748 (VOID
**)&DeviceRecoveryPpi
750 DEBUG ((DEBUG_ERROR
, "LoadRecoveryCapsule - LocateRecoveryPpi (%d) - %r\n", Instance
, Status
));
751 if (EFI_ERROR (Status
)) {
754 NumberRecoveryCapsules
= 0;
755 Status
= DeviceRecoveryPpi
->GetNumberRecoveryCapsules (
756 (EFI_PEI_SERVICES
**)PeiServices
,
758 &NumberRecoveryCapsules
760 DEBUG ((DEBUG_ERROR
, "LoadRecoveryCapsule - GetNumberRecoveryCapsules (%d) - %r\n", NumberRecoveryCapsules
, Status
));
761 if (EFI_ERROR (Status
)) {
764 for (CapsuleInstance
= 1; CapsuleInstance
<= NumberRecoveryCapsules
; CapsuleInstance
++) {
766 Status
= DeviceRecoveryPpi
->GetRecoveryCapsuleInfo (
767 (EFI_PEI_SERVICES
**)PeiServices
,
769 FeaturePcdGet(PcdFrameworkCompatibilitySupport
) ? CapsuleInstance
- 1 : CapsuleInstance
,
773 DEBUG ((DEBUG_ERROR
, "LoadRecoveryCapsule - GetRecoveryCapsuleInfo (%d - %x) - %r\n", CapsuleInstance
, CapsuleSize
, Status
));
774 if (EFI_ERROR (Status
)) {
778 CapsuleBuffer
= AllocatePages (EFI_SIZE_TO_PAGES(CapsuleSize
));
779 if (CapsuleBuffer
== NULL
) {
780 DEBUG ((DEBUG_ERROR
, "LoadRecoveryCapsule - AllocatePool fail\n"));
783 Status
= DeviceRecoveryPpi
->LoadRecoveryCapsule (
784 (EFI_PEI_SERVICES
**)PeiServices
,
786 FeaturePcdGet(PcdFrameworkCompatibilitySupport
) ? CapsuleInstance
- 1 : CapsuleInstance
,
789 DEBUG ((DEBUG_ERROR
, "LoadRecoveryCapsule - LoadRecoveryCapsule (%d) - %r\n", CapsuleInstance
, Status
));
790 if (EFI_ERROR (Status
)) {
791 FreePages (CapsuleBuffer
, EFI_SIZE_TO_PAGES(CapsuleSize
));
795 // good, load capsule buffer
797 Status
= ProcessRecoveryCapsule (CapsuleBuffer
, CapsuleSize
);
802 return EFI_NOT_FOUND
;