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 - 2018, Intel Corporation. All rights reserved.<BR>
14 This program and the accompanying materials
15 are licensed and made available under the terms and conditions of the BSD License
16 which accompanies this distribution. The full text of the license may be found at
17 http://opensource.org/licenses/bsd-license.php
19 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
20 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
26 #include <IndustryStandard/WindowsUxCapsule.h>
28 #include <Guid/FmpCapsule.h>
29 #include <Guid/SystemResourceTable.h>
30 #include <Guid/EventGroup.h>
32 #include <Library/BaseLib.h>
33 #include <Library/DebugLib.h>
34 #include <Library/BaseMemoryLib.h>
35 #include <Library/DxeServicesTableLib.h>
36 #include <Library/UefiBootServicesTableLib.h>
37 #include <Library/UefiRuntimeServicesTableLib.h>
38 #include <Library/MemoryAllocationLib.h>
39 #include <Library/CapsuleLib.h>
40 #include <Library/DevicePathLib.h>
41 #include <Library/UefiLib.h>
42 #include <Library/BmpSupportLib.h>
44 #include <Protocol/GraphicsOutput.h>
45 #include <Protocol/EsrtManagement.h>
46 #include <Protocol/FirmwareManagement.h>
47 #include <Protocol/FirmwareManagementProgress.h>
48 #include <Protocol/DevicePath.h>
50 EFI_SYSTEM_RESOURCE_TABLE
*mEsrtTable
= NULL
;
51 BOOLEAN mIsVirtualAddrConverted
= FALSE
;
53 BOOLEAN mDxeCapsuleLibEndOfDxe
= FALSE
;
54 EFI_EVENT mDxeCapsuleLibEndOfDxeEvent
= NULL
;
56 EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL
*mFmpProgress
= NULL
;
59 Initialize capsule related variables.
67 Record capsule status variable.
69 @param[in] CapsuleHeader The capsule image header
70 @param[in] CapsuleStatus The capsule process stauts
72 @retval EFI_SUCCESS The capsule status variable is recorded.
73 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
76 RecordCapsuleStatusVariable (
77 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
78 IN EFI_STATUS CapsuleStatus
82 Record FMP capsule status variable.
84 @param[in] CapsuleHeader The capsule image header
85 @param[in] CapsuleStatus The capsule process stauts
86 @param[in] PayloadIndex FMP payload index
87 @param[in] ImageHeader FMP image header
88 @param[in] FmpDevicePath DevicePath associated with the FMP producer
90 @retval EFI_SUCCESS The capsule status variable is recorded.
91 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
94 RecordFmpCapsuleStatusVariable (
95 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
96 IN EFI_STATUS CapsuleStatus
,
97 IN UINTN PayloadIndex
,
98 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
,
99 IN EFI_DEVICE_PATH_PROTOCOL
*FmpDevicePath OPTIONAL
103 Function indicate the current completion progress of the firmware
104 update. Platform may override with own specific progress function.
106 @param[in] Completion A value between 1 and 100 indicating the current
107 completion progress of the firmware update
109 @retval EFI_SUCESS The capsule update progress was updated.
110 @retval EFI_INVALID_PARAMETER Completion is greater than 100%.
114 UpdateImageProgress (
119 Return if this CapsuleGuid is a FMP capsule GUID or not.
121 @param[in] CapsuleGuid A pointer to EFI_GUID
123 @retval TRUE It is a FMP capsule GUID.
124 @retval FALSE It is not a FMP capsule GUID.
128 IN EFI_GUID
*CapsuleGuid
131 if (CompareGuid(&gEfiFmpCapsuleGuid
, CapsuleGuid
)) {
139 Validate if it is valid capsule header
141 Caution: This function may receive untrusted input.
143 This function assumes the caller provided correct CapsuleHeader pointer
146 This function validates the fields in EFI_CAPSULE_HEADER.
148 @param[in] CapsuleHeader Points to a capsule header.
149 @param[in] CapsuleSize Size of the whole capsule image.
153 IsValidCapsuleHeader (
154 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
155 IN UINT64 CapsuleSize
158 if (CapsuleHeader
->CapsuleImageSize
!= CapsuleSize
) {
161 if (CapsuleHeader
->HeaderSize
>= CapsuleHeader
->CapsuleImageSize
) {
168 Validate Fmp capsules layout.
170 Caution: This function may receive untrusted input.
172 This function assumes the caller validated the capsule by using
173 IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.
174 The capsule buffer size is CapsuleHeader->CapsuleImageSize.
176 This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
177 and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
179 This function need support nested FMP capsule.
181 @param[in] CapsuleHeader Points to a capsule header.
182 @param[out] EmbeddedDriverCount The EmbeddedDriverCount in the FMP capsule.
184 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
185 @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.
189 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
190 OUT UINT16
*EmbeddedDriverCount OPTIONAL
193 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
195 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
197 UINT64
*ItemOffsetList
;
200 UINTN FmpCapsuleSize
;
201 UINTN FmpCapsuleHeaderSize
;
203 UINTN FmpImageHeaderSize
;
205 if (!IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
206 return ValidateFmpCapsule ((EFI_CAPSULE_HEADER
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
), EmbeddedDriverCount
);
209 if (CapsuleHeader
->HeaderSize
>= CapsuleHeader
->CapsuleImageSize
) {
210 DEBUG((DEBUG_ERROR
, "HeaderSize(0x%x) >= CapsuleImageSize(0x%x)\n", CapsuleHeader
->HeaderSize
, CapsuleHeader
->CapsuleImageSize
));
211 return EFI_INVALID_PARAMETER
;
214 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
215 EndOfCapsule
= (UINT8
*) CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
;
216 FmpCapsuleSize
= (UINTN
)EndOfCapsule
- (UINTN
)FmpCapsuleHeader
;
218 if (FmpCapsuleSize
< sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
)) {
219 DEBUG((DEBUG_ERROR
, "FmpCapsuleSize(0x%x) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\n", FmpCapsuleSize
));
220 return EFI_INVALID_PARAMETER
;
223 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
224 if (FmpCapsuleHeader
->Version
!= EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
225 DEBUG((DEBUG_ERROR
, "FmpCapsuleHeader->Version(0x%x) != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION\n", FmpCapsuleHeader
->Version
));
226 return EFI_INVALID_PARAMETER
;
228 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
231 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
233 if ((FmpCapsuleSize
- sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
))/sizeof(UINT64
) < ItemNum
) {
234 DEBUG((DEBUG_ERROR
, "ItemNum(0x%x) too big\n", ItemNum
));
235 return EFI_INVALID_PARAMETER
;
237 FmpCapsuleHeaderSize
= sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
) + sizeof(UINT64
)*ItemNum
;
239 // Check ItemOffsetList
240 for (Index
= 0; Index
< ItemNum
; Index
++) {
241 if (ItemOffsetList
[Index
] >= FmpCapsuleSize
) {
242 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) >= FmpCapsuleSize(0x%x)\n", Index
, ItemOffsetList
[Index
], FmpCapsuleSize
));
243 return EFI_INVALID_PARAMETER
;
245 if (ItemOffsetList
[Index
] < FmpCapsuleHeaderSize
) {
246 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) < FmpCapsuleHeaderSize(0x%x)\n", Index
, ItemOffsetList
[Index
], FmpCapsuleHeaderSize
));
247 return EFI_INVALID_PARAMETER
;
250 // All the address in ItemOffsetList must be stored in ascending order
253 if (ItemOffsetList
[Index
] <= ItemOffsetList
[Index
- 1]) {
254 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) < ItemOffsetList[%d](0x%x)\n", Index
, ItemOffsetList
[Index
], Index
- 1, ItemOffsetList
[Index
- 1]));
255 return EFI_INVALID_PARAMETER
;
260 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
261 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
262 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
263 if (Index
== ItemNum
- 1) {
264 EndOfPayload
= (UINT8
*)((UINTN
)EndOfCapsule
- (UINTN
)FmpCapsuleHeader
);
266 EndOfPayload
= (UINT8
*)(UINTN
)ItemOffsetList
[Index
+1];
268 FmpImageSize
= (UINTN
)EndOfPayload
- ItemOffsetList
[Index
];
270 FmpImageHeaderSize
= sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
);
271 if ((ImageHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) ||
272 (ImageHeader
->Version
< 1)) {
273 DEBUG((DEBUG_ERROR
, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader
->Version
));
274 return EFI_INVALID_PARAMETER
;
276 if (ImageHeader
->Version
< EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
277 FmpImageHeaderSize
= OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
279 if (FmpImageSize
< FmpImageHeaderSize
) {
280 DEBUG((DEBUG_ERROR
, "FmpImageSize(0x%lx) < FmpImageHeaderSize(0x%x)\n", FmpImageSize
, FmpImageHeaderSize
));
281 return EFI_INVALID_PARAMETER
;
285 if (FmpImageSize
!= (UINT64
)FmpImageHeaderSize
+ (UINT64
)ImageHeader
->UpdateImageSize
+ (UINT64
)ImageHeader
->UpdateVendorCodeSize
) {
286 DEBUG((DEBUG_ERROR
, "FmpImageSize(0x%lx) mismatch, UpdateImageSize(0x%x) UpdateVendorCodeSize(0x%x)\n", FmpImageSize
, ImageHeader
->UpdateImageSize
, ImageHeader
->UpdateVendorCodeSize
));
287 return EFI_INVALID_PARAMETER
;
293 // No driver & payload element in FMP
295 EndOfPayload
= (UINT8
*)(FmpCapsuleHeader
+ 1);
296 if (EndOfPayload
!= EndOfCapsule
) {
297 DEBUG((DEBUG_ERROR
, "EndOfPayload(0x%x) mismatch, EndOfCapsule(0x%x)\n", EndOfPayload
, EndOfCapsule
));
298 return EFI_INVALID_PARAMETER
;
300 return EFI_UNSUPPORTED
;
303 if (EmbeddedDriverCount
!= NULL
) {
304 *EmbeddedDriverCount
= FmpCapsuleHeader
->EmbeddedDriverCount
;
311 Those capsules supported by the firmwares.
313 Caution: This function may receive untrusted input.
315 @param[in] CapsuleHeader Points to a capsule header.
317 @retval EFI_SUCESS Input capsule is supported by firmware.
318 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
321 DisplayCapsuleImage (
322 IN EFI_CAPSULE_HEADER
*CapsuleHeader
325 DISPLAY_DISPLAY_PAYLOAD
*ImagePayload
;
328 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
332 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
335 // UX capsule doesn't have extended header entries.
337 if (CapsuleHeader
->HeaderSize
!= sizeof (EFI_CAPSULE_HEADER
)) {
338 return EFI_UNSUPPORTED
;
340 ImagePayload
= (DISPLAY_DISPLAY_PAYLOAD
*)((UINTN
) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
342 // (CapsuleImageSize > HeaderSize) is guaranteed by IsValidCapsuleHeader().
344 PayloadSize
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
;
347 // Make sure the image payload at least contain the DISPLAY_DISPLAY_PAYLOAD header.
348 // Further size check is performed by the logic translating BMP to GOP BLT.
350 if (PayloadSize
<= sizeof (DISPLAY_DISPLAY_PAYLOAD
)) {
351 return EFI_INVALID_PARAMETER
;
354 if (ImagePayload
->Version
!= 1) {
355 return EFI_UNSUPPORTED
;
357 if (CalculateCheckSum8((UINT8
*)CapsuleHeader
, CapsuleHeader
->CapsuleImageSize
) != 0) {
358 return EFI_UNSUPPORTED
;
361 // Only Support Bitmap by now
363 if (ImagePayload
->ImageType
!= 0) {
364 return EFI_UNSUPPORTED
;
370 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**)&GraphicsOutput
);
371 if (EFI_ERROR (Status
)) {
372 Status
= gBS
->LocateProtocol(&gEfiGraphicsOutputProtocolGuid
, NULL
, (VOID
**)&GraphicsOutput
);
373 if (EFI_ERROR(Status
)) {
374 return EFI_UNSUPPORTED
;
378 if (GraphicsOutput
->Mode
->Mode
!= ImagePayload
->Mode
) {
379 return EFI_UNSUPPORTED
;
385 Status
= TranslateBmpToGopBlt (
387 PayloadSize
- sizeof(DISPLAY_DISPLAY_PAYLOAD
),
394 if (EFI_ERROR (Status
)) {
398 Status
= GraphicsOutput
->Blt (
404 (UINTN
) ImagePayload
->OffsetX
,
405 (UINTN
) ImagePayload
->OffsetY
,
408 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
417 Dump FMP information.
419 @param[in] ImageInfoSize The size of ImageInfo, in bytes.
420 @param[in] ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
421 @param[in] DescriptorVersion The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
422 @param[in] DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
423 @param[in] DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
424 @param[in] PackageVersion The version of package.
425 @param[in] PackageVersionName The version name of package.
429 IN UINTN ImageInfoSize
,
430 IN EFI_FIRMWARE_IMAGE_DESCRIPTOR
*ImageInfo
,
431 IN UINT32 DescriptorVersion
,
432 IN UINT8 DescriptorCount
,
433 IN UINTN DescriptorSize
,
434 IN UINT32 PackageVersion
,
435 IN CHAR16
*PackageVersionName
438 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*CurrentImageInfo
;
441 DEBUG((DEBUG_VERBOSE
, " DescriptorVersion - 0x%x\n", DescriptorVersion
));
442 DEBUG((DEBUG_VERBOSE
, " DescriptorCount - 0x%x\n", DescriptorCount
));
443 DEBUG((DEBUG_VERBOSE
, " DescriptorSize - 0x%x\n", DescriptorSize
));
444 DEBUG((DEBUG_VERBOSE
, " PackageVersion - 0x%x\n", PackageVersion
));
445 DEBUG((DEBUG_VERBOSE
, " PackageVersionName - %s\n\n", PackageVersionName
));
446 CurrentImageInfo
= ImageInfo
;
447 for (Index
= 0; Index
< DescriptorCount
; Index
++) {
448 DEBUG((DEBUG_VERBOSE
, " ImageDescriptor (%d)\n", Index
));
449 DEBUG((DEBUG_VERBOSE
, " ImageIndex - 0x%x\n", CurrentImageInfo
->ImageIndex
));
450 DEBUG((DEBUG_VERBOSE
, " ImageTypeId - %g\n", &CurrentImageInfo
->ImageTypeId
));
451 DEBUG((DEBUG_VERBOSE
, " ImageId - 0x%lx\n", CurrentImageInfo
->ImageId
));
452 DEBUG((DEBUG_VERBOSE
, " ImageIdName - %s\n", CurrentImageInfo
->ImageIdName
));
453 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", CurrentImageInfo
->Version
));
454 DEBUG((DEBUG_VERBOSE
, " VersionName - %s\n", CurrentImageInfo
->VersionName
));
455 DEBUG((DEBUG_VERBOSE
, " Size - 0x%x\n", CurrentImageInfo
->Size
));
456 DEBUG((DEBUG_VERBOSE
, " AttributesSupported - 0x%lx\n", CurrentImageInfo
->AttributesSupported
));
457 DEBUG((DEBUG_VERBOSE
, " AttributesSetting - 0x%lx\n", CurrentImageInfo
->AttributesSetting
));
458 DEBUG((DEBUG_VERBOSE
, " Compatibilities - 0x%lx\n", CurrentImageInfo
->Compatibilities
));
459 if (DescriptorVersion
> 1) {
460 DEBUG((DEBUG_VERBOSE
, " LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo
->LowestSupportedImageVersion
));
461 if (DescriptorVersion
> 2) {
462 DEBUG((DEBUG_VERBOSE
, " LastAttemptVersion - 0x%x\n", CurrentImageInfo
->LastAttemptVersion
));
463 DEBUG((DEBUG_VERBOSE
, " LastAttemptStatus - 0x%x\n", CurrentImageInfo
->LastAttemptStatus
));
464 DEBUG((DEBUG_VERBOSE
, " HardwareInstance - 0x%lx\n", CurrentImageInfo
->HardwareInstance
));
468 // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
470 CurrentImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)CurrentImageInfo
+ DescriptorSize
);
475 Dump a non-nested FMP capsule.
477 @param[in] CapsuleHeader A pointer to CapsuleHeader
481 IN EFI_CAPSULE_HEADER
*CapsuleHeader
484 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
485 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
487 UINT64
*ItemOffsetList
;
489 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
491 DEBUG((DEBUG_VERBOSE
, "FmpCapsule:\n"));
492 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", FmpCapsuleHeader
->Version
));
493 DEBUG((DEBUG_VERBOSE
, " EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader
->EmbeddedDriverCount
));
494 DEBUG((DEBUG_VERBOSE
, " PayloadItemCount - 0x%x\n", FmpCapsuleHeader
->PayloadItemCount
));
496 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
497 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
498 DEBUG((DEBUG_VERBOSE
, " ItemOffsetList[%d] - 0x%lx\n", Index
, ItemOffsetList
[Index
]));
500 for (; Index
< (UINT32
)FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
; Index
++) {
501 DEBUG((DEBUG_VERBOSE
, " ItemOffsetList[%d] - 0x%lx\n", Index
, ItemOffsetList
[Index
]));
502 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
504 DEBUG((DEBUG_VERBOSE
, " ImageHeader:\n"));
505 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", ImageHeader
->Version
));
506 DEBUG((DEBUG_VERBOSE
, " UpdateImageTypeId - %g\n", &ImageHeader
->UpdateImageTypeId
));
507 DEBUG((DEBUG_VERBOSE
, " UpdateImageIndex - 0x%x\n", ImageHeader
->UpdateImageIndex
));
508 DEBUG((DEBUG_VERBOSE
, " UpdateImageSize - 0x%x\n", ImageHeader
->UpdateImageSize
));
509 DEBUG((DEBUG_VERBOSE
, " UpdateVendorCodeSize - 0x%x\n", ImageHeader
->UpdateVendorCodeSize
));
510 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
511 DEBUG((DEBUG_VERBOSE
, " UpdateHardwareInstance - 0x%lx\n", ImageHeader
->UpdateHardwareInstance
));
517 Dump all FMP information.
525 EFI_HANDLE
*HandleBuffer
;
526 UINTN NumberOfHandles
;
527 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
530 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
531 UINT32 FmpImageInfoDescriptorVer
;
532 UINT8 FmpImageInfoCount
;
533 UINTN DescriptorSize
;
534 UINT32 PackageVersion
;
535 CHAR16
*PackageVersionName
;
537 Status
= gBS
->LocateHandleBuffer (
539 &gEfiFirmwareManagementProtocolGuid
,
544 if (EFI_ERROR(Status
)) {
548 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
549 Status
= gBS
->HandleProtocol(
551 &gEfiFirmwareManagementProtocolGuid
,
554 if (EFI_ERROR(Status
)) {
559 Status
= Fmp
->GetImageInfo (
569 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
573 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
574 if (FmpImageInfoBuf
== NULL
) {
578 PackageVersionName
= NULL
;
579 Status
= Fmp
->GetImageInfo (
581 &ImageInfoSize
, // ImageInfoSize
582 FmpImageInfoBuf
, // ImageInfo
583 &FmpImageInfoDescriptorVer
, // DescriptorVersion
584 &FmpImageInfoCount
, // DescriptorCount
585 &DescriptorSize
, // DescriptorSize
586 &PackageVersion
, // PackageVersion
587 &PackageVersionName
// PackageVersionName
589 if (EFI_ERROR(Status
)) {
590 FreePool(FmpImageInfoBuf
);
594 DEBUG((DEBUG_INFO
, "FMP (%d) ImageInfo:\n", Index
));
596 ImageInfoSize
, // ImageInfoSize
597 FmpImageInfoBuf
, // ImageInfo
598 FmpImageInfoDescriptorVer
, // DescriptorVersion
599 FmpImageInfoCount
, // DescriptorCount
600 DescriptorSize
, // DescriptorSize
601 PackageVersion
, // PackageVersion
602 PackageVersionName
// PackageVersionName
605 if (PackageVersionName
!= NULL
) {
606 FreePool(PackageVersionName
);
609 FreePool(FmpImageInfoBuf
);
612 FreePool (HandleBuffer
);
618 Get FMP handle by ImageTypeId and HardwareInstance.
620 @param[in] UpdateImageTypeId Used to identify device firmware targeted by this update.
621 @param[in] UpdateHardwareInstance The HardwareInstance to target with this update.
622 @param[out] NoHandles The number of handles returned in HandleBuf.
623 @param[out] HandleBuf A pointer to the buffer to return the requested array of handles.
624 @param[out] ResetRequiredBuf A pointer to the buffer to return reset required flag for
625 the requested array of handles.
627 @retval EFI_SUCCESS The array of handles and their reset required flag were returned in
628 HandleBuf and ResetRequiredBuf, and the number of handles in HandleBuf
629 was returned in NoHandles.
630 @retval EFI_NOT_FOUND No handles match the search.
631 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
634 GetFmpHandleBufferByType (
635 IN EFI_GUID
*UpdateImageTypeId
,
636 IN UINT64 UpdateHardwareInstance
,
637 OUT UINTN
*NoHandles
, OPTIONAL
638 OUT EFI_HANDLE
**HandleBuf
, OPTIONAL
639 OUT BOOLEAN
**ResetRequiredBuf OPTIONAL
643 EFI_HANDLE
*HandleBuffer
;
644 UINTN NumberOfHandles
;
645 EFI_HANDLE
*MatchedHandleBuffer
;
646 BOOLEAN
*MatchedResetRequiredBuffer
;
647 UINTN MatchedNumberOfHandles
;
648 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
651 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
652 UINT32 FmpImageInfoDescriptorVer
;
653 UINT8 FmpImageInfoCount
;
654 UINTN DescriptorSize
;
655 UINT32 PackageVersion
;
656 CHAR16
*PackageVersionName
;
658 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*TempFmpImageInfo
;
660 if (NoHandles
!= NULL
) {
663 if (HandleBuf
!= NULL
) {
666 if (ResetRequiredBuf
!= NULL
) {
667 *ResetRequiredBuf
= NULL
;
670 Status
= gBS
->LocateHandleBuffer (
672 &gEfiFirmwareManagementProtocolGuid
,
677 if (EFI_ERROR(Status
)) {
681 MatchedNumberOfHandles
= 0;
683 MatchedHandleBuffer
= NULL
;
684 if (HandleBuf
!= NULL
) {
685 MatchedHandleBuffer
= AllocateZeroPool (sizeof(EFI_HANDLE
) * NumberOfHandles
);
686 if (MatchedHandleBuffer
== NULL
) {
687 FreePool (HandleBuffer
);
688 return EFI_OUT_OF_RESOURCES
;
692 MatchedResetRequiredBuffer
= NULL
;
693 if (ResetRequiredBuf
!= NULL
) {
694 MatchedResetRequiredBuffer
= AllocateZeroPool (sizeof(BOOLEAN
) * NumberOfHandles
);
695 if (MatchedResetRequiredBuffer
== NULL
) {
696 if (MatchedHandleBuffer
!= NULL
) {
697 FreePool (MatchedHandleBuffer
);
699 FreePool (HandleBuffer
);
700 return EFI_OUT_OF_RESOURCES
;
704 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
705 Status
= gBS
->HandleProtocol(
707 &gEfiFirmwareManagementProtocolGuid
,
710 if (EFI_ERROR(Status
)) {
715 Status
= Fmp
->GetImageInfo (
725 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
729 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
730 if (FmpImageInfoBuf
== NULL
) {
734 PackageVersionName
= NULL
;
735 Status
= Fmp
->GetImageInfo (
737 &ImageInfoSize
, // ImageInfoSize
738 FmpImageInfoBuf
, // ImageInfo
739 &FmpImageInfoDescriptorVer
, // DescriptorVersion
740 &FmpImageInfoCount
, // DescriptorCount
741 &DescriptorSize
, // DescriptorSize
742 &PackageVersion
, // PackageVersion
743 &PackageVersionName
// PackageVersionName
745 if (EFI_ERROR(Status
)) {
746 FreePool(FmpImageInfoBuf
);
750 if (PackageVersionName
!= NULL
) {
751 FreePool(PackageVersionName
);
754 TempFmpImageInfo
= FmpImageInfoBuf
;
755 for (Index2
= 0; Index2
< FmpImageInfoCount
; Index2
++) {
757 // Check if this FMP instance matches
759 if (CompareGuid(UpdateImageTypeId
, &TempFmpImageInfo
->ImageTypeId
)) {
760 if ((UpdateHardwareInstance
== 0) ||
761 ((FmpImageInfoDescriptorVer
>= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
) &&
762 (UpdateHardwareInstance
== TempFmpImageInfo
->HardwareInstance
))) {
763 if (MatchedHandleBuffer
!= NULL
) {
764 MatchedHandleBuffer
[MatchedNumberOfHandles
] = HandleBuffer
[Index
];
766 if (MatchedResetRequiredBuffer
!= NULL
) {
767 MatchedResetRequiredBuffer
[MatchedNumberOfHandles
] = (((TempFmpImageInfo
->AttributesSupported
&
768 IMAGE_ATTRIBUTE_RESET_REQUIRED
) != 0) &&
769 ((TempFmpImageInfo
->AttributesSetting
&
770 IMAGE_ATTRIBUTE_RESET_REQUIRED
) != 0));
772 MatchedNumberOfHandles
++;
776 TempFmpImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)TempFmpImageInfo
+ DescriptorSize
);
778 FreePool(FmpImageInfoBuf
);
781 FreePool (HandleBuffer
);
783 if (MatchedNumberOfHandles
== 0) {
784 return EFI_NOT_FOUND
;
787 if (NoHandles
!= NULL
) {
788 *NoHandles
= MatchedNumberOfHandles
;
790 if (HandleBuf
!= NULL
) {
791 *HandleBuf
= MatchedHandleBuffer
;
793 if (ResetRequiredBuf
!= NULL
) {
794 *ResetRequiredBuf
= MatchedResetRequiredBuffer
;
801 Return FmpImageInfoDescriptorVer by an FMP handle.
803 @param[in] Handle A FMP handle.
805 @return FmpImageInfoDescriptorVer associated with the FMP.
808 GetFmpImageInfoDescriptorVer (
813 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
815 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
816 UINT32 FmpImageInfoDescriptorVer
;
817 UINT8 FmpImageInfoCount
;
818 UINTN DescriptorSize
;
819 UINT32 PackageVersion
;
820 CHAR16
*PackageVersionName
;
822 Status
= gBS
->HandleProtocol(
824 &gEfiFirmwareManagementProtocolGuid
,
827 if (EFI_ERROR(Status
)) {
832 Status
= Fmp
->GetImageInfo (
842 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
846 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
847 if (FmpImageInfoBuf
== NULL
) {
851 PackageVersionName
= NULL
;
852 Status
= Fmp
->GetImageInfo (
854 &ImageInfoSize
, // ImageInfoSize
855 FmpImageInfoBuf
, // ImageInfo
856 &FmpImageInfoDescriptorVer
, // DescriptorVersion
857 &FmpImageInfoCount
, // DescriptorCount
858 &DescriptorSize
, // DescriptorSize
859 &PackageVersion
, // PackageVersion
860 &PackageVersionName
// PackageVersionName
862 if (EFI_ERROR(Status
)) {
863 FreePool(FmpImageInfoBuf
);
866 return FmpImageInfoDescriptorVer
;
872 @param[in] Handle A FMP handle.
873 @param[in] ImageHeader The payload image header.
874 @param[in] PayloadIndex The index of the payload.
876 @return The status of FMP->SetImage.
880 IN EFI_HANDLE Handle
,
881 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
,
882 IN UINTN PayloadIndex
886 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
890 EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS ProgressCallback
;
892 Status
= gBS
->HandleProtocol(
894 &gEfiFirmwareManagementProtocolGuid
,
897 if (EFI_ERROR(Status
)) {
902 // Lookup Firmware Management Progress Protocol before SetImage() is called
903 // This is an optional protocol that may not be present on Handle.
905 Status
= gBS
->HandleProtocol (
907 &gEdkiiFirmwareManagementProgressProtocolGuid
,
908 (VOID
**)&mFmpProgress
910 if (EFI_ERROR (Status
)) {
914 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
915 Image
= (UINT8
*)(ImageHeader
+ 1);
918 // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1,
919 // Header should exclude UpdateHardwareInstance field
921 Image
= (UINT8
*)ImageHeader
+ OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
924 if (ImageHeader
->UpdateVendorCodeSize
== 0) {
927 VendorCode
= Image
+ ImageHeader
->UpdateImageSize
;
930 DEBUG((DEBUG_INFO
, "Fmp->SetImage ...\n"));
931 DEBUG((DEBUG_INFO
, "ImageTypeId - %g, ", &ImageHeader
->UpdateImageTypeId
));
932 DEBUG((DEBUG_INFO
, "PayloadIndex - 0x%x, ", PayloadIndex
));
933 DEBUG((DEBUG_INFO
, "ImageIndex - 0x%x ", ImageHeader
->UpdateImageIndex
));
934 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
935 DEBUG((DEBUG_INFO
, "(UpdateHardwareInstance - 0x%x)", ImageHeader
->UpdateHardwareInstance
));
937 DEBUG((DEBUG_INFO
, "\n"));
940 // Before calling SetImage(), reset the progress bar to 0%
942 ProgressCallback
= UpdateImageProgress
;
943 Status
= UpdateImageProgress (0);
944 if (EFI_ERROR (Status
)) {
945 ProgressCallback
= NULL
;
948 Status
= Fmp
->SetImage(
950 ImageHeader
->UpdateImageIndex
, // ImageIndex
952 ImageHeader
->UpdateImageSize
, // ImageSize
953 VendorCode
, // VendorCode
954 ProgressCallback
, // Progress
955 &AbortReason
// AbortReason
958 // Set the progress bar to 100% after returning from SetImage()
960 if (ProgressCallback
!= NULL
) {
961 UpdateImageProgress (100);
964 DEBUG((DEBUG_INFO
, "Fmp->SetImage - %r\n", Status
));
965 if (AbortReason
!= NULL
) {
966 DEBUG ((DEBUG_ERROR
, "%s\n", AbortReason
));
967 FreePool(AbortReason
);
971 // Clear mFmpProgress after SetImage() returns
979 Start a UEFI image in the FMP payload.
981 @param[in] ImageBuffer A pointer to the memory location containing a copy of the image to be loaded..
982 @param[in] ImageSize The size in bytes of ImageBuffer.
984 @return The status of gBS->LoadImage and gBS->StartImage.
988 IN VOID
*ImageBuffer
,
992 MEMMAP_DEVICE_PATH MemMapNode
;
994 EFI_HANDLE ImageHandle
;
995 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
998 SetDevicePathNodeLength (&MemMapNode
.Header
, sizeof (MemMapNode
));
999 MemMapNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
1000 MemMapNode
.Header
.SubType
= HW_MEMMAP_DP
;
1001 MemMapNode
.MemoryType
= EfiBootServicesCode
;
1002 MemMapNode
.StartingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)ImageBuffer
;
1003 MemMapNode
.EndingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)((UINT8
*)ImageBuffer
+ ImageSize
- 1);
1005 DriverDevicePath
= AppendDevicePathNode (NULL
, &MemMapNode
.Header
);
1006 if (DriverDevicePath
== NULL
) {
1007 return EFI_OUT_OF_RESOURCES
;
1010 DEBUG((DEBUG_INFO
, "FmpCapsule: LoadImage ...\n"));
1011 Status
= gBS
->LoadImage(
1019 DEBUG((DEBUG_INFO
, "FmpCapsule: LoadImage - %r\n", Status
));
1020 if (EFI_ERROR(Status
)) {
1021 FreePool(DriverDevicePath
);
1025 DEBUG((DEBUG_INFO
, "FmpCapsule: StartImage ...\n"));
1026 Status
= gBS
->StartImage(
1031 DEBUG((DEBUG_INFO
, "FmpCapsule: StartImage - %r\n", Status
));
1032 if (EFI_ERROR(Status
)) {
1033 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
1036 FreePool(DriverDevicePath
);
1041 Record FMP capsule status.
1043 @param[in] Handle A FMP handle.
1044 @param[in] CapsuleHeader The capsule image header
1045 @param[in] CapsuleStatus The capsule process stauts
1046 @param[in] PayloadIndex FMP payload index
1047 @param[in] ImageHeader FMP image header
1050 RecordFmpCapsuleStatus (
1051 IN EFI_HANDLE Handle
, OPTIONAL
1052 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
1053 IN EFI_STATUS CapsuleStatus
,
1054 IN UINTN PayloadIndex
,
1055 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
1059 EFI_DEVICE_PATH_PROTOCOL
*FmpDevicePath
;
1060 UINT32 FmpImageInfoDescriptorVer
;
1061 EFI_STATUS StatusEsrt
;
1062 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
1063 EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry
;
1065 FmpDevicePath
= NULL
;
1066 if (Handle
!= NULL
) {
1067 gBS
->HandleProtocol(
1069 &gEfiDevicePathProtocolGuid
,
1070 (VOID
**)&FmpDevicePath
1074 RecordFmpCapsuleStatusVariable (
1083 // Update corresponding ESRT entry LastAttemp Status
1085 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
1086 if (EFI_ERROR (Status
)) {
1090 if (Handle
== NULL
) {
1095 // Update EsrtEntry For V1, V2 FMP instance.
1096 // V3 FMP ESRT cache will be synced up through SyncEsrtFmp interface
1098 FmpImageInfoDescriptorVer
= GetFmpImageInfoDescriptorVer (Handle
);
1099 if (FmpImageInfoDescriptorVer
< EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
) {
1100 StatusEsrt
= EsrtProtocol
->GetEsrtEntry(&ImageHeader
->UpdateImageTypeId
, &EsrtEntry
);
1101 if (!EFI_ERROR(StatusEsrt
)){
1102 if (!EFI_ERROR(CapsuleStatus
)) {
1103 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_SUCCESS
;
1105 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL
;
1107 EsrtEntry
.LastAttemptVersion
= 0;
1108 EsrtProtocol
->UpdateEsrtEntry(&EsrtEntry
);
1114 Process Firmware management protocol data capsule.
1116 This function assumes the caller validated the capsule by using
1117 ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
1118 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
1119 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
1121 This function need support nested FMP capsule.
1123 @param[in] CapsuleHeader Points to a capsule header.
1124 @param[out] ResetRequired Indicates whether reset is required or not.
1126 @retval EFI_SUCESS Process Capsule Image successfully.
1127 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1128 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1129 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1130 @retval EFI_NOT_READY No FMP protocol to handle this FMP capsule.
1133 ProcessFmpCapsuleImage (
1134 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
1135 OUT BOOLEAN
*ResetRequired OPTIONAL
1139 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
1140 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
1141 UINT64
*ItemOffsetList
;
1144 EFI_HANDLE
*HandleBuffer
;
1145 BOOLEAN
*ResetRequiredBuffer
;
1146 UINTN NumberOfHandles
;
1148 UINT64 UpdateHardwareInstance
;
1153 if (!IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
1154 return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
), ResetRequired
);
1160 DumpFmpCapsule(CapsuleHeader
);
1162 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
1164 if (FmpCapsuleHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
1165 return EFI_INVALID_PARAMETER
;
1167 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
1169 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
1172 // capsule in which driver count and payload count are both zero is not processed.
1179 // 1. Try to load & start all the drivers within capsule
1181 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
1182 if ((FmpCapsuleHeader
->PayloadItemCount
== 0) &&
1183 (Index
== (UINTN
)FmpCapsuleHeader
->EmbeddedDriverCount
- 1)) {
1185 // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
1187 DriverLen
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
- (UINTN
)ItemOffsetList
[Index
];
1189 DriverLen
= (UINTN
)ItemOffsetList
[Index
+ 1] - (UINTN
)ItemOffsetList
[Index
];
1192 Status
= StartFmpImage (
1193 (UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
],
1196 if (EFI_ERROR(Status
)) {
1197 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
1203 // 2. Route payload to right FMP instance
1205 DEBUG((DEBUG_INFO
, "FmpCapsule: route payload to right FMP instance ...\n"));
1210 // Check all the payload entry in capsule payload list
1212 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
1213 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
1215 UpdateHardwareInstance
= 0;
1216 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
1217 UpdateHardwareInstance
= ImageHeader
->UpdateHardwareInstance
;
1220 Status
= GetFmpHandleBufferByType (
1221 &ImageHeader
->UpdateImageTypeId
,
1222 UpdateHardwareInstance
,
1225 &ResetRequiredBuffer
1227 if (EFI_ERROR(Status
) ||
1228 (HandleBuffer
== NULL
) ||
1229 (ResetRequiredBuffer
== NULL
)) {
1231 RecordFmpCapsuleStatus (
1235 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1241 for (Index2
= 0; Index2
< NumberOfHandles
; Index2
++) {
1243 RecordFmpCapsuleStatus (
1244 HandleBuffer
[Index2
],
1247 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1253 Status
= SetFmpImageData (
1254 HandleBuffer
[Index2
],
1256 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
1258 if (Status
!= EFI_SUCCESS
) {
1261 if (ResetRequired
!= NULL
) {
1262 *ResetRequired
|= ResetRequiredBuffer
[Index2
];
1266 RecordFmpCapsuleStatus (
1267 HandleBuffer
[Index2
],
1270 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1274 if (HandleBuffer
!= NULL
) {
1275 FreePool(HandleBuffer
);
1277 if (ResetRequiredBuffer
!= NULL
) {
1278 FreePool(ResetRequiredBuffer
);
1283 return EFI_NOT_READY
;
1287 // always return SUCCESS to indicate this capsule is processed.
1288 // The status of SetImage is recorded in capsule result variable.
1294 Return if there is a FMP header below capsule header.
1296 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1298 @retval TRUE There is a FMP header below capsule header.
1299 @retval FALSE There is not a FMP header below capsule header
1302 IsNestedFmpCapsule (
1303 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1307 EFI_SYSTEM_RESOURCE_ENTRY
*EsrtEntry
;
1309 BOOLEAN EsrtGuidFound
;
1310 EFI_CAPSULE_HEADER
*NestedCapsuleHeader
;
1311 UINTN NestedCapsuleSize
;
1312 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
1313 EFI_SYSTEM_RESOURCE_ENTRY Entry
;
1315 EsrtGuidFound
= FALSE
;
1316 if (mIsVirtualAddrConverted
) {
1317 if(mEsrtTable
!= NULL
) {
1318 EsrtEntry
= (EFI_SYSTEM_RESOURCE_ENTRY
*)(mEsrtTable
+ 1);
1319 for (Index
= 0; Index
< mEsrtTable
->FwResourceCount
; Index
++, EsrtEntry
++) {
1320 if (CompareGuid(&EsrtEntry
->FwClass
, &CapsuleHeader
->CapsuleGuid
)) {
1321 EsrtGuidFound
= TRUE
;
1328 // Check ESRT protocol
1330 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
1331 if (!EFI_ERROR(Status
)) {
1332 Status
= EsrtProtocol
->GetEsrtEntry(&CapsuleHeader
->CapsuleGuid
, &Entry
);
1333 if (!EFI_ERROR(Status
)) {
1334 EsrtGuidFound
= TRUE
;
1339 // Check Firmware Management Protocols
1341 if (!EsrtGuidFound
) {
1342 Status
= GetFmpHandleBufferByType (
1343 &CapsuleHeader
->CapsuleGuid
,
1349 if (!EFI_ERROR(Status
)) {
1350 EsrtGuidFound
= TRUE
;
1354 if (!EsrtGuidFound
) {
1359 // Check nested capsule header
1360 // FMP GUID after ESRT one
1362 NestedCapsuleHeader
= (EFI_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
1363 NestedCapsuleSize
= (UINTN
)CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
- (UINTN
)NestedCapsuleHeader
;
1364 if (NestedCapsuleSize
< sizeof(EFI_CAPSULE_HEADER
)) {
1367 if (!IsValidCapsuleHeader(NestedCapsuleHeader
, NestedCapsuleSize
)) {
1370 if (!IsFmpCapsuleGuid(&NestedCapsuleHeader
->CapsuleGuid
)) {
1373 DEBUG ((DEBUG_INFO
, "IsNestedFmpCapsule\n"));
1378 Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
1380 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1382 @retval TRUE It is a system FMP.
1383 @retval FALSE It is a device FMP.
1387 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1390 if (IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
1393 if (IsNestedFmpCapsule(CapsuleHeader
)) {
1400 Those capsules supported by the firmwares.
1402 Caution: This function may receive untrusted input.
1404 @param[in] CapsuleHeader Points to a capsule header.
1406 @retval EFI_SUCESS Input capsule is supported by firmware.
1407 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
1408 @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
1412 SupportCapsuleImage (
1413 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1417 // check Display Capsule Guid
1419 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1423 if (IsFmpCapsule(CapsuleHeader
)) {
1425 // Check layout of FMP capsule
1427 return ValidateFmpCapsule(CapsuleHeader
, NULL
);
1429 DEBUG((DEBUG_ERROR
, "Unknown Capsule Guid - %g\n", &CapsuleHeader
->CapsuleGuid
));
1430 return EFI_UNSUPPORTED
;
1434 The firmware implements to process the capsule image.
1436 Caution: This function may receive untrusted input.
1438 @param[in] CapsuleHeader Points to a capsule header.
1439 @param[out] ResetRequired Indicates whether reset is required or not.
1441 @retval EFI_SUCESS Process Capsule Image successfully.
1442 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1443 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1444 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1448 ProcessThisCapsuleImage (
1449 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
1450 OUT BOOLEAN
*ResetRequired OPTIONAL
1455 if (SupportCapsuleImage (CapsuleHeader
) != EFI_SUCCESS
) {
1456 RecordCapsuleStatusVariable(CapsuleHeader
, EFI_UNSUPPORTED
);
1457 return EFI_UNSUPPORTED
;
1461 // Display image in firmware update display capsule
1463 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1464 DEBUG((DEBUG_INFO
, "ProcessCapsuleImage for WindowsUxCapsule ...\n"));
1465 Status
= DisplayCapsuleImage(CapsuleHeader
);
1466 RecordCapsuleStatusVariable(CapsuleHeader
, Status
);
1471 // Check FMP capsule layout
1473 if (IsFmpCapsule (CapsuleHeader
)) {
1474 DEBUG((DEBUG_INFO
, "ProcessCapsuleImage for FmpCapsule ...\n"));
1475 DEBUG((DEBUG_INFO
, "ValidateFmpCapsule ...\n"));
1476 Status
= ValidateFmpCapsule(CapsuleHeader
, NULL
);
1477 DEBUG((DEBUG_INFO
, "ValidateFmpCapsule - %r\n", Status
));
1478 if (EFI_ERROR(Status
)) {
1479 RecordCapsuleStatusVariable(CapsuleHeader
, Status
);
1484 // Process EFI FMP Capsule
1486 DEBUG((DEBUG_INFO
, "ProcessFmpCapsuleImage ...\n"));
1487 Status
= ProcessFmpCapsuleImage(CapsuleHeader
, ResetRequired
);
1488 DEBUG((DEBUG_INFO
, "ProcessFmpCapsuleImage - %r\n", Status
));
1493 return EFI_UNSUPPORTED
;
1497 The firmware implements to process the capsule image.
1499 Caution: This function may receive untrusted input.
1501 @param[in] CapsuleHeader Points to a capsule header.
1503 @retval EFI_SUCESS Process Capsule Image successfully.
1504 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1505 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1506 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1510 ProcessCapsuleImage (
1511 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1514 return ProcessThisCapsuleImage (CapsuleHeader
, NULL
);
1518 Callback function executed when the EndOfDxe event group is signaled.
1520 @param[in] Event Event whose notification function is being invoked.
1521 @param[in] Context The pointer to the notification function's context, which
1522 is implementation-dependent.
1526 DxeCapsuleLibEndOfDxe (
1531 mDxeCapsuleLibEndOfDxe
= TRUE
;
1535 The constructor function.
1537 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1538 @param[in] SystemTable A pointer to the EFI System Table.
1540 @retval EFI_SUCCESS The constructor successfully .
1544 DxeCapsuleLibConstructor (
1545 IN EFI_HANDLE ImageHandle
,
1546 IN EFI_SYSTEM_TABLE
*SystemTable
1551 Status
= gBS
->CreateEventEx (
1554 DxeCapsuleLibEndOfDxe
,
1556 &gEfiEndOfDxeEventGroupGuid
,
1557 &mDxeCapsuleLibEndOfDxeEvent
1559 ASSERT_EFI_ERROR (Status
);
1561 InitCapsuleVariable();
1567 The destructor function closes the End of DXE event.
1569 @param ImageHandle The firmware allocated handle for the EFI image.
1570 @param SystemTable A pointer to the EFI System Table.
1572 @retval EFI_SUCCESS The destructor completed successfully.
1576 DxeCapsuleLibDestructor (
1577 IN EFI_HANDLE ImageHandle
,
1578 IN EFI_SYSTEM_TABLE
*SystemTable
1584 // Close the End of DXE event.
1586 Status
= gBS
->CloseEvent (mDxeCapsuleLibEndOfDxeEvent
);
1587 ASSERT_EFI_ERROR (Status
);