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 SupportCapsuleImage(), ProcessCapsuleImage(), IsValidCapsuleHeader(),
10 ValidateFmpCapsule(), and DisplayCapsuleImage() receives untrusted input and
11 performs basic validation.
13 Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
14 SPDX-License-Identifier: BSD-2-Clause-Patent
20 #include <IndustryStandard/WindowsUxCapsule.h>
22 #include <Guid/FmpCapsule.h>
23 #include <Guid/SystemResourceTable.h>
24 #include <Guid/EventGroup.h>
26 #include <Library/BaseLib.h>
27 #include <Library/DebugLib.h>
28 #include <Library/BaseMemoryLib.h>
29 #include <Library/DxeServicesTableLib.h>
30 #include <Library/UefiBootServicesTableLib.h>
31 #include <Library/UefiRuntimeServicesTableLib.h>
32 #include <Library/MemoryAllocationLib.h>
33 #include <Library/CapsuleLib.h>
34 #include <Library/DevicePathLib.h>
35 #include <Library/UefiLib.h>
36 #include <Library/BmpSupportLib.h>
38 #include <Protocol/GraphicsOutput.h>
39 #include <Protocol/EsrtManagement.h>
40 #include <Protocol/FirmwareManagement.h>
41 #include <Protocol/FirmwareManagementProgress.h>
42 #include <Protocol/DevicePath.h>
44 EFI_SYSTEM_RESOURCE_TABLE
*mEsrtTable
= NULL
;
45 BOOLEAN mIsVirtualAddrConverted
= FALSE
;
47 BOOLEAN mDxeCapsuleLibEndOfDxe
= FALSE
;
48 EFI_EVENT mDxeCapsuleLibEndOfDxeEvent
= NULL
;
50 EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL
*mFmpProgress
= NULL
;
53 Initialize capsule related variables.
61 Record capsule status variable.
63 @param[in] CapsuleHeader The capsule image header
64 @param[in] CapsuleStatus The capsule process stauts
66 @retval EFI_SUCCESS The capsule status variable is recorded.
67 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
70 RecordCapsuleStatusVariable (
71 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
72 IN EFI_STATUS CapsuleStatus
76 Record FMP capsule status variable.
78 @param[in] CapsuleHeader The capsule image header
79 @param[in] CapsuleStatus The capsule process stauts
80 @param[in] PayloadIndex FMP payload index
81 @param[in] ImageHeader FMP image header
82 @param[in] FmpDevicePath DevicePath associated with the FMP producer
83 @param[in] CapFileName Capsule file name
85 @retval EFI_SUCCESS The capsule status variable is recorded.
86 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
89 RecordFmpCapsuleStatusVariable (
90 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
91 IN EFI_STATUS CapsuleStatus
,
92 IN UINTN PayloadIndex
,
93 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
,
94 IN EFI_DEVICE_PATH_PROTOCOL
*FmpDevicePath OPTIONAL
,
95 IN CHAR16
*CapFileName OPTIONAL
99 Function indicate the current completion progress of the firmware
100 update. Platform may override with own specific progress function.
102 @param[in] Completion A value between 1 and 100 indicating the current
103 completion progress of the firmware update
105 @retval EFI_SUCESS The capsule update progress was updated.
106 @retval EFI_INVALID_PARAMETER Completion is greater than 100%.
110 UpdateImageProgress (
115 Return if this capsule is a capsule name capsule, based upon CapsuleHeader.
117 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
119 @retval TRUE It is a capsule name capsule.
120 @retval FALSE It is not a capsule name capsule.
123 IsCapsuleNameCapsule (
124 IN EFI_CAPSULE_HEADER
*CapsuleHeader
127 return CompareGuid (&CapsuleHeader
->CapsuleGuid
, &gEdkiiCapsuleOnDiskNameGuid
);
131 Return if this CapsuleGuid is a FMP capsule GUID or not.
133 @param[in] CapsuleGuid A pointer to EFI_GUID
135 @retval TRUE It is a FMP capsule GUID.
136 @retval FALSE It is not a FMP capsule GUID.
140 IN EFI_GUID
*CapsuleGuid
143 if (CompareGuid (&gEfiFmpCapsuleGuid
, CapsuleGuid
)) {
151 Validate if it is valid capsule header
153 Caution: This function may receive untrusted input.
155 This function assumes the caller provided correct CapsuleHeader pointer
158 This function validates the fields in EFI_CAPSULE_HEADER.
160 @param[in] CapsuleHeader Points to a capsule header.
161 @param[in] CapsuleSize Size of the whole capsule image.
165 IsValidCapsuleHeader (
166 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
167 IN UINT64 CapsuleSize
170 if (CapsuleHeader
->CapsuleImageSize
!= CapsuleSize
) {
174 if (CapsuleHeader
->HeaderSize
>= CapsuleHeader
->CapsuleImageSize
) {
182 Validate Fmp capsules layout.
184 Caution: This function may receive untrusted input.
186 This function assumes the caller validated the capsule by using
187 IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.
188 The capsule buffer size is CapsuleHeader->CapsuleImageSize.
190 This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
191 and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
193 This function need support nested FMP capsule.
195 @param[in] CapsuleHeader Points to a capsule header.
196 @param[out] EmbeddedDriverCount The EmbeddedDriverCount in the FMP capsule.
198 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
199 @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.
203 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
204 OUT UINT16
*EmbeddedDriverCount OPTIONAL
207 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
209 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
211 UINT64
*ItemOffsetList
;
214 UINTN FmpCapsuleSize
;
215 UINTN FmpCapsuleHeaderSize
;
217 UINTN FmpImageHeaderSize
;
219 if (!IsFmpCapsuleGuid (&CapsuleHeader
->CapsuleGuid
)) {
220 return ValidateFmpCapsule ((EFI_CAPSULE_HEADER
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
), EmbeddedDriverCount
);
223 if (CapsuleHeader
->HeaderSize
>= CapsuleHeader
->CapsuleImageSize
) {
224 DEBUG ((DEBUG_ERROR
, "HeaderSize(0x%x) >= CapsuleImageSize(0x%x)\n", CapsuleHeader
->HeaderSize
, CapsuleHeader
->CapsuleImageSize
));
225 return EFI_INVALID_PARAMETER
;
228 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
229 EndOfCapsule
= (UINT8
*)CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
;
230 FmpCapsuleSize
= (UINTN
)EndOfCapsule
- (UINTN
)FmpCapsuleHeader
;
232 if (FmpCapsuleSize
< sizeof (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
)) {
233 DEBUG ((DEBUG_ERROR
, "FmpCapsuleSize(0x%x) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\n", FmpCapsuleSize
));
234 return EFI_INVALID_PARAMETER
;
237 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
238 if (FmpCapsuleHeader
->Version
!= EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
239 DEBUG ((DEBUG_ERROR
, "FmpCapsuleHeader->Version(0x%x) != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION\n", FmpCapsuleHeader
->Version
));
240 return EFI_INVALID_PARAMETER
;
243 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
246 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
248 if ((FmpCapsuleSize
- sizeof (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
))/sizeof (UINT64
) < ItemNum
) {
249 DEBUG ((DEBUG_ERROR
, "ItemNum(0x%x) too big\n", ItemNum
));
250 return EFI_INVALID_PARAMETER
;
253 FmpCapsuleHeaderSize
= sizeof (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
) + sizeof (UINT64
)*ItemNum
;
255 // Check ItemOffsetList
256 for (Index
= 0; Index
< ItemNum
; Index
++) {
257 if (ItemOffsetList
[Index
] >= FmpCapsuleSize
) {
258 DEBUG ((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) >= FmpCapsuleSize(0x%x)\n", Index
, ItemOffsetList
[Index
], FmpCapsuleSize
));
259 return EFI_INVALID_PARAMETER
;
262 if (ItemOffsetList
[Index
] < FmpCapsuleHeaderSize
) {
263 DEBUG ((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) < FmpCapsuleHeaderSize(0x%x)\n", Index
, ItemOffsetList
[Index
], FmpCapsuleHeaderSize
));
264 return EFI_INVALID_PARAMETER
;
268 // All the address in ItemOffsetList must be stored in ascending order
271 if (ItemOffsetList
[Index
] <= ItemOffsetList
[Index
- 1]) {
272 DEBUG ((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) < ItemOffsetList[%d](0x%x)\n", Index
, ItemOffsetList
[Index
], Index
- 1, ItemOffsetList
[Index
- 1]));
273 return EFI_INVALID_PARAMETER
;
278 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
279 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
280 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
281 if (Index
== ItemNum
- 1) {
282 EndOfPayload
= (UINT8
*)((UINTN
)EndOfCapsule
- (UINTN
)FmpCapsuleHeader
);
284 EndOfPayload
= (UINT8
*)(UINTN
)ItemOffsetList
[Index
+1];
287 FmpImageSize
= (UINTN
)EndOfPayload
- ItemOffsetList
[Index
];
289 FmpImageHeaderSize
= sizeof (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
);
290 if ((ImageHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) ||
291 (ImageHeader
->Version
< 1))
293 DEBUG ((DEBUG_ERROR
, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader
->Version
));
294 return EFI_INVALID_PARAMETER
;
297 if (ImageHeader
->Version
== 1) {
298 FmpImageHeaderSize
= OFFSET_OF (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
299 } else if (ImageHeader
->Version
== 2) {
300 FmpImageHeaderSize
= OFFSET_OF (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, ImageCapsuleSupport
);
303 if (FmpImageSize
< FmpImageHeaderSize
) {
304 DEBUG ((DEBUG_ERROR
, "FmpImageSize(0x%lx) < FmpImageHeaderSize(0x%x)\n", FmpImageSize
, FmpImageHeaderSize
));
305 return EFI_INVALID_PARAMETER
;
309 if (FmpImageSize
!= (UINT64
)FmpImageHeaderSize
+ (UINT64
)ImageHeader
->UpdateImageSize
+ (UINT64
)ImageHeader
->UpdateVendorCodeSize
) {
310 DEBUG ((DEBUG_ERROR
, "FmpImageSize(0x%lx) mismatch, UpdateImageSize(0x%x) UpdateVendorCodeSize(0x%x)\n", FmpImageSize
, ImageHeader
->UpdateImageSize
, ImageHeader
->UpdateVendorCodeSize
));
311 return EFI_INVALID_PARAMETER
;
317 // No driver & payload element in FMP
319 EndOfPayload
= (UINT8
*)(FmpCapsuleHeader
+ 1);
320 if (EndOfPayload
!= EndOfCapsule
) {
321 DEBUG ((DEBUG_ERROR
, "EndOfPayload(0x%x) mismatch, EndOfCapsule(0x%x)\n", EndOfPayload
, EndOfCapsule
));
322 return EFI_INVALID_PARAMETER
;
325 return EFI_UNSUPPORTED
;
328 if (EmbeddedDriverCount
!= NULL
) {
329 *EmbeddedDriverCount
= FmpCapsuleHeader
->EmbeddedDriverCount
;
336 Those capsules supported by the firmwares.
338 Caution: This function may receive untrusted input.
340 @param[in] CapsuleHeader Points to a capsule header.
342 @retval EFI_SUCESS Input capsule is supported by firmware.
343 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
346 DisplayCapsuleImage (
347 IN EFI_CAPSULE_HEADER
*CapsuleHeader
350 DISPLAY_DISPLAY_PAYLOAD
*ImagePayload
;
353 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
357 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
360 // UX capsule doesn't have extended header entries.
362 if (CapsuleHeader
->HeaderSize
!= sizeof (EFI_CAPSULE_HEADER
)) {
363 return EFI_UNSUPPORTED
;
366 ImagePayload
= (DISPLAY_DISPLAY_PAYLOAD
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
368 // (CapsuleImageSize > HeaderSize) is guaranteed by IsValidCapsuleHeader().
370 PayloadSize
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
;
373 // Make sure the image payload at least contain the DISPLAY_DISPLAY_PAYLOAD header.
374 // Further size check is performed by the logic translating BMP to GOP BLT.
376 if (PayloadSize
<= sizeof (DISPLAY_DISPLAY_PAYLOAD
)) {
377 return EFI_INVALID_PARAMETER
;
380 if (ImagePayload
->Version
!= 1) {
381 return EFI_UNSUPPORTED
;
384 if (CalculateCheckSum8 ((UINT8
*)CapsuleHeader
, CapsuleHeader
->CapsuleImageSize
) != 0) {
385 return EFI_UNSUPPORTED
;
389 // Only Support Bitmap by now
391 if (ImagePayload
->ImageType
!= 0) {
392 return EFI_UNSUPPORTED
;
398 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**)&GraphicsOutput
);
399 if (EFI_ERROR (Status
)) {
400 Status
= gBS
->LocateProtocol (&gEfiGraphicsOutputProtocolGuid
, NULL
, (VOID
**)&GraphicsOutput
);
401 if (EFI_ERROR (Status
)) {
402 return EFI_UNSUPPORTED
;
406 if (GraphicsOutput
->Mode
->Mode
!= ImagePayload
->Mode
) {
407 return EFI_UNSUPPORTED
;
413 Status
= TranslateBmpToGopBlt (
415 PayloadSize
- sizeof (DISPLAY_DISPLAY_PAYLOAD
),
422 if (EFI_ERROR (Status
)) {
426 Status
= GraphicsOutput
->Blt (
432 (UINTN
)ImagePayload
->OffsetX
,
433 (UINTN
)ImagePayload
->OffsetY
,
436 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
445 Dump FMP information.
447 @param[in] ImageInfoSize The size of ImageInfo, in bytes.
448 @param[in] ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
449 @param[in] DescriptorVersion The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
450 @param[in] DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
451 @param[in] DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
452 @param[in] PackageVersion The version of package.
453 @param[in] PackageVersionName The version name of package.
457 IN UINTN ImageInfoSize
,
458 IN EFI_FIRMWARE_IMAGE_DESCRIPTOR
*ImageInfo
,
459 IN UINT32 DescriptorVersion
,
460 IN UINT8 DescriptorCount
,
461 IN UINTN DescriptorSize
,
462 IN UINT32 PackageVersion
,
463 IN CHAR16
*PackageVersionName
466 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*CurrentImageInfo
;
469 DEBUG ((DEBUG_VERBOSE
, " DescriptorVersion - 0x%x\n", DescriptorVersion
));
470 DEBUG ((DEBUG_VERBOSE
, " DescriptorCount - 0x%x\n", DescriptorCount
));
471 DEBUG ((DEBUG_VERBOSE
, " DescriptorSize - 0x%x\n", DescriptorSize
));
472 DEBUG ((DEBUG_VERBOSE
, " PackageVersion - 0x%x\n", PackageVersion
));
473 DEBUG ((DEBUG_VERBOSE
, " PackageVersionName - %s\n\n", PackageVersionName
));
474 CurrentImageInfo
= ImageInfo
;
475 for (Index
= 0; Index
< DescriptorCount
; Index
++) {
476 DEBUG ((DEBUG_VERBOSE
, " ImageDescriptor (%d)\n", Index
));
477 DEBUG ((DEBUG_VERBOSE
, " ImageIndex - 0x%x\n", CurrentImageInfo
->ImageIndex
));
478 DEBUG ((DEBUG_VERBOSE
, " ImageTypeId - %g\n", &CurrentImageInfo
->ImageTypeId
));
479 DEBUG ((DEBUG_VERBOSE
, " ImageId - 0x%lx\n", CurrentImageInfo
->ImageId
));
480 DEBUG ((DEBUG_VERBOSE
, " ImageIdName - %s\n", CurrentImageInfo
->ImageIdName
));
481 DEBUG ((DEBUG_VERBOSE
, " Version - 0x%x\n", CurrentImageInfo
->Version
));
482 DEBUG ((DEBUG_VERBOSE
, " VersionName - %s\n", CurrentImageInfo
->VersionName
));
483 DEBUG ((DEBUG_VERBOSE
, " Size - 0x%x\n", CurrentImageInfo
->Size
));
484 DEBUG ((DEBUG_VERBOSE
, " AttributesSupported - 0x%lx\n", CurrentImageInfo
->AttributesSupported
));
485 DEBUG ((DEBUG_VERBOSE
, " AttributesSetting - 0x%lx\n", CurrentImageInfo
->AttributesSetting
));
486 DEBUG ((DEBUG_VERBOSE
, " Compatibilities - 0x%lx\n", CurrentImageInfo
->Compatibilities
));
487 if (DescriptorVersion
> 1) {
488 DEBUG ((DEBUG_VERBOSE
, " LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo
->LowestSupportedImageVersion
));
489 if (DescriptorVersion
> 2) {
490 DEBUG ((DEBUG_VERBOSE
, " LastAttemptVersion - 0x%x\n", CurrentImageInfo
->LastAttemptVersion
));
491 DEBUG ((DEBUG_VERBOSE
, " LastAttemptStatus - 0x%x\n", CurrentImageInfo
->LastAttemptStatus
));
492 DEBUG ((DEBUG_VERBOSE
, " HardwareInstance - 0x%lx\n", CurrentImageInfo
->HardwareInstance
));
497 // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
499 CurrentImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)CurrentImageInfo
+ DescriptorSize
);
504 Dump a non-nested FMP capsule.
506 @param[in] CapsuleHeader A pointer to CapsuleHeader
510 IN EFI_CAPSULE_HEADER
*CapsuleHeader
513 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
514 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
516 UINT64
*ItemOffsetList
;
518 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
520 DEBUG ((DEBUG_VERBOSE
, "FmpCapsule:\n"));
521 DEBUG ((DEBUG_VERBOSE
, " Version - 0x%x\n", FmpCapsuleHeader
->Version
));
522 DEBUG ((DEBUG_VERBOSE
, " EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader
->EmbeddedDriverCount
));
523 DEBUG ((DEBUG_VERBOSE
, " PayloadItemCount - 0x%x\n", FmpCapsuleHeader
->PayloadItemCount
));
525 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
526 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
527 DEBUG ((DEBUG_VERBOSE
, " ItemOffsetList[%d] - 0x%lx\n", Index
, ItemOffsetList
[Index
]));
530 for ( ; Index
< (UINT32
)FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
; Index
++) {
531 DEBUG ((DEBUG_VERBOSE
, " ItemOffsetList[%d] - 0x%lx\n", Index
, ItemOffsetList
[Index
]));
532 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
534 DEBUG ((DEBUG_VERBOSE
, " ImageHeader:\n"));
535 DEBUG ((DEBUG_VERBOSE
, " Version - 0x%x\n", ImageHeader
->Version
));
536 DEBUG ((DEBUG_VERBOSE
, " UpdateImageTypeId - %g\n", &ImageHeader
->UpdateImageTypeId
));
537 DEBUG ((DEBUG_VERBOSE
, " UpdateImageIndex - 0x%x\n", ImageHeader
->UpdateImageIndex
));
538 DEBUG ((DEBUG_VERBOSE
, " UpdateImageSize - 0x%x\n", ImageHeader
->UpdateImageSize
));
539 DEBUG ((DEBUG_VERBOSE
, " UpdateVendorCodeSize - 0x%x\n", ImageHeader
->UpdateVendorCodeSize
));
540 if (ImageHeader
->Version
>= 2) {
541 DEBUG ((DEBUG_VERBOSE
, " UpdateHardwareInstance - 0x%lx\n", ImageHeader
->UpdateHardwareInstance
));
542 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
543 DEBUG ((DEBUG_VERBOSE
, " ImageCapsuleSupport - 0x%lx\n", ImageHeader
->ImageCapsuleSupport
));
550 Dump all FMP information.
558 EFI_HANDLE
*HandleBuffer
;
559 UINTN NumberOfHandles
;
560 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
563 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
564 UINT32 FmpImageInfoDescriptorVer
;
565 UINT8 FmpImageInfoCount
;
566 UINTN DescriptorSize
;
567 UINT32 PackageVersion
;
568 CHAR16
*PackageVersionName
;
570 Status
= gBS
->LocateHandleBuffer (
572 &gEfiFirmwareManagementProtocolGuid
,
577 if (EFI_ERROR (Status
)) {
581 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
582 Status
= gBS
->HandleProtocol (
584 &gEfiFirmwareManagementProtocolGuid
,
587 if (EFI_ERROR (Status
)) {
592 Status
= Fmp
->GetImageInfo (
602 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
606 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
607 if (FmpImageInfoBuf
== NULL
) {
611 PackageVersionName
= NULL
;
612 Status
= Fmp
->GetImageInfo (
614 &ImageInfoSize
, // ImageInfoSize
615 FmpImageInfoBuf
, // ImageInfo
616 &FmpImageInfoDescriptorVer
, // DescriptorVersion
617 &FmpImageInfoCount
, // DescriptorCount
618 &DescriptorSize
, // DescriptorSize
619 &PackageVersion
, // PackageVersion
620 &PackageVersionName
// PackageVersionName
622 if (EFI_ERROR (Status
)) {
623 FreePool (FmpImageInfoBuf
);
627 DEBUG ((DEBUG_INFO
, "FMP (%d) ImageInfo:\n", Index
));
629 ImageInfoSize
, // ImageInfoSize
630 FmpImageInfoBuf
, // ImageInfo
631 FmpImageInfoDescriptorVer
, // DescriptorVersion
632 FmpImageInfoCount
, // DescriptorCount
633 DescriptorSize
, // DescriptorSize
634 PackageVersion
, // PackageVersion
635 PackageVersionName
// PackageVersionName
638 if (PackageVersionName
!= NULL
) {
639 FreePool (PackageVersionName
);
642 FreePool (FmpImageInfoBuf
);
645 FreePool (HandleBuffer
);
651 Get FMP handle by ImageTypeId and HardwareInstance.
653 @param[in] UpdateImageTypeId Used to identify device firmware targeted by this update.
654 @param[in] UpdateHardwareInstance The HardwareInstance to target with this update.
655 @param[out] NoHandles The number of handles returned in HandleBuf.
656 @param[out] HandleBuf A pointer to the buffer to return the requested array of handles.
657 @param[out] ResetRequiredBuf A pointer to the buffer to return reset required flag for
658 the requested array of handles.
660 @retval EFI_SUCCESS The array of handles and their reset required flag were returned in
661 HandleBuf and ResetRequiredBuf, and the number of handles in HandleBuf
662 was returned in NoHandles.
663 @retval EFI_NOT_FOUND No handles match the search.
664 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
667 GetFmpHandleBufferByType (
668 IN EFI_GUID
*UpdateImageTypeId
,
669 IN UINT64 UpdateHardwareInstance
,
670 OUT UINTN
*NoHandles OPTIONAL
,
671 OUT EFI_HANDLE
**HandleBuf OPTIONAL
,
672 OUT BOOLEAN
**ResetRequiredBuf OPTIONAL
676 EFI_HANDLE
*HandleBuffer
;
677 UINTN NumberOfHandles
;
678 EFI_HANDLE
*MatchedHandleBuffer
;
679 BOOLEAN
*MatchedResetRequiredBuffer
;
680 UINTN MatchedNumberOfHandles
;
681 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
684 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
685 UINT32 FmpImageInfoDescriptorVer
;
686 UINT8 FmpImageInfoCount
;
687 UINTN DescriptorSize
;
688 UINT32 PackageVersion
;
689 CHAR16
*PackageVersionName
;
691 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*TempFmpImageInfo
;
693 if (NoHandles
!= NULL
) {
697 if (HandleBuf
!= NULL
) {
701 if (ResetRequiredBuf
!= NULL
) {
702 *ResetRequiredBuf
= NULL
;
705 Status
= gBS
->LocateHandleBuffer (
707 &gEfiFirmwareManagementProtocolGuid
,
712 if (EFI_ERROR (Status
)) {
716 MatchedNumberOfHandles
= 0;
718 MatchedHandleBuffer
= NULL
;
719 if (HandleBuf
!= NULL
) {
720 MatchedHandleBuffer
= AllocateZeroPool (sizeof (EFI_HANDLE
) * NumberOfHandles
);
721 if (MatchedHandleBuffer
== NULL
) {
722 FreePool (HandleBuffer
);
723 return EFI_OUT_OF_RESOURCES
;
727 MatchedResetRequiredBuffer
= NULL
;
728 if (ResetRequiredBuf
!= NULL
) {
729 MatchedResetRequiredBuffer
= AllocateZeroPool (sizeof (BOOLEAN
) * NumberOfHandles
);
730 if (MatchedResetRequiredBuffer
== NULL
) {
731 if (MatchedHandleBuffer
!= NULL
) {
732 FreePool (MatchedHandleBuffer
);
735 FreePool (HandleBuffer
);
736 return EFI_OUT_OF_RESOURCES
;
740 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
741 Status
= gBS
->HandleProtocol (
743 &gEfiFirmwareManagementProtocolGuid
,
746 if (EFI_ERROR (Status
)) {
751 Status
= Fmp
->GetImageInfo (
761 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
765 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
766 if (FmpImageInfoBuf
== NULL
) {
770 PackageVersionName
= NULL
;
771 Status
= Fmp
->GetImageInfo (
773 &ImageInfoSize
, // ImageInfoSize
774 FmpImageInfoBuf
, // ImageInfo
775 &FmpImageInfoDescriptorVer
, // DescriptorVersion
776 &FmpImageInfoCount
, // DescriptorCount
777 &DescriptorSize
, // DescriptorSize
778 &PackageVersion
, // PackageVersion
779 &PackageVersionName
// PackageVersionName
781 if (EFI_ERROR (Status
)) {
782 FreePool (FmpImageInfoBuf
);
786 if (PackageVersionName
!= NULL
) {
787 FreePool (PackageVersionName
);
790 TempFmpImageInfo
= FmpImageInfoBuf
;
791 for (Index2
= 0; Index2
< FmpImageInfoCount
; Index2
++) {
793 // Check if this FMP instance matches
795 if (CompareGuid (UpdateImageTypeId
, &TempFmpImageInfo
->ImageTypeId
)) {
796 if ((UpdateHardwareInstance
== 0) ||
797 ((FmpImageInfoDescriptorVer
>= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
) &&
798 (UpdateHardwareInstance
== TempFmpImageInfo
->HardwareInstance
)))
800 if (MatchedHandleBuffer
!= NULL
) {
801 MatchedHandleBuffer
[MatchedNumberOfHandles
] = HandleBuffer
[Index
];
804 if (MatchedResetRequiredBuffer
!= NULL
) {
805 MatchedResetRequiredBuffer
[MatchedNumberOfHandles
] = (((TempFmpImageInfo
->AttributesSupported
&
806 IMAGE_ATTRIBUTE_RESET_REQUIRED
) != 0) &&
807 ((TempFmpImageInfo
->AttributesSetting
&
808 IMAGE_ATTRIBUTE_RESET_REQUIRED
) != 0));
811 MatchedNumberOfHandles
++;
816 TempFmpImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)TempFmpImageInfo
+ DescriptorSize
);
819 FreePool (FmpImageInfoBuf
);
822 FreePool (HandleBuffer
);
824 if (MatchedNumberOfHandles
== 0) {
825 return EFI_NOT_FOUND
;
828 if (NoHandles
!= NULL
) {
829 *NoHandles
= MatchedNumberOfHandles
;
832 if (HandleBuf
!= NULL
) {
833 *HandleBuf
= MatchedHandleBuffer
;
836 if (ResetRequiredBuf
!= NULL
) {
837 *ResetRequiredBuf
= MatchedResetRequiredBuffer
;
844 Return FmpImageInfoDescriptorVer by an FMP handle.
846 @param[in] Handle A FMP handle.
848 @return FmpImageInfoDescriptorVer associated with the FMP.
851 GetFmpImageInfoDescriptorVer (
856 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
858 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
859 UINT32 FmpImageInfoDescriptorVer
;
860 UINT8 FmpImageInfoCount
;
861 UINTN DescriptorSize
;
862 UINT32 PackageVersion
;
863 CHAR16
*PackageVersionName
;
865 Status
= gBS
->HandleProtocol (
867 &gEfiFirmwareManagementProtocolGuid
,
870 if (EFI_ERROR (Status
)) {
875 Status
= Fmp
->GetImageInfo (
885 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
889 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
890 if (FmpImageInfoBuf
== NULL
) {
894 PackageVersionName
= NULL
;
895 Status
= Fmp
->GetImageInfo (
897 &ImageInfoSize
, // ImageInfoSize
898 FmpImageInfoBuf
, // ImageInfo
899 &FmpImageInfoDescriptorVer
, // DescriptorVersion
900 &FmpImageInfoCount
, // DescriptorCount
901 &DescriptorSize
, // DescriptorSize
902 &PackageVersion
, // PackageVersion
903 &PackageVersionName
// PackageVersionName
905 if (EFI_ERROR (Status
)) {
906 FreePool (FmpImageInfoBuf
);
910 return FmpImageInfoDescriptorVer
;
916 @param[in] Handle A FMP handle.
917 @param[in] ImageHeader The payload image header.
918 @param[in] PayloadIndex The index of the payload.
920 @return The status of FMP->SetImage.
924 IN EFI_HANDLE Handle
,
925 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
,
926 IN UINTN PayloadIndex
930 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
934 EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS ProgressCallback
;
936 Status
= gBS
->HandleProtocol (
938 &gEfiFirmwareManagementProtocolGuid
,
941 if (EFI_ERROR (Status
)) {
946 // Lookup Firmware Management Progress Protocol before SetImage() is called
947 // This is an optional protocol that may not be present on Handle.
949 Status
= gBS
->HandleProtocol (
951 &gEdkiiFirmwareManagementProgressProtocolGuid
,
952 (VOID
**)&mFmpProgress
954 if (EFI_ERROR (Status
)) {
958 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
959 Image
= (UINT8
*)(ImageHeader
+ 1);
962 // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1,
963 // Header should exclude UpdateHardwareInstance field, and
964 // ImageCapsuleSupport field if version is 2.
966 if (ImageHeader
->Version
== 1) {
967 Image
= (UINT8
*)ImageHeader
+ OFFSET_OF (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
969 Image
= (UINT8
*)ImageHeader
+ OFFSET_OF (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, ImageCapsuleSupport
);
973 if (ImageHeader
->UpdateVendorCodeSize
== 0) {
976 VendorCode
= Image
+ ImageHeader
->UpdateImageSize
;
980 DEBUG ((DEBUG_INFO
, "Fmp->SetImage ...\n"));
981 DEBUG ((DEBUG_INFO
, "ImageTypeId - %g, ", &ImageHeader
->UpdateImageTypeId
));
982 DEBUG ((DEBUG_INFO
, "PayloadIndex - 0x%x, ", PayloadIndex
));
983 DEBUG ((DEBUG_INFO
, "ImageIndex - 0x%x ", ImageHeader
->UpdateImageIndex
));
984 if (ImageHeader
->Version
>= 2) {
985 DEBUG ((DEBUG_INFO
, "(UpdateHardwareInstance - 0x%x)", ImageHeader
->UpdateHardwareInstance
));
986 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
987 DEBUG ((DEBUG_INFO
, "(ImageCapsuleSupport - 0x%x)", ImageHeader
->ImageCapsuleSupport
));
991 DEBUG ((DEBUG_INFO
, "\n"));
994 // Before calling SetImage(), reset the progress bar to 0%
996 ProgressCallback
= UpdateImageProgress
;
997 Status
= UpdateImageProgress (0);
998 if (EFI_ERROR (Status
)) {
999 ProgressCallback
= NULL
;
1002 Status
= Fmp
->SetImage (
1004 ImageHeader
->UpdateImageIndex
, // ImageIndex
1006 ImageHeader
->UpdateImageSize
, // ImageSize
1007 VendorCode
, // VendorCode
1008 ProgressCallback
, // Progress
1009 &AbortReason
// AbortReason
1012 // Set the progress bar to 100% after returning from SetImage()
1014 if (ProgressCallback
!= NULL
) {
1015 UpdateImageProgress (100);
1018 DEBUG ((DEBUG_INFO
, "Fmp->SetImage - %r\n", Status
));
1019 if (AbortReason
!= NULL
) {
1020 DEBUG ((DEBUG_ERROR
, "%s\n", AbortReason
));
1021 FreePool (AbortReason
);
1025 // Clear mFmpProgress after SetImage() returns
1027 mFmpProgress
= NULL
;
1033 Start a UEFI image in the FMP payload.
1035 @param[in] ImageBuffer A pointer to the memory location containing a copy of the image to be loaded..
1036 @param[in] ImageSize The size in bytes of ImageBuffer.
1038 @return The status of gBS->LoadImage and gBS->StartImage.
1042 IN VOID
*ImageBuffer
,
1046 MEMMAP_DEVICE_PATH MemMapNode
;
1048 EFI_HANDLE ImageHandle
;
1049 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
1052 SetDevicePathNodeLength (&MemMapNode
.Header
, sizeof (MemMapNode
));
1053 MemMapNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
1054 MemMapNode
.Header
.SubType
= HW_MEMMAP_DP
;
1055 MemMapNode
.MemoryType
= EfiBootServicesCode
;
1056 MemMapNode
.StartingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)ImageBuffer
;
1057 MemMapNode
.EndingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)((UINT8
*)ImageBuffer
+ ImageSize
- 1);
1059 DriverDevicePath
= AppendDevicePathNode (NULL
, &MemMapNode
.Header
);
1060 if (DriverDevicePath
== NULL
) {
1061 return EFI_OUT_OF_RESOURCES
;
1064 DEBUG ((DEBUG_INFO
, "FmpCapsule: LoadImage ...\n"));
1065 Status
= gBS
->LoadImage (
1073 DEBUG ((DEBUG_INFO
, "FmpCapsule: LoadImage - %r\n", Status
));
1074 if (EFI_ERROR (Status
)) {
1076 // With EFI_SECURITY_VIOLATION retval, the Image was loaded and an ImageHandle was created
1077 // with a valid EFI_LOADED_IMAGE_PROTOCOL, but the image can not be started right now.
1078 // If the caller doesn't have the option to defer the execution of an image, we should
1079 // unload image for the EFI_SECURITY_VIOLATION to avoid resource leak.
1081 if (Status
== EFI_SECURITY_VIOLATION
) {
1082 gBS
->UnloadImage (ImageHandle
);
1085 FreePool (DriverDevicePath
);
1089 DEBUG ((DEBUG_INFO
, "FmpCapsule: StartImage ...\n"));
1090 Status
= gBS
->StartImage (
1095 DEBUG ((DEBUG_INFO
, "FmpCapsule: StartImage - %r\n", Status
));
1096 if (EFI_ERROR (Status
)) {
1097 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
1100 FreePool (DriverDevicePath
);
1105 Record FMP capsule status.
1107 @param[in] Handle A FMP handle.
1108 @param[in] CapsuleHeader The capsule image header
1109 @param[in] CapsuleStatus The capsule process stauts
1110 @param[in] PayloadIndex FMP payload index
1111 @param[in] ImageHeader FMP image header
1112 @param[in] CapFileName Capsule file name
1115 RecordFmpCapsuleStatus (
1116 IN EFI_HANDLE Handle OPTIONAL
,
1117 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
1118 IN EFI_STATUS CapsuleStatus
,
1119 IN UINTN PayloadIndex
,
1120 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
,
1121 IN CHAR16
*CapFileName OPTIONAL
1125 EFI_DEVICE_PATH_PROTOCOL
*FmpDevicePath
;
1126 UINT32 FmpImageInfoDescriptorVer
;
1127 EFI_STATUS StatusEsrt
;
1128 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
1129 EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry
;
1131 FmpDevicePath
= NULL
;
1132 if (Handle
!= NULL
) {
1133 gBS
->HandleProtocol (
1135 &gEfiDevicePathProtocolGuid
,
1136 (VOID
**)&FmpDevicePath
1140 RecordFmpCapsuleStatusVariable (
1150 // Update corresponding ESRT entry LastAttemp Status
1152 Status
= gBS
->LocateProtocol (&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
1153 if (EFI_ERROR (Status
)) {
1157 if (Handle
== NULL
) {
1162 // Update EsrtEntry For V1, V2 FMP instance.
1163 // V3 FMP ESRT cache will be synced up through SyncEsrtFmp interface
1165 FmpImageInfoDescriptorVer
= GetFmpImageInfoDescriptorVer (Handle
);
1166 if (FmpImageInfoDescriptorVer
< EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
) {
1167 StatusEsrt
= EsrtProtocol
->GetEsrtEntry (&ImageHeader
->UpdateImageTypeId
, &EsrtEntry
);
1168 if (!EFI_ERROR (StatusEsrt
)) {
1169 if (!EFI_ERROR (CapsuleStatus
)) {
1170 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_SUCCESS
;
1172 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL
;
1175 EsrtEntry
.LastAttemptVersion
= 0;
1176 EsrtProtocol
->UpdateEsrtEntry (&EsrtEntry
);
1182 Process Firmware management protocol data capsule.
1184 This function assumes the caller validated the capsule by using
1185 ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
1186 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
1187 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
1189 This function need support nested FMP capsule.
1191 @param[in] CapsuleHeader Points to a capsule header.
1192 @param[in] CapFileName Capsule file name.
1193 @param[out] ResetRequired Indicates whether reset is required or not.
1195 @retval EFI_SUCESS Process Capsule Image successfully.
1196 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1197 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1198 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1199 @retval EFI_NOT_READY No FMP protocol to handle this FMP capsule.
1202 ProcessFmpCapsuleImage (
1203 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
1204 IN CHAR16
*CapFileName OPTIONAL
,
1205 OUT BOOLEAN
*ResetRequired OPTIONAL
1209 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
1210 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
1211 UINT64
*ItemOffsetList
;
1214 EFI_HANDLE
*HandleBuffer
;
1215 BOOLEAN
*ResetRequiredBuffer
;
1216 UINTN NumberOfHandles
;
1218 UINT64 UpdateHardwareInstance
;
1223 if (!IsFmpCapsuleGuid (&CapsuleHeader
->CapsuleGuid
)) {
1224 return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
), CapFileName
, ResetRequired
);
1230 DumpFmpCapsule (CapsuleHeader
);
1232 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
1234 if (FmpCapsuleHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
1235 return EFI_INVALID_PARAMETER
;
1238 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
1240 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
1243 // capsule in which driver count and payload count are both zero is not processed.
1250 // 1. Try to load & start all the drivers within capsule
1252 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
1253 if ((FmpCapsuleHeader
->PayloadItemCount
== 0) &&
1254 (Index
== (UINTN
)FmpCapsuleHeader
->EmbeddedDriverCount
- 1))
1257 // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
1259 DriverLen
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
- (UINTN
)ItemOffsetList
[Index
];
1261 DriverLen
= (UINTN
)ItemOffsetList
[Index
+ 1] - (UINTN
)ItemOffsetList
[Index
];
1264 Status
= StartFmpImage (
1265 (UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
],
1268 if (EFI_ERROR (Status
)) {
1269 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
1275 // 2. Route payload to right FMP instance
1277 DEBUG ((DEBUG_INFO
, "FmpCapsule: route payload to right FMP instance ...\n"));
1282 // Check all the payload entry in capsule payload list
1284 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
1285 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
1287 UpdateHardwareInstance
= 0;
1289 /// UpdateHardwareInstance field was added in Version 2
1291 if (ImageHeader
->Version
>= 2) {
1292 UpdateHardwareInstance
= ImageHeader
->UpdateHardwareInstance
;
1295 Status
= GetFmpHandleBufferByType (
1296 &ImageHeader
->UpdateImageTypeId
,
1297 UpdateHardwareInstance
,
1300 &ResetRequiredBuffer
1302 if (EFI_ERROR (Status
) ||
1303 (HandleBuffer
== NULL
) ||
1304 (ResetRequiredBuffer
== NULL
))
1307 RecordFmpCapsuleStatus (
1311 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1318 for (Index2
= 0; Index2
< NumberOfHandles
; Index2
++) {
1320 RecordFmpCapsuleStatus (
1321 HandleBuffer
[Index2
],
1324 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1331 Status
= SetFmpImageData (
1332 HandleBuffer
[Index2
],
1334 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
1336 if (Status
!= EFI_SUCCESS
) {
1339 if (ResetRequired
!= NULL
) {
1340 *ResetRequired
|= ResetRequiredBuffer
[Index2
];
1344 RecordFmpCapsuleStatus (
1345 HandleBuffer
[Index2
],
1348 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1354 if (HandleBuffer
!= NULL
) {
1355 FreePool (HandleBuffer
);
1358 if (ResetRequiredBuffer
!= NULL
) {
1359 FreePool (ResetRequiredBuffer
);
1364 return EFI_NOT_READY
;
1368 // always return SUCCESS to indicate this capsule is processed.
1369 // The status of SetImage is recorded in capsule result variable.
1375 Return if there is a FMP header below capsule header.
1377 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1379 @retval TRUE There is a FMP header below capsule header.
1380 @retval FALSE There is not a FMP header below capsule header
1383 IsNestedFmpCapsule (
1384 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1388 EFI_SYSTEM_RESOURCE_ENTRY
*EsrtEntry
;
1390 BOOLEAN EsrtGuidFound
;
1391 EFI_CAPSULE_HEADER
*NestedCapsuleHeader
;
1392 UINTN NestedCapsuleSize
;
1393 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
1394 EFI_SYSTEM_RESOURCE_ENTRY Entry
;
1396 EsrtGuidFound
= FALSE
;
1397 if (mIsVirtualAddrConverted
) {
1398 if (mEsrtTable
!= NULL
) {
1399 EsrtEntry
= (EFI_SYSTEM_RESOURCE_ENTRY
*)(mEsrtTable
+ 1);
1400 for (Index
= 0; Index
< mEsrtTable
->FwResourceCount
; Index
++, EsrtEntry
++) {
1401 if (CompareGuid (&EsrtEntry
->FwClass
, &CapsuleHeader
->CapsuleGuid
)) {
1402 EsrtGuidFound
= TRUE
;
1409 // Check ESRT protocol
1411 Status
= gBS
->LocateProtocol (&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
1412 if (!EFI_ERROR (Status
)) {
1413 Status
= EsrtProtocol
->GetEsrtEntry (&CapsuleHeader
->CapsuleGuid
, &Entry
);
1414 if (!EFI_ERROR (Status
)) {
1415 EsrtGuidFound
= TRUE
;
1420 // Check Firmware Management Protocols
1422 if (!EsrtGuidFound
) {
1423 Status
= GetFmpHandleBufferByType (
1424 &CapsuleHeader
->CapsuleGuid
,
1430 if (!EFI_ERROR (Status
)) {
1431 EsrtGuidFound
= TRUE
;
1436 if (!EsrtGuidFound
) {
1441 // Check nested capsule header
1442 // FMP GUID after ESRT one
1444 NestedCapsuleHeader
= (EFI_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
1445 NestedCapsuleSize
= (UINTN
)CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
- (UINTN
)NestedCapsuleHeader
;
1446 if (NestedCapsuleSize
< sizeof (EFI_CAPSULE_HEADER
)) {
1450 if (!IsValidCapsuleHeader (NestedCapsuleHeader
, NestedCapsuleSize
)) {
1454 if (!IsFmpCapsuleGuid (&NestedCapsuleHeader
->CapsuleGuid
)) {
1458 DEBUG ((DEBUG_INFO
, "IsNestedFmpCapsule\n"));
1463 Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
1465 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1467 @retval TRUE It is a system FMP.
1468 @retval FALSE It is a device FMP.
1472 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1475 if (IsFmpCapsuleGuid (&CapsuleHeader
->CapsuleGuid
)) {
1479 if (IsNestedFmpCapsule (CapsuleHeader
)) {
1487 Those capsules supported by the firmwares.
1489 Caution: This function may receive untrusted input.
1491 @param[in] CapsuleHeader Points to a capsule header.
1493 @retval EFI_SUCESS Input capsule is supported by firmware.
1494 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
1495 @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
1499 SupportCapsuleImage (
1500 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1504 // check Display Capsule Guid
1506 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1511 // Check capsule file name capsule
1513 if (IsCapsuleNameCapsule (CapsuleHeader
)) {
1517 if (IsFmpCapsule (CapsuleHeader
)) {
1519 // Fake capsule header is valid case in QueryCapsuleCpapbilities().
1521 if (CapsuleHeader
->HeaderSize
== CapsuleHeader
->CapsuleImageSize
) {
1526 // Check layout of FMP capsule
1528 return ValidateFmpCapsule (CapsuleHeader
, NULL
);
1531 DEBUG ((DEBUG_ERROR
, "Unknown Capsule Guid - %g\n", &CapsuleHeader
->CapsuleGuid
));
1532 return EFI_UNSUPPORTED
;
1536 The firmware implements to process the capsule image.
1538 Caution: This function may receive untrusted input.
1540 @param[in] CapsuleHeader Points to a capsule header.
1541 @param[in] CapFileName Capsule file name.
1542 @param[out] ResetRequired Indicates whether reset is required or not.
1544 @retval EFI_SUCESS Process Capsule Image successfully.
1545 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1546 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1547 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1551 ProcessThisCapsuleImage (
1552 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
1553 IN CHAR16
*CapFileName OPTIONAL
,
1554 OUT BOOLEAN
*ResetRequired OPTIONAL
1559 if (SupportCapsuleImage (CapsuleHeader
) != EFI_SUCCESS
) {
1560 RecordCapsuleStatusVariable (CapsuleHeader
, EFI_UNSUPPORTED
);
1561 return EFI_UNSUPPORTED
;
1565 // Display image in firmware update display capsule
1567 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1568 DEBUG ((DEBUG_INFO
, "ProcessCapsuleImage for WindowsUxCapsule ...\n"));
1569 Status
= DisplayCapsuleImage (CapsuleHeader
);
1570 RecordCapsuleStatusVariable (CapsuleHeader
, Status
);
1575 // Check FMP capsule layout
1577 if (IsFmpCapsule (CapsuleHeader
)) {
1578 DEBUG ((DEBUG_INFO
, "ProcessCapsuleImage for FmpCapsule ...\n"));
1579 DEBUG ((DEBUG_INFO
, "ValidateFmpCapsule ...\n"));
1580 Status
= ValidateFmpCapsule (CapsuleHeader
, NULL
);
1581 DEBUG ((DEBUG_INFO
, "ValidateFmpCapsule - %r\n", Status
));
1582 if (EFI_ERROR (Status
)) {
1583 RecordCapsuleStatusVariable (CapsuleHeader
, Status
);
1588 // Process EFI FMP Capsule
1590 DEBUG ((DEBUG_INFO
, "ProcessFmpCapsuleImage ...\n"));
1591 Status
= ProcessFmpCapsuleImage (CapsuleHeader
, CapFileName
, ResetRequired
);
1592 DEBUG ((DEBUG_INFO
, "ProcessFmpCapsuleImage - %r\n", Status
));
1597 return EFI_UNSUPPORTED
;
1601 The firmware implements to process the capsule image.
1603 Caution: This function may receive untrusted input.
1605 @param[in] CapsuleHeader Points to a capsule header.
1607 @retval EFI_SUCESS Process Capsule Image successfully.
1608 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1609 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1610 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1614 ProcessCapsuleImage (
1615 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1618 return ProcessThisCapsuleImage (CapsuleHeader
, NULL
, NULL
);
1622 Callback function executed when the EndOfDxe event group is signaled.
1624 @param[in] Event Event whose notification function is being invoked.
1625 @param[in] Context The pointer to the notification function's context, which
1626 is implementation-dependent.
1630 DxeCapsuleLibEndOfDxe (
1635 mDxeCapsuleLibEndOfDxe
= TRUE
;
1639 The constructor function.
1641 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1642 @param[in] SystemTable A pointer to the EFI System Table.
1644 @retval EFI_SUCCESS The constructor successfully .
1648 DxeCapsuleLibConstructor (
1649 IN EFI_HANDLE ImageHandle
,
1650 IN EFI_SYSTEM_TABLE
*SystemTable
1655 Status
= gBS
->CreateEventEx (
1658 DxeCapsuleLibEndOfDxe
,
1660 &gEfiEndOfDxeEventGroupGuid
,
1661 &mDxeCapsuleLibEndOfDxeEvent
1663 ASSERT_EFI_ERROR (Status
);
1665 InitCapsuleVariable ();
1671 The destructor function closes the End of DXE event.
1673 @param ImageHandle The firmware allocated handle for the EFI image.
1674 @param SystemTable A pointer to the EFI System Table.
1676 @retval EFI_SUCCESS The destructor completed successfully.
1680 DxeCapsuleLibDestructor (
1681 IN EFI_HANDLE ImageHandle
,
1682 IN EFI_SYSTEM_TABLE
*SystemTable
1688 // Close the End of DXE event.
1690 Status
= gBS
->CloseEvent (mDxeCapsuleLibEndOfDxeEvent
);
1691 ASSERT_EFI_ERROR (Status
);