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 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
84 @retval EFI_SUCCESS The capsule status variable is recorded.
85 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
88 RecordFmpCapsuleStatusVariable (
89 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
90 IN EFI_STATUS CapsuleStatus
,
91 IN UINTN PayloadIndex
,
92 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
,
93 IN EFI_DEVICE_PATH_PROTOCOL
*FmpDevicePath OPTIONAL
97 Function indicate the current completion progress of the firmware
98 update. Platform may override with own specific progress function.
100 @param[in] Completion A value between 1 and 100 indicating the current
101 completion progress of the firmware update
103 @retval EFI_SUCESS The capsule update progress was updated.
104 @retval EFI_INVALID_PARAMETER Completion is greater than 100%.
108 UpdateImageProgress (
113 Return if this CapsuleGuid is a FMP capsule GUID or not.
115 @param[in] CapsuleGuid A pointer to EFI_GUID
117 @retval TRUE It is a FMP capsule GUID.
118 @retval FALSE It is not a FMP capsule GUID.
122 IN EFI_GUID
*CapsuleGuid
125 if (CompareGuid(&gEfiFmpCapsuleGuid
, CapsuleGuid
)) {
133 Validate if it is valid capsule header
135 Caution: This function may receive untrusted input.
137 This function assumes the caller provided correct CapsuleHeader pointer
140 This function validates the fields in EFI_CAPSULE_HEADER.
142 @param[in] CapsuleHeader Points to a capsule header.
143 @param[in] CapsuleSize Size of the whole capsule image.
147 IsValidCapsuleHeader (
148 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
149 IN UINT64 CapsuleSize
152 if (CapsuleHeader
->CapsuleImageSize
!= CapsuleSize
) {
155 if (CapsuleHeader
->HeaderSize
>= CapsuleHeader
->CapsuleImageSize
) {
162 Validate Fmp capsules layout.
164 Caution: This function may receive untrusted input.
166 This function assumes the caller validated the capsule by using
167 IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.
168 The capsule buffer size is CapsuleHeader->CapsuleImageSize.
170 This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
171 and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
173 This function need support nested FMP capsule.
175 @param[in] CapsuleHeader Points to a capsule header.
176 @param[out] EmbeddedDriverCount The EmbeddedDriverCount in the FMP capsule.
178 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
179 @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.
183 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
184 OUT UINT16
*EmbeddedDriverCount OPTIONAL
187 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
189 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
191 UINT64
*ItemOffsetList
;
194 UINTN FmpCapsuleSize
;
195 UINTN FmpCapsuleHeaderSize
;
197 UINTN FmpImageHeaderSize
;
199 if (!IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
200 return ValidateFmpCapsule ((EFI_CAPSULE_HEADER
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
), EmbeddedDriverCount
);
203 if (CapsuleHeader
->HeaderSize
>= CapsuleHeader
->CapsuleImageSize
) {
204 DEBUG((DEBUG_ERROR
, "HeaderSize(0x%x) >= CapsuleImageSize(0x%x)\n", CapsuleHeader
->HeaderSize
, CapsuleHeader
->CapsuleImageSize
));
205 return EFI_INVALID_PARAMETER
;
208 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
209 EndOfCapsule
= (UINT8
*) CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
;
210 FmpCapsuleSize
= (UINTN
)EndOfCapsule
- (UINTN
)FmpCapsuleHeader
;
212 if (FmpCapsuleSize
< sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
)) {
213 DEBUG((DEBUG_ERROR
, "FmpCapsuleSize(0x%x) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\n", FmpCapsuleSize
));
214 return EFI_INVALID_PARAMETER
;
217 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
218 if (FmpCapsuleHeader
->Version
!= EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
219 DEBUG((DEBUG_ERROR
, "FmpCapsuleHeader->Version(0x%x) != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION\n", FmpCapsuleHeader
->Version
));
220 return EFI_INVALID_PARAMETER
;
222 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
225 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
227 if ((FmpCapsuleSize
- sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
))/sizeof(UINT64
) < ItemNum
) {
228 DEBUG((DEBUG_ERROR
, "ItemNum(0x%x) too big\n", ItemNum
));
229 return EFI_INVALID_PARAMETER
;
231 FmpCapsuleHeaderSize
= sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
) + sizeof(UINT64
)*ItemNum
;
233 // Check ItemOffsetList
234 for (Index
= 0; Index
< ItemNum
; Index
++) {
235 if (ItemOffsetList
[Index
] >= FmpCapsuleSize
) {
236 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) >= FmpCapsuleSize(0x%x)\n", Index
, ItemOffsetList
[Index
], FmpCapsuleSize
));
237 return EFI_INVALID_PARAMETER
;
239 if (ItemOffsetList
[Index
] < FmpCapsuleHeaderSize
) {
240 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) < FmpCapsuleHeaderSize(0x%x)\n", Index
, ItemOffsetList
[Index
], FmpCapsuleHeaderSize
));
241 return EFI_INVALID_PARAMETER
;
244 // All the address in ItemOffsetList must be stored in ascending order
247 if (ItemOffsetList
[Index
] <= ItemOffsetList
[Index
- 1]) {
248 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) < ItemOffsetList[%d](0x%x)\n", Index
, ItemOffsetList
[Index
], Index
- 1, ItemOffsetList
[Index
- 1]));
249 return EFI_INVALID_PARAMETER
;
254 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
255 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
256 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
257 if (Index
== ItemNum
- 1) {
258 EndOfPayload
= (UINT8
*)((UINTN
)EndOfCapsule
- (UINTN
)FmpCapsuleHeader
);
260 EndOfPayload
= (UINT8
*)(UINTN
)ItemOffsetList
[Index
+1];
262 FmpImageSize
= (UINTN
)EndOfPayload
- ItemOffsetList
[Index
];
264 FmpImageHeaderSize
= sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
);
265 if ((ImageHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) ||
266 (ImageHeader
->Version
< 1)) {
267 DEBUG((DEBUG_ERROR
, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader
->Version
));
268 return EFI_INVALID_PARAMETER
;
270 if (ImageHeader
->Version
< EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
271 FmpImageHeaderSize
= OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
273 if (FmpImageSize
< FmpImageHeaderSize
) {
274 DEBUG((DEBUG_ERROR
, "FmpImageSize(0x%lx) < FmpImageHeaderSize(0x%x)\n", FmpImageSize
, FmpImageHeaderSize
));
275 return EFI_INVALID_PARAMETER
;
279 if (FmpImageSize
!= (UINT64
)FmpImageHeaderSize
+ (UINT64
)ImageHeader
->UpdateImageSize
+ (UINT64
)ImageHeader
->UpdateVendorCodeSize
) {
280 DEBUG((DEBUG_ERROR
, "FmpImageSize(0x%lx) mismatch, UpdateImageSize(0x%x) UpdateVendorCodeSize(0x%x)\n", FmpImageSize
, ImageHeader
->UpdateImageSize
, ImageHeader
->UpdateVendorCodeSize
));
281 return EFI_INVALID_PARAMETER
;
287 // No driver & payload element in FMP
289 EndOfPayload
= (UINT8
*)(FmpCapsuleHeader
+ 1);
290 if (EndOfPayload
!= EndOfCapsule
) {
291 DEBUG((DEBUG_ERROR
, "EndOfPayload(0x%x) mismatch, EndOfCapsule(0x%x)\n", EndOfPayload
, EndOfCapsule
));
292 return EFI_INVALID_PARAMETER
;
294 return EFI_UNSUPPORTED
;
297 if (EmbeddedDriverCount
!= NULL
) {
298 *EmbeddedDriverCount
= FmpCapsuleHeader
->EmbeddedDriverCount
;
305 Those capsules supported by the firmwares.
307 Caution: This function may receive untrusted input.
309 @param[in] CapsuleHeader Points to a capsule header.
311 @retval EFI_SUCESS Input capsule is supported by firmware.
312 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
315 DisplayCapsuleImage (
316 IN EFI_CAPSULE_HEADER
*CapsuleHeader
319 DISPLAY_DISPLAY_PAYLOAD
*ImagePayload
;
322 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
326 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
329 // UX capsule doesn't have extended header entries.
331 if (CapsuleHeader
->HeaderSize
!= sizeof (EFI_CAPSULE_HEADER
)) {
332 return EFI_UNSUPPORTED
;
334 ImagePayload
= (DISPLAY_DISPLAY_PAYLOAD
*)((UINTN
) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
336 // (CapsuleImageSize > HeaderSize) is guaranteed by IsValidCapsuleHeader().
338 PayloadSize
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
;
341 // Make sure the image payload at least contain the DISPLAY_DISPLAY_PAYLOAD header.
342 // Further size check is performed by the logic translating BMP to GOP BLT.
344 if (PayloadSize
<= sizeof (DISPLAY_DISPLAY_PAYLOAD
)) {
345 return EFI_INVALID_PARAMETER
;
348 if (ImagePayload
->Version
!= 1) {
349 return EFI_UNSUPPORTED
;
351 if (CalculateCheckSum8((UINT8
*)CapsuleHeader
, CapsuleHeader
->CapsuleImageSize
) != 0) {
352 return EFI_UNSUPPORTED
;
355 // Only Support Bitmap by now
357 if (ImagePayload
->ImageType
!= 0) {
358 return EFI_UNSUPPORTED
;
364 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**)&GraphicsOutput
);
365 if (EFI_ERROR (Status
)) {
366 Status
= gBS
->LocateProtocol(&gEfiGraphicsOutputProtocolGuid
, NULL
, (VOID
**)&GraphicsOutput
);
367 if (EFI_ERROR(Status
)) {
368 return EFI_UNSUPPORTED
;
372 if (GraphicsOutput
->Mode
->Mode
!= ImagePayload
->Mode
) {
373 return EFI_UNSUPPORTED
;
379 Status
= TranslateBmpToGopBlt (
381 PayloadSize
- sizeof(DISPLAY_DISPLAY_PAYLOAD
),
388 if (EFI_ERROR (Status
)) {
392 Status
= GraphicsOutput
->Blt (
398 (UINTN
) ImagePayload
->OffsetX
,
399 (UINTN
) ImagePayload
->OffsetY
,
402 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
411 Dump FMP information.
413 @param[in] ImageInfoSize The size of ImageInfo, in bytes.
414 @param[in] ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
415 @param[in] DescriptorVersion The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
416 @param[in] DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
417 @param[in] DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
418 @param[in] PackageVersion The version of package.
419 @param[in] PackageVersionName The version name of package.
423 IN UINTN ImageInfoSize
,
424 IN EFI_FIRMWARE_IMAGE_DESCRIPTOR
*ImageInfo
,
425 IN UINT32 DescriptorVersion
,
426 IN UINT8 DescriptorCount
,
427 IN UINTN DescriptorSize
,
428 IN UINT32 PackageVersion
,
429 IN CHAR16
*PackageVersionName
432 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*CurrentImageInfo
;
435 DEBUG((DEBUG_VERBOSE
, " DescriptorVersion - 0x%x\n", DescriptorVersion
));
436 DEBUG((DEBUG_VERBOSE
, " DescriptorCount - 0x%x\n", DescriptorCount
));
437 DEBUG((DEBUG_VERBOSE
, " DescriptorSize - 0x%x\n", DescriptorSize
));
438 DEBUG((DEBUG_VERBOSE
, " PackageVersion - 0x%x\n", PackageVersion
));
439 DEBUG((DEBUG_VERBOSE
, " PackageVersionName - %s\n\n", PackageVersionName
));
440 CurrentImageInfo
= ImageInfo
;
441 for (Index
= 0; Index
< DescriptorCount
; Index
++) {
442 DEBUG((DEBUG_VERBOSE
, " ImageDescriptor (%d)\n", Index
));
443 DEBUG((DEBUG_VERBOSE
, " ImageIndex - 0x%x\n", CurrentImageInfo
->ImageIndex
));
444 DEBUG((DEBUG_VERBOSE
, " ImageTypeId - %g\n", &CurrentImageInfo
->ImageTypeId
));
445 DEBUG((DEBUG_VERBOSE
, " ImageId - 0x%lx\n", CurrentImageInfo
->ImageId
));
446 DEBUG((DEBUG_VERBOSE
, " ImageIdName - %s\n", CurrentImageInfo
->ImageIdName
));
447 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", CurrentImageInfo
->Version
));
448 DEBUG((DEBUG_VERBOSE
, " VersionName - %s\n", CurrentImageInfo
->VersionName
));
449 DEBUG((DEBUG_VERBOSE
, " Size - 0x%x\n", CurrentImageInfo
->Size
));
450 DEBUG((DEBUG_VERBOSE
, " AttributesSupported - 0x%lx\n", CurrentImageInfo
->AttributesSupported
));
451 DEBUG((DEBUG_VERBOSE
, " AttributesSetting - 0x%lx\n", CurrentImageInfo
->AttributesSetting
));
452 DEBUG((DEBUG_VERBOSE
, " Compatibilities - 0x%lx\n", CurrentImageInfo
->Compatibilities
));
453 if (DescriptorVersion
> 1) {
454 DEBUG((DEBUG_VERBOSE
, " LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo
->LowestSupportedImageVersion
));
455 if (DescriptorVersion
> 2) {
456 DEBUG((DEBUG_VERBOSE
, " LastAttemptVersion - 0x%x\n", CurrentImageInfo
->LastAttemptVersion
));
457 DEBUG((DEBUG_VERBOSE
, " LastAttemptStatus - 0x%x\n", CurrentImageInfo
->LastAttemptStatus
));
458 DEBUG((DEBUG_VERBOSE
, " HardwareInstance - 0x%lx\n", CurrentImageInfo
->HardwareInstance
));
462 // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
464 CurrentImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)CurrentImageInfo
+ DescriptorSize
);
469 Dump a non-nested FMP capsule.
471 @param[in] CapsuleHeader A pointer to CapsuleHeader
475 IN EFI_CAPSULE_HEADER
*CapsuleHeader
478 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
479 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
481 UINT64
*ItemOffsetList
;
483 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
485 DEBUG((DEBUG_VERBOSE
, "FmpCapsule:\n"));
486 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", FmpCapsuleHeader
->Version
));
487 DEBUG((DEBUG_VERBOSE
, " EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader
->EmbeddedDriverCount
));
488 DEBUG((DEBUG_VERBOSE
, " PayloadItemCount - 0x%x\n", FmpCapsuleHeader
->PayloadItemCount
));
490 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
491 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
492 DEBUG((DEBUG_VERBOSE
, " ItemOffsetList[%d] - 0x%lx\n", Index
, ItemOffsetList
[Index
]));
494 for (; Index
< (UINT32
)FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
; Index
++) {
495 DEBUG((DEBUG_VERBOSE
, " ItemOffsetList[%d] - 0x%lx\n", Index
, ItemOffsetList
[Index
]));
496 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
498 DEBUG((DEBUG_VERBOSE
, " ImageHeader:\n"));
499 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", ImageHeader
->Version
));
500 DEBUG((DEBUG_VERBOSE
, " UpdateImageTypeId - %g\n", &ImageHeader
->UpdateImageTypeId
));
501 DEBUG((DEBUG_VERBOSE
, " UpdateImageIndex - 0x%x\n", ImageHeader
->UpdateImageIndex
));
502 DEBUG((DEBUG_VERBOSE
, " UpdateImageSize - 0x%x\n", ImageHeader
->UpdateImageSize
));
503 DEBUG((DEBUG_VERBOSE
, " UpdateVendorCodeSize - 0x%x\n", ImageHeader
->UpdateVendorCodeSize
));
504 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
505 DEBUG((DEBUG_VERBOSE
, " UpdateHardwareInstance - 0x%lx\n", ImageHeader
->UpdateHardwareInstance
));
511 Dump all FMP information.
519 EFI_HANDLE
*HandleBuffer
;
520 UINTN NumberOfHandles
;
521 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
524 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
525 UINT32 FmpImageInfoDescriptorVer
;
526 UINT8 FmpImageInfoCount
;
527 UINTN DescriptorSize
;
528 UINT32 PackageVersion
;
529 CHAR16
*PackageVersionName
;
531 Status
= gBS
->LocateHandleBuffer (
533 &gEfiFirmwareManagementProtocolGuid
,
538 if (EFI_ERROR(Status
)) {
542 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
543 Status
= gBS
->HandleProtocol(
545 &gEfiFirmwareManagementProtocolGuid
,
548 if (EFI_ERROR(Status
)) {
553 Status
= Fmp
->GetImageInfo (
563 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
567 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
568 if (FmpImageInfoBuf
== NULL
) {
572 PackageVersionName
= NULL
;
573 Status
= Fmp
->GetImageInfo (
575 &ImageInfoSize
, // ImageInfoSize
576 FmpImageInfoBuf
, // ImageInfo
577 &FmpImageInfoDescriptorVer
, // DescriptorVersion
578 &FmpImageInfoCount
, // DescriptorCount
579 &DescriptorSize
, // DescriptorSize
580 &PackageVersion
, // PackageVersion
581 &PackageVersionName
// PackageVersionName
583 if (EFI_ERROR(Status
)) {
584 FreePool(FmpImageInfoBuf
);
588 DEBUG((DEBUG_INFO
, "FMP (%d) ImageInfo:\n", Index
));
590 ImageInfoSize
, // ImageInfoSize
591 FmpImageInfoBuf
, // ImageInfo
592 FmpImageInfoDescriptorVer
, // DescriptorVersion
593 FmpImageInfoCount
, // DescriptorCount
594 DescriptorSize
, // DescriptorSize
595 PackageVersion
, // PackageVersion
596 PackageVersionName
// PackageVersionName
599 if (PackageVersionName
!= NULL
) {
600 FreePool(PackageVersionName
);
603 FreePool(FmpImageInfoBuf
);
606 FreePool (HandleBuffer
);
612 Get FMP handle by ImageTypeId and HardwareInstance.
614 @param[in] UpdateImageTypeId Used to identify device firmware targeted by this update.
615 @param[in] UpdateHardwareInstance The HardwareInstance to target with this update.
616 @param[out] NoHandles The number of handles returned in HandleBuf.
617 @param[out] HandleBuf A pointer to the buffer to return the requested array of handles.
618 @param[out] ResetRequiredBuf A pointer to the buffer to return reset required flag for
619 the requested array of handles.
621 @retval EFI_SUCCESS The array of handles and their reset required flag were returned in
622 HandleBuf and ResetRequiredBuf, and the number of handles in HandleBuf
623 was returned in NoHandles.
624 @retval EFI_NOT_FOUND No handles match the search.
625 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
628 GetFmpHandleBufferByType (
629 IN EFI_GUID
*UpdateImageTypeId
,
630 IN UINT64 UpdateHardwareInstance
,
631 OUT UINTN
*NoHandles
, OPTIONAL
632 OUT EFI_HANDLE
**HandleBuf
, OPTIONAL
633 OUT BOOLEAN
**ResetRequiredBuf OPTIONAL
637 EFI_HANDLE
*HandleBuffer
;
638 UINTN NumberOfHandles
;
639 EFI_HANDLE
*MatchedHandleBuffer
;
640 BOOLEAN
*MatchedResetRequiredBuffer
;
641 UINTN MatchedNumberOfHandles
;
642 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
645 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
646 UINT32 FmpImageInfoDescriptorVer
;
647 UINT8 FmpImageInfoCount
;
648 UINTN DescriptorSize
;
649 UINT32 PackageVersion
;
650 CHAR16
*PackageVersionName
;
652 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*TempFmpImageInfo
;
654 if (NoHandles
!= NULL
) {
657 if (HandleBuf
!= NULL
) {
660 if (ResetRequiredBuf
!= NULL
) {
661 *ResetRequiredBuf
= NULL
;
664 Status
= gBS
->LocateHandleBuffer (
666 &gEfiFirmwareManagementProtocolGuid
,
671 if (EFI_ERROR(Status
)) {
675 MatchedNumberOfHandles
= 0;
677 MatchedHandleBuffer
= NULL
;
678 if (HandleBuf
!= NULL
) {
679 MatchedHandleBuffer
= AllocateZeroPool (sizeof(EFI_HANDLE
) * NumberOfHandles
);
680 if (MatchedHandleBuffer
== NULL
) {
681 FreePool (HandleBuffer
);
682 return EFI_OUT_OF_RESOURCES
;
686 MatchedResetRequiredBuffer
= NULL
;
687 if (ResetRequiredBuf
!= NULL
) {
688 MatchedResetRequiredBuffer
= AllocateZeroPool (sizeof(BOOLEAN
) * NumberOfHandles
);
689 if (MatchedResetRequiredBuffer
== NULL
) {
690 if (MatchedHandleBuffer
!= NULL
) {
691 FreePool (MatchedHandleBuffer
);
693 FreePool (HandleBuffer
);
694 return EFI_OUT_OF_RESOURCES
;
698 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
699 Status
= gBS
->HandleProtocol(
701 &gEfiFirmwareManagementProtocolGuid
,
704 if (EFI_ERROR(Status
)) {
709 Status
= Fmp
->GetImageInfo (
719 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
723 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
724 if (FmpImageInfoBuf
== NULL
) {
728 PackageVersionName
= NULL
;
729 Status
= Fmp
->GetImageInfo (
731 &ImageInfoSize
, // ImageInfoSize
732 FmpImageInfoBuf
, // ImageInfo
733 &FmpImageInfoDescriptorVer
, // DescriptorVersion
734 &FmpImageInfoCount
, // DescriptorCount
735 &DescriptorSize
, // DescriptorSize
736 &PackageVersion
, // PackageVersion
737 &PackageVersionName
// PackageVersionName
739 if (EFI_ERROR(Status
)) {
740 FreePool(FmpImageInfoBuf
);
744 if (PackageVersionName
!= NULL
) {
745 FreePool(PackageVersionName
);
748 TempFmpImageInfo
= FmpImageInfoBuf
;
749 for (Index2
= 0; Index2
< FmpImageInfoCount
; Index2
++) {
751 // Check if this FMP instance matches
753 if (CompareGuid(UpdateImageTypeId
, &TempFmpImageInfo
->ImageTypeId
)) {
754 if ((UpdateHardwareInstance
== 0) ||
755 ((FmpImageInfoDescriptorVer
>= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
) &&
756 (UpdateHardwareInstance
== TempFmpImageInfo
->HardwareInstance
))) {
757 if (MatchedHandleBuffer
!= NULL
) {
758 MatchedHandleBuffer
[MatchedNumberOfHandles
] = HandleBuffer
[Index
];
760 if (MatchedResetRequiredBuffer
!= NULL
) {
761 MatchedResetRequiredBuffer
[MatchedNumberOfHandles
] = (((TempFmpImageInfo
->AttributesSupported
&
762 IMAGE_ATTRIBUTE_RESET_REQUIRED
) != 0) &&
763 ((TempFmpImageInfo
->AttributesSetting
&
764 IMAGE_ATTRIBUTE_RESET_REQUIRED
) != 0));
766 MatchedNumberOfHandles
++;
770 TempFmpImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)TempFmpImageInfo
+ DescriptorSize
);
772 FreePool(FmpImageInfoBuf
);
775 FreePool (HandleBuffer
);
777 if (MatchedNumberOfHandles
== 0) {
778 return EFI_NOT_FOUND
;
781 if (NoHandles
!= NULL
) {
782 *NoHandles
= MatchedNumberOfHandles
;
784 if (HandleBuf
!= NULL
) {
785 *HandleBuf
= MatchedHandleBuffer
;
787 if (ResetRequiredBuf
!= NULL
) {
788 *ResetRequiredBuf
= MatchedResetRequiredBuffer
;
795 Return FmpImageInfoDescriptorVer by an FMP handle.
797 @param[in] Handle A FMP handle.
799 @return FmpImageInfoDescriptorVer associated with the FMP.
802 GetFmpImageInfoDescriptorVer (
807 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
809 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
810 UINT32 FmpImageInfoDescriptorVer
;
811 UINT8 FmpImageInfoCount
;
812 UINTN DescriptorSize
;
813 UINT32 PackageVersion
;
814 CHAR16
*PackageVersionName
;
816 Status
= gBS
->HandleProtocol(
818 &gEfiFirmwareManagementProtocolGuid
,
821 if (EFI_ERROR(Status
)) {
826 Status
= Fmp
->GetImageInfo (
836 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
840 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
841 if (FmpImageInfoBuf
== NULL
) {
845 PackageVersionName
= NULL
;
846 Status
= Fmp
->GetImageInfo (
848 &ImageInfoSize
, // ImageInfoSize
849 FmpImageInfoBuf
, // ImageInfo
850 &FmpImageInfoDescriptorVer
, // DescriptorVersion
851 &FmpImageInfoCount
, // DescriptorCount
852 &DescriptorSize
, // DescriptorSize
853 &PackageVersion
, // PackageVersion
854 &PackageVersionName
// PackageVersionName
856 if (EFI_ERROR(Status
)) {
857 FreePool(FmpImageInfoBuf
);
860 return FmpImageInfoDescriptorVer
;
866 @param[in] Handle A FMP handle.
867 @param[in] ImageHeader The payload image header.
868 @param[in] PayloadIndex The index of the payload.
870 @return The status of FMP->SetImage.
874 IN EFI_HANDLE Handle
,
875 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
,
876 IN UINTN PayloadIndex
880 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
884 EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS ProgressCallback
;
886 Status
= gBS
->HandleProtocol(
888 &gEfiFirmwareManagementProtocolGuid
,
891 if (EFI_ERROR(Status
)) {
896 // Lookup Firmware Management Progress Protocol before SetImage() is called
897 // This is an optional protocol that may not be present on Handle.
899 Status
= gBS
->HandleProtocol (
901 &gEdkiiFirmwareManagementProgressProtocolGuid
,
902 (VOID
**)&mFmpProgress
904 if (EFI_ERROR (Status
)) {
908 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
909 Image
= (UINT8
*)(ImageHeader
+ 1);
912 // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1,
913 // Header should exclude UpdateHardwareInstance field
915 Image
= (UINT8
*)ImageHeader
+ OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
918 if (ImageHeader
->UpdateVendorCodeSize
== 0) {
921 VendorCode
= Image
+ ImageHeader
->UpdateImageSize
;
924 DEBUG((DEBUG_INFO
, "Fmp->SetImage ...\n"));
925 DEBUG((DEBUG_INFO
, "ImageTypeId - %g, ", &ImageHeader
->UpdateImageTypeId
));
926 DEBUG((DEBUG_INFO
, "PayloadIndex - 0x%x, ", PayloadIndex
));
927 DEBUG((DEBUG_INFO
, "ImageIndex - 0x%x ", ImageHeader
->UpdateImageIndex
));
928 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
929 DEBUG((DEBUG_INFO
, "(UpdateHardwareInstance - 0x%x)", ImageHeader
->UpdateHardwareInstance
));
931 DEBUG((DEBUG_INFO
, "\n"));
934 // Before calling SetImage(), reset the progress bar to 0%
936 ProgressCallback
= UpdateImageProgress
;
937 Status
= UpdateImageProgress (0);
938 if (EFI_ERROR (Status
)) {
939 ProgressCallback
= NULL
;
942 Status
= Fmp
->SetImage(
944 ImageHeader
->UpdateImageIndex
, // ImageIndex
946 ImageHeader
->UpdateImageSize
, // ImageSize
947 VendorCode
, // VendorCode
948 ProgressCallback
, // Progress
949 &AbortReason
// AbortReason
952 // Set the progress bar to 100% after returning from SetImage()
954 if (ProgressCallback
!= NULL
) {
955 UpdateImageProgress (100);
958 DEBUG((DEBUG_INFO
, "Fmp->SetImage - %r\n", Status
));
959 if (AbortReason
!= NULL
) {
960 DEBUG ((DEBUG_ERROR
, "%s\n", AbortReason
));
961 FreePool(AbortReason
);
965 // Clear mFmpProgress after SetImage() returns
973 Start a UEFI image in the FMP payload.
975 @param[in] ImageBuffer A pointer to the memory location containing a copy of the image to be loaded..
976 @param[in] ImageSize The size in bytes of ImageBuffer.
978 @return The status of gBS->LoadImage and gBS->StartImage.
982 IN VOID
*ImageBuffer
,
986 MEMMAP_DEVICE_PATH MemMapNode
;
988 EFI_HANDLE ImageHandle
;
989 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
992 SetDevicePathNodeLength (&MemMapNode
.Header
, sizeof (MemMapNode
));
993 MemMapNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
994 MemMapNode
.Header
.SubType
= HW_MEMMAP_DP
;
995 MemMapNode
.MemoryType
= EfiBootServicesCode
;
996 MemMapNode
.StartingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)ImageBuffer
;
997 MemMapNode
.EndingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)((UINT8
*)ImageBuffer
+ ImageSize
- 1);
999 DriverDevicePath
= AppendDevicePathNode (NULL
, &MemMapNode
.Header
);
1000 if (DriverDevicePath
== NULL
) {
1001 return EFI_OUT_OF_RESOURCES
;
1004 DEBUG((DEBUG_INFO
, "FmpCapsule: LoadImage ...\n"));
1005 Status
= gBS
->LoadImage(
1013 DEBUG((DEBUG_INFO
, "FmpCapsule: LoadImage - %r\n", Status
));
1014 if (EFI_ERROR(Status
)) {
1015 FreePool(DriverDevicePath
);
1019 DEBUG((DEBUG_INFO
, "FmpCapsule: StartImage ...\n"));
1020 Status
= gBS
->StartImage(
1025 DEBUG((DEBUG_INFO
, "FmpCapsule: StartImage - %r\n", Status
));
1026 if (EFI_ERROR(Status
)) {
1027 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
1030 FreePool(DriverDevicePath
);
1035 Record FMP capsule status.
1037 @param[in] Handle A FMP handle.
1038 @param[in] CapsuleHeader The capsule image header
1039 @param[in] CapsuleStatus The capsule process stauts
1040 @param[in] PayloadIndex FMP payload index
1041 @param[in] ImageHeader FMP image header
1044 RecordFmpCapsuleStatus (
1045 IN EFI_HANDLE Handle
, OPTIONAL
1046 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
1047 IN EFI_STATUS CapsuleStatus
,
1048 IN UINTN PayloadIndex
,
1049 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
1053 EFI_DEVICE_PATH_PROTOCOL
*FmpDevicePath
;
1054 UINT32 FmpImageInfoDescriptorVer
;
1055 EFI_STATUS StatusEsrt
;
1056 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
1057 EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry
;
1059 FmpDevicePath
= NULL
;
1060 if (Handle
!= NULL
) {
1061 gBS
->HandleProtocol(
1063 &gEfiDevicePathProtocolGuid
,
1064 (VOID
**)&FmpDevicePath
1068 RecordFmpCapsuleStatusVariable (
1077 // Update corresponding ESRT entry LastAttemp Status
1079 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
1080 if (EFI_ERROR (Status
)) {
1084 if (Handle
== NULL
) {
1089 // Update EsrtEntry For V1, V2 FMP instance.
1090 // V3 FMP ESRT cache will be synced up through SyncEsrtFmp interface
1092 FmpImageInfoDescriptorVer
= GetFmpImageInfoDescriptorVer (Handle
);
1093 if (FmpImageInfoDescriptorVer
< EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
) {
1094 StatusEsrt
= EsrtProtocol
->GetEsrtEntry(&ImageHeader
->UpdateImageTypeId
, &EsrtEntry
);
1095 if (!EFI_ERROR(StatusEsrt
)){
1096 if (!EFI_ERROR(CapsuleStatus
)) {
1097 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_SUCCESS
;
1099 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL
;
1101 EsrtEntry
.LastAttemptVersion
= 0;
1102 EsrtProtocol
->UpdateEsrtEntry(&EsrtEntry
);
1108 Process Firmware management protocol data capsule.
1110 This function assumes the caller validated the capsule by using
1111 ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
1112 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
1113 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
1115 This function need support nested FMP capsule.
1117 @param[in] CapsuleHeader Points to a capsule header.
1118 @param[out] ResetRequired Indicates whether reset is required or not.
1120 @retval EFI_SUCESS Process Capsule Image successfully.
1121 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1122 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1123 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1124 @retval EFI_NOT_READY No FMP protocol to handle this FMP capsule.
1127 ProcessFmpCapsuleImage (
1128 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
1129 OUT BOOLEAN
*ResetRequired OPTIONAL
1133 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
1134 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
1135 UINT64
*ItemOffsetList
;
1138 EFI_HANDLE
*HandleBuffer
;
1139 BOOLEAN
*ResetRequiredBuffer
;
1140 UINTN NumberOfHandles
;
1142 UINT64 UpdateHardwareInstance
;
1147 if (!IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
1148 return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
), ResetRequired
);
1154 DumpFmpCapsule(CapsuleHeader
);
1156 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
1158 if (FmpCapsuleHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
1159 return EFI_INVALID_PARAMETER
;
1161 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
1163 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
1166 // capsule in which driver count and payload count are both zero is not processed.
1173 // 1. Try to load & start all the drivers within capsule
1175 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
1176 if ((FmpCapsuleHeader
->PayloadItemCount
== 0) &&
1177 (Index
== (UINTN
)FmpCapsuleHeader
->EmbeddedDriverCount
- 1)) {
1179 // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
1181 DriverLen
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
- (UINTN
)ItemOffsetList
[Index
];
1183 DriverLen
= (UINTN
)ItemOffsetList
[Index
+ 1] - (UINTN
)ItemOffsetList
[Index
];
1186 Status
= StartFmpImage (
1187 (UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
],
1190 if (EFI_ERROR(Status
)) {
1191 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
1197 // 2. Route payload to right FMP instance
1199 DEBUG((DEBUG_INFO
, "FmpCapsule: route payload to right FMP instance ...\n"));
1204 // Check all the payload entry in capsule payload list
1206 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
1207 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
1209 UpdateHardwareInstance
= 0;
1210 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
1211 UpdateHardwareInstance
= ImageHeader
->UpdateHardwareInstance
;
1214 Status
= GetFmpHandleBufferByType (
1215 &ImageHeader
->UpdateImageTypeId
,
1216 UpdateHardwareInstance
,
1219 &ResetRequiredBuffer
1221 if (EFI_ERROR(Status
) ||
1222 (HandleBuffer
== NULL
) ||
1223 (ResetRequiredBuffer
== NULL
)) {
1225 RecordFmpCapsuleStatus (
1229 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1235 for (Index2
= 0; Index2
< NumberOfHandles
; Index2
++) {
1237 RecordFmpCapsuleStatus (
1238 HandleBuffer
[Index2
],
1241 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1247 Status
= SetFmpImageData (
1248 HandleBuffer
[Index2
],
1250 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
1252 if (Status
!= EFI_SUCCESS
) {
1255 if (ResetRequired
!= NULL
) {
1256 *ResetRequired
|= ResetRequiredBuffer
[Index2
];
1260 RecordFmpCapsuleStatus (
1261 HandleBuffer
[Index2
],
1264 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1268 if (HandleBuffer
!= NULL
) {
1269 FreePool(HandleBuffer
);
1271 if (ResetRequiredBuffer
!= NULL
) {
1272 FreePool(ResetRequiredBuffer
);
1277 return EFI_NOT_READY
;
1281 // always return SUCCESS to indicate this capsule is processed.
1282 // The status of SetImage is recorded in capsule result variable.
1288 Return if there is a FMP header below capsule header.
1290 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1292 @retval TRUE There is a FMP header below capsule header.
1293 @retval FALSE There is not a FMP header below capsule header
1296 IsNestedFmpCapsule (
1297 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1301 EFI_SYSTEM_RESOURCE_ENTRY
*EsrtEntry
;
1303 BOOLEAN EsrtGuidFound
;
1304 EFI_CAPSULE_HEADER
*NestedCapsuleHeader
;
1305 UINTN NestedCapsuleSize
;
1306 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
1307 EFI_SYSTEM_RESOURCE_ENTRY Entry
;
1309 EsrtGuidFound
= FALSE
;
1310 if (mIsVirtualAddrConverted
) {
1311 if(mEsrtTable
!= NULL
) {
1312 EsrtEntry
= (EFI_SYSTEM_RESOURCE_ENTRY
*)(mEsrtTable
+ 1);
1313 for (Index
= 0; Index
< mEsrtTable
->FwResourceCount
; Index
++, EsrtEntry
++) {
1314 if (CompareGuid(&EsrtEntry
->FwClass
, &CapsuleHeader
->CapsuleGuid
)) {
1315 EsrtGuidFound
= TRUE
;
1322 // Check ESRT protocol
1324 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
1325 if (!EFI_ERROR(Status
)) {
1326 Status
= EsrtProtocol
->GetEsrtEntry(&CapsuleHeader
->CapsuleGuid
, &Entry
);
1327 if (!EFI_ERROR(Status
)) {
1328 EsrtGuidFound
= TRUE
;
1333 // Check Firmware Management Protocols
1335 if (!EsrtGuidFound
) {
1336 Status
= GetFmpHandleBufferByType (
1337 &CapsuleHeader
->CapsuleGuid
,
1343 if (!EFI_ERROR(Status
)) {
1344 EsrtGuidFound
= TRUE
;
1348 if (!EsrtGuidFound
) {
1353 // Check nested capsule header
1354 // FMP GUID after ESRT one
1356 NestedCapsuleHeader
= (EFI_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
1357 NestedCapsuleSize
= (UINTN
)CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
- (UINTN
)NestedCapsuleHeader
;
1358 if (NestedCapsuleSize
< sizeof(EFI_CAPSULE_HEADER
)) {
1361 if (!IsValidCapsuleHeader(NestedCapsuleHeader
, NestedCapsuleSize
)) {
1364 if (!IsFmpCapsuleGuid(&NestedCapsuleHeader
->CapsuleGuid
)) {
1367 DEBUG ((DEBUG_INFO
, "IsNestedFmpCapsule\n"));
1372 Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
1374 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1376 @retval TRUE It is a system FMP.
1377 @retval FALSE It is a device FMP.
1381 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1384 if (IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
1387 if (IsNestedFmpCapsule(CapsuleHeader
)) {
1394 Those capsules supported by the firmwares.
1396 Caution: This function may receive untrusted input.
1398 @param[in] CapsuleHeader Points to a capsule header.
1400 @retval EFI_SUCESS Input capsule is supported by firmware.
1401 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
1402 @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
1406 SupportCapsuleImage (
1407 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1411 // check Display Capsule Guid
1413 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1417 if (IsFmpCapsule(CapsuleHeader
)) {
1419 // Fake capsule header is valid case in QueryCapsuleCpapbilities().
1421 if (CapsuleHeader
->HeaderSize
== CapsuleHeader
->CapsuleImageSize
) {
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
);