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
) {
173 if (CapsuleHeader
->HeaderSize
>= CapsuleHeader
->CapsuleImageSize
) {
180 Validate Fmp capsules layout.
182 Caution: This function may receive untrusted input.
184 This function assumes the caller validated the capsule by using
185 IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.
186 The capsule buffer size is CapsuleHeader->CapsuleImageSize.
188 This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
189 and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
191 This function need support nested FMP capsule.
193 @param[in] CapsuleHeader Points to a capsule header.
194 @param[out] EmbeddedDriverCount The EmbeddedDriverCount in the FMP capsule.
196 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
197 @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.
201 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
202 OUT UINT16
*EmbeddedDriverCount OPTIONAL
205 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
207 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
209 UINT64
*ItemOffsetList
;
212 UINTN FmpCapsuleSize
;
213 UINTN FmpCapsuleHeaderSize
;
215 UINTN FmpImageHeaderSize
;
217 if (!IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
218 return ValidateFmpCapsule ((EFI_CAPSULE_HEADER
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
), EmbeddedDriverCount
);
221 if (CapsuleHeader
->HeaderSize
>= CapsuleHeader
->CapsuleImageSize
) {
222 DEBUG((DEBUG_ERROR
, "HeaderSize(0x%x) >= CapsuleImageSize(0x%x)\n", CapsuleHeader
->HeaderSize
, CapsuleHeader
->CapsuleImageSize
));
223 return EFI_INVALID_PARAMETER
;
226 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
227 EndOfCapsule
= (UINT8
*) CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
;
228 FmpCapsuleSize
= (UINTN
)EndOfCapsule
- (UINTN
)FmpCapsuleHeader
;
230 if (FmpCapsuleSize
< sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
)) {
231 DEBUG((DEBUG_ERROR
, "FmpCapsuleSize(0x%x) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\n", FmpCapsuleSize
));
232 return EFI_INVALID_PARAMETER
;
235 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
236 if (FmpCapsuleHeader
->Version
!= EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
237 DEBUG((DEBUG_ERROR
, "FmpCapsuleHeader->Version(0x%x) != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION\n", FmpCapsuleHeader
->Version
));
238 return EFI_INVALID_PARAMETER
;
240 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
243 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
245 if ((FmpCapsuleSize
- sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
))/sizeof(UINT64
) < ItemNum
) {
246 DEBUG((DEBUG_ERROR
, "ItemNum(0x%x) too big\n", ItemNum
));
247 return EFI_INVALID_PARAMETER
;
249 FmpCapsuleHeaderSize
= sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
) + sizeof(UINT64
)*ItemNum
;
251 // Check ItemOffsetList
252 for (Index
= 0; Index
< ItemNum
; Index
++) {
253 if (ItemOffsetList
[Index
] >= FmpCapsuleSize
) {
254 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) >= FmpCapsuleSize(0x%x)\n", Index
, ItemOffsetList
[Index
], FmpCapsuleSize
));
255 return EFI_INVALID_PARAMETER
;
257 if (ItemOffsetList
[Index
] < FmpCapsuleHeaderSize
) {
258 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) < FmpCapsuleHeaderSize(0x%x)\n", Index
, ItemOffsetList
[Index
], FmpCapsuleHeaderSize
));
259 return EFI_INVALID_PARAMETER
;
262 // All the address in ItemOffsetList must be stored in ascending order
265 if (ItemOffsetList
[Index
] <= ItemOffsetList
[Index
- 1]) {
266 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) < ItemOffsetList[%d](0x%x)\n", Index
, ItemOffsetList
[Index
], Index
- 1, ItemOffsetList
[Index
- 1]));
267 return EFI_INVALID_PARAMETER
;
272 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
273 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
274 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
275 if (Index
== ItemNum
- 1) {
276 EndOfPayload
= (UINT8
*)((UINTN
)EndOfCapsule
- (UINTN
)FmpCapsuleHeader
);
278 EndOfPayload
= (UINT8
*)(UINTN
)ItemOffsetList
[Index
+1];
280 FmpImageSize
= (UINTN
)EndOfPayload
- ItemOffsetList
[Index
];
282 FmpImageHeaderSize
= sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
);
283 if ((ImageHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) ||
284 (ImageHeader
->Version
< 1)) {
285 DEBUG((DEBUG_ERROR
, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader
->Version
));
286 return EFI_INVALID_PARAMETER
;
288 if (ImageHeader
->Version
== 1) {
289 FmpImageHeaderSize
= OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
290 } else if (ImageHeader
->Version
== 2) {
291 FmpImageHeaderSize
= OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, ImageCapsuleSupport
);
293 if (FmpImageSize
< FmpImageHeaderSize
) {
294 DEBUG((DEBUG_ERROR
, "FmpImageSize(0x%lx) < FmpImageHeaderSize(0x%x)\n", FmpImageSize
, FmpImageHeaderSize
));
295 return EFI_INVALID_PARAMETER
;
299 if (FmpImageSize
!= (UINT64
)FmpImageHeaderSize
+ (UINT64
)ImageHeader
->UpdateImageSize
+ (UINT64
)ImageHeader
->UpdateVendorCodeSize
) {
300 DEBUG((DEBUG_ERROR
, "FmpImageSize(0x%lx) mismatch, UpdateImageSize(0x%x) UpdateVendorCodeSize(0x%x)\n", FmpImageSize
, ImageHeader
->UpdateImageSize
, ImageHeader
->UpdateVendorCodeSize
));
301 return EFI_INVALID_PARAMETER
;
307 // No driver & payload element in FMP
309 EndOfPayload
= (UINT8
*)(FmpCapsuleHeader
+ 1);
310 if (EndOfPayload
!= EndOfCapsule
) {
311 DEBUG((DEBUG_ERROR
, "EndOfPayload(0x%x) mismatch, EndOfCapsule(0x%x)\n", EndOfPayload
, EndOfCapsule
));
312 return EFI_INVALID_PARAMETER
;
314 return EFI_UNSUPPORTED
;
317 if (EmbeddedDriverCount
!= NULL
) {
318 *EmbeddedDriverCount
= FmpCapsuleHeader
->EmbeddedDriverCount
;
325 Those capsules supported by the firmwares.
327 Caution: This function may receive untrusted input.
329 @param[in] CapsuleHeader Points to a capsule header.
331 @retval EFI_SUCESS Input capsule is supported by firmware.
332 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
335 DisplayCapsuleImage (
336 IN EFI_CAPSULE_HEADER
*CapsuleHeader
339 DISPLAY_DISPLAY_PAYLOAD
*ImagePayload
;
342 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
346 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
349 // UX capsule doesn't have extended header entries.
351 if (CapsuleHeader
->HeaderSize
!= sizeof (EFI_CAPSULE_HEADER
)) {
352 return EFI_UNSUPPORTED
;
354 ImagePayload
= (DISPLAY_DISPLAY_PAYLOAD
*)((UINTN
) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
356 // (CapsuleImageSize > HeaderSize) is guaranteed by IsValidCapsuleHeader().
358 PayloadSize
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
;
361 // Make sure the image payload at least contain the DISPLAY_DISPLAY_PAYLOAD header.
362 // Further size check is performed by the logic translating BMP to GOP BLT.
364 if (PayloadSize
<= sizeof (DISPLAY_DISPLAY_PAYLOAD
)) {
365 return EFI_INVALID_PARAMETER
;
368 if (ImagePayload
->Version
!= 1) {
369 return EFI_UNSUPPORTED
;
371 if (CalculateCheckSum8((UINT8
*)CapsuleHeader
, CapsuleHeader
->CapsuleImageSize
) != 0) {
372 return EFI_UNSUPPORTED
;
375 // Only Support Bitmap by now
377 if (ImagePayload
->ImageType
!= 0) {
378 return EFI_UNSUPPORTED
;
384 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**)&GraphicsOutput
);
385 if (EFI_ERROR (Status
)) {
386 Status
= gBS
->LocateProtocol(&gEfiGraphicsOutputProtocolGuid
, NULL
, (VOID
**)&GraphicsOutput
);
387 if (EFI_ERROR(Status
)) {
388 return EFI_UNSUPPORTED
;
392 if (GraphicsOutput
->Mode
->Mode
!= ImagePayload
->Mode
) {
393 return EFI_UNSUPPORTED
;
399 Status
= TranslateBmpToGopBlt (
401 PayloadSize
- sizeof(DISPLAY_DISPLAY_PAYLOAD
),
408 if (EFI_ERROR (Status
)) {
412 Status
= GraphicsOutput
->Blt (
418 (UINTN
) ImagePayload
->OffsetX
,
419 (UINTN
) ImagePayload
->OffsetY
,
422 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
431 Dump FMP information.
433 @param[in] ImageInfoSize The size of ImageInfo, in bytes.
434 @param[in] ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
435 @param[in] DescriptorVersion The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
436 @param[in] DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
437 @param[in] DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
438 @param[in] PackageVersion The version of package.
439 @param[in] PackageVersionName The version name of package.
443 IN UINTN ImageInfoSize
,
444 IN EFI_FIRMWARE_IMAGE_DESCRIPTOR
*ImageInfo
,
445 IN UINT32 DescriptorVersion
,
446 IN UINT8 DescriptorCount
,
447 IN UINTN DescriptorSize
,
448 IN UINT32 PackageVersion
,
449 IN CHAR16
*PackageVersionName
452 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*CurrentImageInfo
;
455 DEBUG((DEBUG_VERBOSE
, " DescriptorVersion - 0x%x\n", DescriptorVersion
));
456 DEBUG((DEBUG_VERBOSE
, " DescriptorCount - 0x%x\n", DescriptorCount
));
457 DEBUG((DEBUG_VERBOSE
, " DescriptorSize - 0x%x\n", DescriptorSize
));
458 DEBUG((DEBUG_VERBOSE
, " PackageVersion - 0x%x\n", PackageVersion
));
459 DEBUG((DEBUG_VERBOSE
, " PackageVersionName - %s\n\n", PackageVersionName
));
460 CurrentImageInfo
= ImageInfo
;
461 for (Index
= 0; Index
< DescriptorCount
; Index
++) {
462 DEBUG((DEBUG_VERBOSE
, " ImageDescriptor (%d)\n", Index
));
463 DEBUG((DEBUG_VERBOSE
, " ImageIndex - 0x%x\n", CurrentImageInfo
->ImageIndex
));
464 DEBUG((DEBUG_VERBOSE
, " ImageTypeId - %g\n", &CurrentImageInfo
->ImageTypeId
));
465 DEBUG((DEBUG_VERBOSE
, " ImageId - 0x%lx\n", CurrentImageInfo
->ImageId
));
466 DEBUG((DEBUG_VERBOSE
, " ImageIdName - %s\n", CurrentImageInfo
->ImageIdName
));
467 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", CurrentImageInfo
->Version
));
468 DEBUG((DEBUG_VERBOSE
, " VersionName - %s\n", CurrentImageInfo
->VersionName
));
469 DEBUG((DEBUG_VERBOSE
, " Size - 0x%x\n", CurrentImageInfo
->Size
));
470 DEBUG((DEBUG_VERBOSE
, " AttributesSupported - 0x%lx\n", CurrentImageInfo
->AttributesSupported
));
471 DEBUG((DEBUG_VERBOSE
, " AttributesSetting - 0x%lx\n", CurrentImageInfo
->AttributesSetting
));
472 DEBUG((DEBUG_VERBOSE
, " Compatibilities - 0x%lx\n", CurrentImageInfo
->Compatibilities
));
473 if (DescriptorVersion
> 1) {
474 DEBUG((DEBUG_VERBOSE
, " LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo
->LowestSupportedImageVersion
));
475 if (DescriptorVersion
> 2) {
476 DEBUG((DEBUG_VERBOSE
, " LastAttemptVersion - 0x%x\n", CurrentImageInfo
->LastAttemptVersion
));
477 DEBUG((DEBUG_VERBOSE
, " LastAttemptStatus - 0x%x\n", CurrentImageInfo
->LastAttemptStatus
));
478 DEBUG((DEBUG_VERBOSE
, " HardwareInstance - 0x%lx\n", CurrentImageInfo
->HardwareInstance
));
482 // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
484 CurrentImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)CurrentImageInfo
+ DescriptorSize
);
489 Dump a non-nested FMP capsule.
491 @param[in] CapsuleHeader A pointer to CapsuleHeader
495 IN EFI_CAPSULE_HEADER
*CapsuleHeader
498 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
499 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
501 UINT64
*ItemOffsetList
;
503 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
505 DEBUG((DEBUG_VERBOSE
, "FmpCapsule:\n"));
506 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", FmpCapsuleHeader
->Version
));
507 DEBUG((DEBUG_VERBOSE
, " EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader
->EmbeddedDriverCount
));
508 DEBUG((DEBUG_VERBOSE
, " PayloadItemCount - 0x%x\n", FmpCapsuleHeader
->PayloadItemCount
));
510 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
511 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
512 DEBUG((DEBUG_VERBOSE
, " ItemOffsetList[%d] - 0x%lx\n", Index
, ItemOffsetList
[Index
]));
514 for (; Index
< (UINT32
)FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
; Index
++) {
515 DEBUG((DEBUG_VERBOSE
, " ItemOffsetList[%d] - 0x%lx\n", Index
, ItemOffsetList
[Index
]));
516 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
518 DEBUG((DEBUG_VERBOSE
, " ImageHeader:\n"));
519 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", ImageHeader
->Version
));
520 DEBUG((DEBUG_VERBOSE
, " UpdateImageTypeId - %g\n", &ImageHeader
->UpdateImageTypeId
));
521 DEBUG((DEBUG_VERBOSE
, " UpdateImageIndex - 0x%x\n", ImageHeader
->UpdateImageIndex
));
522 DEBUG((DEBUG_VERBOSE
, " UpdateImageSize - 0x%x\n", ImageHeader
->UpdateImageSize
));
523 DEBUG((DEBUG_VERBOSE
, " UpdateVendorCodeSize - 0x%x\n", ImageHeader
->UpdateVendorCodeSize
));
524 if (ImageHeader
->Version
>= 2) {
525 DEBUG((DEBUG_VERBOSE
, " UpdateHardwareInstance - 0x%lx\n", ImageHeader
->UpdateHardwareInstance
));
526 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
527 DEBUG((DEBUG_VERBOSE
, " ImageCapsuleSupport - 0x%lx\n", ImageHeader
->ImageCapsuleSupport
));
534 Dump all FMP information.
542 EFI_HANDLE
*HandleBuffer
;
543 UINTN NumberOfHandles
;
544 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
547 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
548 UINT32 FmpImageInfoDescriptorVer
;
549 UINT8 FmpImageInfoCount
;
550 UINTN DescriptorSize
;
551 UINT32 PackageVersion
;
552 CHAR16
*PackageVersionName
;
554 Status
= gBS
->LocateHandleBuffer (
556 &gEfiFirmwareManagementProtocolGuid
,
561 if (EFI_ERROR(Status
)) {
565 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
566 Status
= gBS
->HandleProtocol(
568 &gEfiFirmwareManagementProtocolGuid
,
571 if (EFI_ERROR(Status
)) {
576 Status
= Fmp
->GetImageInfo (
586 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
590 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
591 if (FmpImageInfoBuf
== NULL
) {
595 PackageVersionName
= NULL
;
596 Status
= Fmp
->GetImageInfo (
598 &ImageInfoSize
, // ImageInfoSize
599 FmpImageInfoBuf
, // ImageInfo
600 &FmpImageInfoDescriptorVer
, // DescriptorVersion
601 &FmpImageInfoCount
, // DescriptorCount
602 &DescriptorSize
, // DescriptorSize
603 &PackageVersion
, // PackageVersion
604 &PackageVersionName
// PackageVersionName
606 if (EFI_ERROR(Status
)) {
607 FreePool(FmpImageInfoBuf
);
611 DEBUG((DEBUG_INFO
, "FMP (%d) ImageInfo:\n", Index
));
613 ImageInfoSize
, // ImageInfoSize
614 FmpImageInfoBuf
, // ImageInfo
615 FmpImageInfoDescriptorVer
, // DescriptorVersion
616 FmpImageInfoCount
, // DescriptorCount
617 DescriptorSize
, // DescriptorSize
618 PackageVersion
, // PackageVersion
619 PackageVersionName
// PackageVersionName
622 if (PackageVersionName
!= NULL
) {
623 FreePool(PackageVersionName
);
626 FreePool(FmpImageInfoBuf
);
629 FreePool (HandleBuffer
);
635 Get FMP handle by ImageTypeId and HardwareInstance.
637 @param[in] UpdateImageTypeId Used to identify device firmware targeted by this update.
638 @param[in] UpdateHardwareInstance The HardwareInstance to target with this update.
639 @param[out] NoHandles The number of handles returned in HandleBuf.
640 @param[out] HandleBuf A pointer to the buffer to return the requested array of handles.
641 @param[out] ResetRequiredBuf A pointer to the buffer to return reset required flag for
642 the requested array of handles.
644 @retval EFI_SUCCESS The array of handles and their reset required flag were returned in
645 HandleBuf and ResetRequiredBuf, and the number of handles in HandleBuf
646 was returned in NoHandles.
647 @retval EFI_NOT_FOUND No handles match the search.
648 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
651 GetFmpHandleBufferByType (
652 IN EFI_GUID
*UpdateImageTypeId
,
653 IN UINT64 UpdateHardwareInstance
,
654 OUT UINTN
*NoHandles
, OPTIONAL
655 OUT EFI_HANDLE
**HandleBuf
, OPTIONAL
656 OUT BOOLEAN
**ResetRequiredBuf OPTIONAL
660 EFI_HANDLE
*HandleBuffer
;
661 UINTN NumberOfHandles
;
662 EFI_HANDLE
*MatchedHandleBuffer
;
663 BOOLEAN
*MatchedResetRequiredBuffer
;
664 UINTN MatchedNumberOfHandles
;
665 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
668 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
669 UINT32 FmpImageInfoDescriptorVer
;
670 UINT8 FmpImageInfoCount
;
671 UINTN DescriptorSize
;
672 UINT32 PackageVersion
;
673 CHAR16
*PackageVersionName
;
675 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*TempFmpImageInfo
;
677 if (NoHandles
!= NULL
) {
680 if (HandleBuf
!= NULL
) {
683 if (ResetRequiredBuf
!= NULL
) {
684 *ResetRequiredBuf
= NULL
;
687 Status
= gBS
->LocateHandleBuffer (
689 &gEfiFirmwareManagementProtocolGuid
,
694 if (EFI_ERROR(Status
)) {
698 MatchedNumberOfHandles
= 0;
700 MatchedHandleBuffer
= NULL
;
701 if (HandleBuf
!= NULL
) {
702 MatchedHandleBuffer
= AllocateZeroPool (sizeof(EFI_HANDLE
) * NumberOfHandles
);
703 if (MatchedHandleBuffer
== NULL
) {
704 FreePool (HandleBuffer
);
705 return EFI_OUT_OF_RESOURCES
;
709 MatchedResetRequiredBuffer
= NULL
;
710 if (ResetRequiredBuf
!= NULL
) {
711 MatchedResetRequiredBuffer
= AllocateZeroPool (sizeof(BOOLEAN
) * NumberOfHandles
);
712 if (MatchedResetRequiredBuffer
== NULL
) {
713 if (MatchedHandleBuffer
!= NULL
) {
714 FreePool (MatchedHandleBuffer
);
716 FreePool (HandleBuffer
);
717 return EFI_OUT_OF_RESOURCES
;
721 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
722 Status
= gBS
->HandleProtocol(
724 &gEfiFirmwareManagementProtocolGuid
,
727 if (EFI_ERROR(Status
)) {
732 Status
= Fmp
->GetImageInfo (
742 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
746 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
747 if (FmpImageInfoBuf
== NULL
) {
751 PackageVersionName
= NULL
;
752 Status
= Fmp
->GetImageInfo (
754 &ImageInfoSize
, // ImageInfoSize
755 FmpImageInfoBuf
, // ImageInfo
756 &FmpImageInfoDescriptorVer
, // DescriptorVersion
757 &FmpImageInfoCount
, // DescriptorCount
758 &DescriptorSize
, // DescriptorSize
759 &PackageVersion
, // PackageVersion
760 &PackageVersionName
// PackageVersionName
762 if (EFI_ERROR(Status
)) {
763 FreePool(FmpImageInfoBuf
);
767 if (PackageVersionName
!= NULL
) {
768 FreePool(PackageVersionName
);
771 TempFmpImageInfo
= FmpImageInfoBuf
;
772 for (Index2
= 0; Index2
< FmpImageInfoCount
; Index2
++) {
774 // Check if this FMP instance matches
776 if (CompareGuid(UpdateImageTypeId
, &TempFmpImageInfo
->ImageTypeId
)) {
777 if ((UpdateHardwareInstance
== 0) ||
778 ((FmpImageInfoDescriptorVer
>= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
) &&
779 (UpdateHardwareInstance
== TempFmpImageInfo
->HardwareInstance
))) {
780 if (MatchedHandleBuffer
!= NULL
) {
781 MatchedHandleBuffer
[MatchedNumberOfHandles
] = HandleBuffer
[Index
];
783 if (MatchedResetRequiredBuffer
!= NULL
) {
784 MatchedResetRequiredBuffer
[MatchedNumberOfHandles
] = (((TempFmpImageInfo
->AttributesSupported
&
785 IMAGE_ATTRIBUTE_RESET_REQUIRED
) != 0) &&
786 ((TempFmpImageInfo
->AttributesSetting
&
787 IMAGE_ATTRIBUTE_RESET_REQUIRED
) != 0));
789 MatchedNumberOfHandles
++;
793 TempFmpImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)TempFmpImageInfo
+ DescriptorSize
);
795 FreePool(FmpImageInfoBuf
);
798 FreePool (HandleBuffer
);
800 if (MatchedNumberOfHandles
== 0) {
801 return EFI_NOT_FOUND
;
804 if (NoHandles
!= NULL
) {
805 *NoHandles
= MatchedNumberOfHandles
;
807 if (HandleBuf
!= NULL
) {
808 *HandleBuf
= MatchedHandleBuffer
;
810 if (ResetRequiredBuf
!= NULL
) {
811 *ResetRequiredBuf
= MatchedResetRequiredBuffer
;
818 Return FmpImageInfoDescriptorVer by an FMP handle.
820 @param[in] Handle A FMP handle.
822 @return FmpImageInfoDescriptorVer associated with the FMP.
825 GetFmpImageInfoDescriptorVer (
830 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
832 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
833 UINT32 FmpImageInfoDescriptorVer
;
834 UINT8 FmpImageInfoCount
;
835 UINTN DescriptorSize
;
836 UINT32 PackageVersion
;
837 CHAR16
*PackageVersionName
;
839 Status
= gBS
->HandleProtocol(
841 &gEfiFirmwareManagementProtocolGuid
,
844 if (EFI_ERROR(Status
)) {
849 Status
= Fmp
->GetImageInfo (
859 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
863 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
864 if (FmpImageInfoBuf
== NULL
) {
868 PackageVersionName
= NULL
;
869 Status
= Fmp
->GetImageInfo (
871 &ImageInfoSize
, // ImageInfoSize
872 FmpImageInfoBuf
, // ImageInfo
873 &FmpImageInfoDescriptorVer
, // DescriptorVersion
874 &FmpImageInfoCount
, // DescriptorCount
875 &DescriptorSize
, // DescriptorSize
876 &PackageVersion
, // PackageVersion
877 &PackageVersionName
// PackageVersionName
879 if (EFI_ERROR(Status
)) {
880 FreePool(FmpImageInfoBuf
);
883 return FmpImageInfoDescriptorVer
;
889 @param[in] Handle A FMP handle.
890 @param[in] ImageHeader The payload image header.
891 @param[in] PayloadIndex The index of the payload.
893 @return The status of FMP->SetImage.
897 IN EFI_HANDLE Handle
,
898 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
,
899 IN UINTN PayloadIndex
903 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
907 EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS ProgressCallback
;
909 Status
= gBS
->HandleProtocol(
911 &gEfiFirmwareManagementProtocolGuid
,
914 if (EFI_ERROR(Status
)) {
919 // Lookup Firmware Management Progress Protocol before SetImage() is called
920 // This is an optional protocol that may not be present on Handle.
922 Status
= gBS
->HandleProtocol (
924 &gEdkiiFirmwareManagementProgressProtocolGuid
,
925 (VOID
**)&mFmpProgress
927 if (EFI_ERROR (Status
)) {
931 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
932 Image
= (UINT8
*)(ImageHeader
+ 1);
935 // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1,
936 // Header should exclude UpdateHardwareInstance field, and
937 // ImageCapsuleSupport field if version is 2.
939 if (ImageHeader
->Version
== 1) {
940 Image
= (UINT8
*)ImageHeader
+ OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
942 Image
= (UINT8
*)ImageHeader
+ OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, ImageCapsuleSupport
);
946 if (ImageHeader
->UpdateVendorCodeSize
== 0) {
949 VendorCode
= Image
+ ImageHeader
->UpdateImageSize
;
952 DEBUG((DEBUG_INFO
, "Fmp->SetImage ...\n"));
953 DEBUG((DEBUG_INFO
, "ImageTypeId - %g, ", &ImageHeader
->UpdateImageTypeId
));
954 DEBUG((DEBUG_INFO
, "PayloadIndex - 0x%x, ", PayloadIndex
));
955 DEBUG((DEBUG_INFO
, "ImageIndex - 0x%x ", ImageHeader
->UpdateImageIndex
));
956 if (ImageHeader
->Version
>= 2) {
957 DEBUG((DEBUG_INFO
, "(UpdateHardwareInstance - 0x%x)", ImageHeader
->UpdateHardwareInstance
));
958 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
959 DEBUG((DEBUG_INFO
, "(ImageCapsuleSupport - 0x%x)", ImageHeader
->ImageCapsuleSupport
));
962 DEBUG((DEBUG_INFO
, "\n"));
965 // Before calling SetImage(), reset the progress bar to 0%
967 ProgressCallback
= UpdateImageProgress
;
968 Status
= UpdateImageProgress (0);
969 if (EFI_ERROR (Status
)) {
970 ProgressCallback
= NULL
;
973 Status
= Fmp
->SetImage(
975 ImageHeader
->UpdateImageIndex
, // ImageIndex
977 ImageHeader
->UpdateImageSize
, // ImageSize
978 VendorCode
, // VendorCode
979 ProgressCallback
, // Progress
980 &AbortReason
// AbortReason
983 // Set the progress bar to 100% after returning from SetImage()
985 if (ProgressCallback
!= NULL
) {
986 UpdateImageProgress (100);
989 DEBUG((DEBUG_INFO
, "Fmp->SetImage - %r\n", Status
));
990 if (AbortReason
!= NULL
) {
991 DEBUG ((DEBUG_ERROR
, "%s\n", AbortReason
));
992 FreePool(AbortReason
);
996 // Clear mFmpProgress after SetImage() returns
1004 Start a UEFI image in the FMP payload.
1006 @param[in] ImageBuffer A pointer to the memory location containing a copy of the image to be loaded..
1007 @param[in] ImageSize The size in bytes of ImageBuffer.
1009 @return The status of gBS->LoadImage and gBS->StartImage.
1013 IN VOID
*ImageBuffer
,
1017 MEMMAP_DEVICE_PATH MemMapNode
;
1019 EFI_HANDLE ImageHandle
;
1020 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
1023 SetDevicePathNodeLength (&MemMapNode
.Header
, sizeof (MemMapNode
));
1024 MemMapNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
1025 MemMapNode
.Header
.SubType
= HW_MEMMAP_DP
;
1026 MemMapNode
.MemoryType
= EfiBootServicesCode
;
1027 MemMapNode
.StartingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)ImageBuffer
;
1028 MemMapNode
.EndingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)((UINT8
*)ImageBuffer
+ ImageSize
- 1);
1030 DriverDevicePath
= AppendDevicePathNode (NULL
, &MemMapNode
.Header
);
1031 if (DriverDevicePath
== NULL
) {
1032 return EFI_OUT_OF_RESOURCES
;
1035 DEBUG((DEBUG_INFO
, "FmpCapsule: LoadImage ...\n"));
1036 Status
= gBS
->LoadImage(
1044 DEBUG((DEBUG_INFO
, "FmpCapsule: LoadImage - %r\n", Status
));
1045 if (EFI_ERROR(Status
)) {
1047 // With EFI_SECURITY_VIOLATION retval, the Image was loaded and an ImageHandle was created
1048 // with a valid EFI_LOADED_IMAGE_PROTOCOL, but the image can not be started right now.
1049 // If the caller doesn't have the option to defer the execution of an image, we should
1050 // unload image for the EFI_SECURITY_VIOLATION to avoid resource leak.
1052 if (Status
== EFI_SECURITY_VIOLATION
) {
1053 gBS
->UnloadImage (ImageHandle
);
1055 FreePool(DriverDevicePath
);
1059 DEBUG((DEBUG_INFO
, "FmpCapsule: StartImage ...\n"));
1060 Status
= gBS
->StartImage(
1065 DEBUG((DEBUG_INFO
, "FmpCapsule: StartImage - %r\n", Status
));
1066 if (EFI_ERROR(Status
)) {
1067 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
1070 FreePool(DriverDevicePath
);
1075 Record FMP capsule status.
1077 @param[in] Handle A FMP handle.
1078 @param[in] CapsuleHeader The capsule image header
1079 @param[in] CapsuleStatus The capsule process stauts
1080 @param[in] PayloadIndex FMP payload index
1081 @param[in] ImageHeader FMP image header
1082 @param[in] CapFileName Capsule file name
1085 RecordFmpCapsuleStatus (
1086 IN EFI_HANDLE Handle
, OPTIONAL
1087 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
1088 IN EFI_STATUS CapsuleStatus
,
1089 IN UINTN PayloadIndex
,
1090 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
,
1091 IN CHAR16
*CapFileName OPTIONAL
1095 EFI_DEVICE_PATH_PROTOCOL
*FmpDevicePath
;
1096 UINT32 FmpImageInfoDescriptorVer
;
1097 EFI_STATUS StatusEsrt
;
1098 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
1099 EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry
;
1101 FmpDevicePath
= NULL
;
1102 if (Handle
!= NULL
) {
1103 gBS
->HandleProtocol(
1105 &gEfiDevicePathProtocolGuid
,
1106 (VOID
**)&FmpDevicePath
1110 RecordFmpCapsuleStatusVariable (
1120 // Update corresponding ESRT entry LastAttemp Status
1122 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
1123 if (EFI_ERROR (Status
)) {
1127 if (Handle
== NULL
) {
1132 // Update EsrtEntry For V1, V2 FMP instance.
1133 // V3 FMP ESRT cache will be synced up through SyncEsrtFmp interface
1135 FmpImageInfoDescriptorVer
= GetFmpImageInfoDescriptorVer (Handle
);
1136 if (FmpImageInfoDescriptorVer
< EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
) {
1137 StatusEsrt
= EsrtProtocol
->GetEsrtEntry(&ImageHeader
->UpdateImageTypeId
, &EsrtEntry
);
1138 if (!EFI_ERROR(StatusEsrt
)){
1139 if (!EFI_ERROR(CapsuleStatus
)) {
1140 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_SUCCESS
;
1142 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL
;
1144 EsrtEntry
.LastAttemptVersion
= 0;
1145 EsrtProtocol
->UpdateEsrtEntry(&EsrtEntry
);
1151 Process Firmware management protocol data capsule.
1153 This function assumes the caller validated the capsule by using
1154 ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
1155 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
1156 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
1158 This function need support nested FMP capsule.
1160 @param[in] CapsuleHeader Points to a capsule header.
1161 @param[in] CapFileName Capsule file name.
1162 @param[out] ResetRequired Indicates whether reset is required or not.
1164 @retval EFI_SUCESS Process Capsule Image successfully.
1165 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1166 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1167 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1168 @retval EFI_NOT_READY No FMP protocol to handle this FMP capsule.
1171 ProcessFmpCapsuleImage (
1172 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
1173 IN CHAR16
*CapFileName
, OPTIONAL
1174 OUT BOOLEAN
*ResetRequired OPTIONAL
1178 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
1179 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
1180 UINT64
*ItemOffsetList
;
1183 EFI_HANDLE
*HandleBuffer
;
1184 BOOLEAN
*ResetRequiredBuffer
;
1185 UINTN NumberOfHandles
;
1187 UINT64 UpdateHardwareInstance
;
1192 if (!IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
1193 return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
), CapFileName
, ResetRequired
);
1199 DumpFmpCapsule(CapsuleHeader
);
1201 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
1203 if (FmpCapsuleHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
1204 return EFI_INVALID_PARAMETER
;
1206 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
1208 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
1211 // capsule in which driver count and payload count are both zero is not processed.
1218 // 1. Try to load & start all the drivers within capsule
1220 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
1221 if ((FmpCapsuleHeader
->PayloadItemCount
== 0) &&
1222 (Index
== (UINTN
)FmpCapsuleHeader
->EmbeddedDriverCount
- 1)) {
1224 // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
1226 DriverLen
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
- (UINTN
)ItemOffsetList
[Index
];
1228 DriverLen
= (UINTN
)ItemOffsetList
[Index
+ 1] - (UINTN
)ItemOffsetList
[Index
];
1231 Status
= StartFmpImage (
1232 (UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
],
1235 if (EFI_ERROR(Status
)) {
1236 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
1242 // 2. Route payload to right FMP instance
1244 DEBUG((DEBUG_INFO
, "FmpCapsule: route payload to right FMP instance ...\n"));
1249 // Check all the payload entry in capsule payload list
1251 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
1252 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
1254 UpdateHardwareInstance
= 0;
1256 /// UpdateHardwareInstance field was added in Version 2
1258 if (ImageHeader
->Version
>= 2) {
1259 UpdateHardwareInstance
= ImageHeader
->UpdateHardwareInstance
;
1262 Status
= GetFmpHandleBufferByType (
1263 &ImageHeader
->UpdateImageTypeId
,
1264 UpdateHardwareInstance
,
1267 &ResetRequiredBuffer
1269 if (EFI_ERROR(Status
) ||
1270 (HandleBuffer
== NULL
) ||
1271 (ResetRequiredBuffer
== NULL
)) {
1273 RecordFmpCapsuleStatus (
1277 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1284 for (Index2
= 0; Index2
< NumberOfHandles
; Index2
++) {
1286 RecordFmpCapsuleStatus (
1287 HandleBuffer
[Index2
],
1290 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1297 Status
= SetFmpImageData (
1298 HandleBuffer
[Index2
],
1300 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
1302 if (Status
!= EFI_SUCCESS
) {
1305 if (ResetRequired
!= NULL
) {
1306 *ResetRequired
|= ResetRequiredBuffer
[Index2
];
1310 RecordFmpCapsuleStatus (
1311 HandleBuffer
[Index2
],
1314 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1319 if (HandleBuffer
!= NULL
) {
1320 FreePool(HandleBuffer
);
1322 if (ResetRequiredBuffer
!= NULL
) {
1323 FreePool(ResetRequiredBuffer
);
1328 return EFI_NOT_READY
;
1332 // always return SUCCESS to indicate this capsule is processed.
1333 // The status of SetImage is recorded in capsule result variable.
1339 Return if there is a FMP header below capsule header.
1341 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1343 @retval TRUE There is a FMP header below capsule header.
1344 @retval FALSE There is not a FMP header below capsule header
1347 IsNestedFmpCapsule (
1348 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1352 EFI_SYSTEM_RESOURCE_ENTRY
*EsrtEntry
;
1354 BOOLEAN EsrtGuidFound
;
1355 EFI_CAPSULE_HEADER
*NestedCapsuleHeader
;
1356 UINTN NestedCapsuleSize
;
1357 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
1358 EFI_SYSTEM_RESOURCE_ENTRY Entry
;
1360 EsrtGuidFound
= FALSE
;
1361 if (mIsVirtualAddrConverted
) {
1362 if(mEsrtTable
!= NULL
) {
1363 EsrtEntry
= (EFI_SYSTEM_RESOURCE_ENTRY
*)(mEsrtTable
+ 1);
1364 for (Index
= 0; Index
< mEsrtTable
->FwResourceCount
; Index
++, EsrtEntry
++) {
1365 if (CompareGuid(&EsrtEntry
->FwClass
, &CapsuleHeader
->CapsuleGuid
)) {
1366 EsrtGuidFound
= TRUE
;
1373 // Check ESRT protocol
1375 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
1376 if (!EFI_ERROR(Status
)) {
1377 Status
= EsrtProtocol
->GetEsrtEntry(&CapsuleHeader
->CapsuleGuid
, &Entry
);
1378 if (!EFI_ERROR(Status
)) {
1379 EsrtGuidFound
= TRUE
;
1384 // Check Firmware Management Protocols
1386 if (!EsrtGuidFound
) {
1387 Status
= GetFmpHandleBufferByType (
1388 &CapsuleHeader
->CapsuleGuid
,
1394 if (!EFI_ERROR(Status
)) {
1395 EsrtGuidFound
= TRUE
;
1399 if (!EsrtGuidFound
) {
1404 // Check nested capsule header
1405 // FMP GUID after ESRT one
1407 NestedCapsuleHeader
= (EFI_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
1408 NestedCapsuleSize
= (UINTN
)CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
- (UINTN
)NestedCapsuleHeader
;
1409 if (NestedCapsuleSize
< sizeof(EFI_CAPSULE_HEADER
)) {
1412 if (!IsValidCapsuleHeader(NestedCapsuleHeader
, NestedCapsuleSize
)) {
1415 if (!IsFmpCapsuleGuid(&NestedCapsuleHeader
->CapsuleGuid
)) {
1418 DEBUG ((DEBUG_INFO
, "IsNestedFmpCapsule\n"));
1423 Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
1425 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1427 @retval TRUE It is a system FMP.
1428 @retval FALSE It is a device FMP.
1432 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1435 if (IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
1438 if (IsNestedFmpCapsule(CapsuleHeader
)) {
1445 Those capsules supported by the firmwares.
1447 Caution: This function may receive untrusted input.
1449 @param[in] CapsuleHeader Points to a capsule header.
1451 @retval EFI_SUCESS Input capsule is supported by firmware.
1452 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
1453 @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
1457 SupportCapsuleImage (
1458 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1462 // check Display Capsule Guid
1464 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1469 // Check capsule file name capsule
1471 if (IsCapsuleNameCapsule(CapsuleHeader
)) {
1475 if (IsFmpCapsule(CapsuleHeader
)) {
1477 // Fake capsule header is valid case in QueryCapsuleCpapbilities().
1479 if (CapsuleHeader
->HeaderSize
== CapsuleHeader
->CapsuleImageSize
) {
1483 // Check layout of FMP capsule
1485 return ValidateFmpCapsule(CapsuleHeader
, NULL
);
1487 DEBUG((DEBUG_ERROR
, "Unknown Capsule Guid - %g\n", &CapsuleHeader
->CapsuleGuid
));
1488 return EFI_UNSUPPORTED
;
1492 The firmware implements to process the capsule image.
1494 Caution: This function may receive untrusted input.
1496 @param[in] CapsuleHeader Points to a capsule header.
1497 @param[in] CapFileName Capsule file name.
1498 @param[out] ResetRequired Indicates whether reset is required or not.
1500 @retval EFI_SUCESS Process Capsule Image successfully.
1501 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1502 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1503 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1507 ProcessThisCapsuleImage (
1508 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
1509 IN CHAR16
*CapFileName
, OPTIONAL
1510 OUT BOOLEAN
*ResetRequired OPTIONAL
1515 if (SupportCapsuleImage (CapsuleHeader
) != EFI_SUCCESS
) {
1516 RecordCapsuleStatusVariable(CapsuleHeader
, EFI_UNSUPPORTED
);
1517 return EFI_UNSUPPORTED
;
1521 // Display image in firmware update display capsule
1523 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1524 DEBUG((DEBUG_INFO
, "ProcessCapsuleImage for WindowsUxCapsule ...\n"));
1525 Status
= DisplayCapsuleImage(CapsuleHeader
);
1526 RecordCapsuleStatusVariable(CapsuleHeader
, Status
);
1531 // Check FMP capsule layout
1533 if (IsFmpCapsule (CapsuleHeader
)) {
1534 DEBUG((DEBUG_INFO
, "ProcessCapsuleImage for FmpCapsule ...\n"));
1535 DEBUG((DEBUG_INFO
, "ValidateFmpCapsule ...\n"));
1536 Status
= ValidateFmpCapsule(CapsuleHeader
, NULL
);
1537 DEBUG((DEBUG_INFO
, "ValidateFmpCapsule - %r\n", Status
));
1538 if (EFI_ERROR(Status
)) {
1539 RecordCapsuleStatusVariable(CapsuleHeader
, Status
);
1544 // Process EFI FMP Capsule
1546 DEBUG((DEBUG_INFO
, "ProcessFmpCapsuleImage ...\n"));
1547 Status
= ProcessFmpCapsuleImage(CapsuleHeader
, CapFileName
, ResetRequired
);
1548 DEBUG((DEBUG_INFO
, "ProcessFmpCapsuleImage - %r\n", Status
));
1553 return EFI_UNSUPPORTED
;
1557 The firmware implements to process the capsule image.
1559 Caution: This function may receive untrusted input.
1561 @param[in] CapsuleHeader Points to a capsule header.
1563 @retval EFI_SUCESS Process Capsule Image successfully.
1564 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1565 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1566 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1570 ProcessCapsuleImage (
1571 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1574 return ProcessThisCapsuleImage (CapsuleHeader
, NULL
, NULL
);
1578 Callback function executed when the EndOfDxe event group is signaled.
1580 @param[in] Event Event whose notification function is being invoked.
1581 @param[in] Context The pointer to the notification function's context, which
1582 is implementation-dependent.
1586 DxeCapsuleLibEndOfDxe (
1591 mDxeCapsuleLibEndOfDxe
= TRUE
;
1595 The constructor function.
1597 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1598 @param[in] SystemTable A pointer to the EFI System Table.
1600 @retval EFI_SUCCESS The constructor successfully .
1604 DxeCapsuleLibConstructor (
1605 IN EFI_HANDLE ImageHandle
,
1606 IN EFI_SYSTEM_TABLE
*SystemTable
1611 Status
= gBS
->CreateEventEx (
1614 DxeCapsuleLibEndOfDxe
,
1616 &gEfiEndOfDxeEventGroupGuid
,
1617 &mDxeCapsuleLibEndOfDxeEvent
1619 ASSERT_EFI_ERROR (Status
);
1621 InitCapsuleVariable();
1627 The destructor function closes the End of DXE event.
1629 @param ImageHandle The firmware allocated handle for the EFI image.
1630 @param SystemTable A pointer to the EFI System Table.
1632 @retval EFI_SUCCESS The destructor completed successfully.
1636 DxeCapsuleLibDestructor (
1637 IN EFI_HANDLE ImageHandle
,
1638 IN EFI_SYSTEM_TABLE
*SystemTable
1644 // Close the End of DXE event.
1646 Status
= gBS
->CloseEvent (mDxeCapsuleLibEndOfDxeEvent
);
1647 ASSERT_EFI_ERROR (Status
);