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
< EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
289 FmpImageHeaderSize
= OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
291 if (FmpImageSize
< FmpImageHeaderSize
) {
292 DEBUG((DEBUG_ERROR
, "FmpImageSize(0x%lx) < FmpImageHeaderSize(0x%x)\n", FmpImageSize
, FmpImageHeaderSize
));
293 return EFI_INVALID_PARAMETER
;
297 if (FmpImageSize
!= (UINT64
)FmpImageHeaderSize
+ (UINT64
)ImageHeader
->UpdateImageSize
+ (UINT64
)ImageHeader
->UpdateVendorCodeSize
) {
298 DEBUG((DEBUG_ERROR
, "FmpImageSize(0x%lx) mismatch, UpdateImageSize(0x%x) UpdateVendorCodeSize(0x%x)\n", FmpImageSize
, ImageHeader
->UpdateImageSize
, ImageHeader
->UpdateVendorCodeSize
));
299 return EFI_INVALID_PARAMETER
;
305 // No driver & payload element in FMP
307 EndOfPayload
= (UINT8
*)(FmpCapsuleHeader
+ 1);
308 if (EndOfPayload
!= EndOfCapsule
) {
309 DEBUG((DEBUG_ERROR
, "EndOfPayload(0x%x) mismatch, EndOfCapsule(0x%x)\n", EndOfPayload
, EndOfCapsule
));
310 return EFI_INVALID_PARAMETER
;
312 return EFI_UNSUPPORTED
;
315 if (EmbeddedDriverCount
!= NULL
) {
316 *EmbeddedDriverCount
= FmpCapsuleHeader
->EmbeddedDriverCount
;
323 Those capsules supported by the firmwares.
325 Caution: This function may receive untrusted input.
327 @param[in] CapsuleHeader Points to a capsule header.
329 @retval EFI_SUCESS Input capsule is supported by firmware.
330 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
333 DisplayCapsuleImage (
334 IN EFI_CAPSULE_HEADER
*CapsuleHeader
337 DISPLAY_DISPLAY_PAYLOAD
*ImagePayload
;
340 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
344 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
347 // UX capsule doesn't have extended header entries.
349 if (CapsuleHeader
->HeaderSize
!= sizeof (EFI_CAPSULE_HEADER
)) {
350 return EFI_UNSUPPORTED
;
352 ImagePayload
= (DISPLAY_DISPLAY_PAYLOAD
*)((UINTN
) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
354 // (CapsuleImageSize > HeaderSize) is guaranteed by IsValidCapsuleHeader().
356 PayloadSize
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
;
359 // Make sure the image payload at least contain the DISPLAY_DISPLAY_PAYLOAD header.
360 // Further size check is performed by the logic translating BMP to GOP BLT.
362 if (PayloadSize
<= sizeof (DISPLAY_DISPLAY_PAYLOAD
)) {
363 return EFI_INVALID_PARAMETER
;
366 if (ImagePayload
->Version
!= 1) {
367 return EFI_UNSUPPORTED
;
369 if (CalculateCheckSum8((UINT8
*)CapsuleHeader
, CapsuleHeader
->CapsuleImageSize
) != 0) {
370 return EFI_UNSUPPORTED
;
373 // Only Support Bitmap by now
375 if (ImagePayload
->ImageType
!= 0) {
376 return EFI_UNSUPPORTED
;
382 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**)&GraphicsOutput
);
383 if (EFI_ERROR (Status
)) {
384 Status
= gBS
->LocateProtocol(&gEfiGraphicsOutputProtocolGuid
, NULL
, (VOID
**)&GraphicsOutput
);
385 if (EFI_ERROR(Status
)) {
386 return EFI_UNSUPPORTED
;
390 if (GraphicsOutput
->Mode
->Mode
!= ImagePayload
->Mode
) {
391 return EFI_UNSUPPORTED
;
397 Status
= TranslateBmpToGopBlt (
399 PayloadSize
- sizeof(DISPLAY_DISPLAY_PAYLOAD
),
406 if (EFI_ERROR (Status
)) {
410 Status
= GraphicsOutput
->Blt (
416 (UINTN
) ImagePayload
->OffsetX
,
417 (UINTN
) ImagePayload
->OffsetY
,
420 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
429 Dump FMP information.
431 @param[in] ImageInfoSize The size of ImageInfo, in bytes.
432 @param[in] ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
433 @param[in] DescriptorVersion The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
434 @param[in] DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
435 @param[in] DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
436 @param[in] PackageVersion The version of package.
437 @param[in] PackageVersionName The version name of package.
441 IN UINTN ImageInfoSize
,
442 IN EFI_FIRMWARE_IMAGE_DESCRIPTOR
*ImageInfo
,
443 IN UINT32 DescriptorVersion
,
444 IN UINT8 DescriptorCount
,
445 IN UINTN DescriptorSize
,
446 IN UINT32 PackageVersion
,
447 IN CHAR16
*PackageVersionName
450 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*CurrentImageInfo
;
453 DEBUG((DEBUG_VERBOSE
, " DescriptorVersion - 0x%x\n", DescriptorVersion
));
454 DEBUG((DEBUG_VERBOSE
, " DescriptorCount - 0x%x\n", DescriptorCount
));
455 DEBUG((DEBUG_VERBOSE
, " DescriptorSize - 0x%x\n", DescriptorSize
));
456 DEBUG((DEBUG_VERBOSE
, " PackageVersion - 0x%x\n", PackageVersion
));
457 DEBUG((DEBUG_VERBOSE
, " PackageVersionName - %s\n\n", PackageVersionName
));
458 CurrentImageInfo
= ImageInfo
;
459 for (Index
= 0; Index
< DescriptorCount
; Index
++) {
460 DEBUG((DEBUG_VERBOSE
, " ImageDescriptor (%d)\n", Index
));
461 DEBUG((DEBUG_VERBOSE
, " ImageIndex - 0x%x\n", CurrentImageInfo
->ImageIndex
));
462 DEBUG((DEBUG_VERBOSE
, " ImageTypeId - %g\n", &CurrentImageInfo
->ImageTypeId
));
463 DEBUG((DEBUG_VERBOSE
, " ImageId - 0x%lx\n", CurrentImageInfo
->ImageId
));
464 DEBUG((DEBUG_VERBOSE
, " ImageIdName - %s\n", CurrentImageInfo
->ImageIdName
));
465 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", CurrentImageInfo
->Version
));
466 DEBUG((DEBUG_VERBOSE
, " VersionName - %s\n", CurrentImageInfo
->VersionName
));
467 DEBUG((DEBUG_VERBOSE
, " Size - 0x%x\n", CurrentImageInfo
->Size
));
468 DEBUG((DEBUG_VERBOSE
, " AttributesSupported - 0x%lx\n", CurrentImageInfo
->AttributesSupported
));
469 DEBUG((DEBUG_VERBOSE
, " AttributesSetting - 0x%lx\n", CurrentImageInfo
->AttributesSetting
));
470 DEBUG((DEBUG_VERBOSE
, " Compatibilities - 0x%lx\n", CurrentImageInfo
->Compatibilities
));
471 if (DescriptorVersion
> 1) {
472 DEBUG((DEBUG_VERBOSE
, " LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo
->LowestSupportedImageVersion
));
473 if (DescriptorVersion
> 2) {
474 DEBUG((DEBUG_VERBOSE
, " LastAttemptVersion - 0x%x\n", CurrentImageInfo
->LastAttemptVersion
));
475 DEBUG((DEBUG_VERBOSE
, " LastAttemptStatus - 0x%x\n", CurrentImageInfo
->LastAttemptStatus
));
476 DEBUG((DEBUG_VERBOSE
, " HardwareInstance - 0x%lx\n", CurrentImageInfo
->HardwareInstance
));
480 // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
482 CurrentImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)CurrentImageInfo
+ DescriptorSize
);
487 Dump a non-nested FMP capsule.
489 @param[in] CapsuleHeader A pointer to CapsuleHeader
493 IN EFI_CAPSULE_HEADER
*CapsuleHeader
496 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
497 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
499 UINT64
*ItemOffsetList
;
501 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
503 DEBUG((DEBUG_VERBOSE
, "FmpCapsule:\n"));
504 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", FmpCapsuleHeader
->Version
));
505 DEBUG((DEBUG_VERBOSE
, " EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader
->EmbeddedDriverCount
));
506 DEBUG((DEBUG_VERBOSE
, " PayloadItemCount - 0x%x\n", FmpCapsuleHeader
->PayloadItemCount
));
508 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
509 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
510 DEBUG((DEBUG_VERBOSE
, " ItemOffsetList[%d] - 0x%lx\n", Index
, ItemOffsetList
[Index
]));
512 for (; Index
< (UINT32
)FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
; Index
++) {
513 DEBUG((DEBUG_VERBOSE
, " ItemOffsetList[%d] - 0x%lx\n", Index
, ItemOffsetList
[Index
]));
514 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
516 DEBUG((DEBUG_VERBOSE
, " ImageHeader:\n"));
517 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", ImageHeader
->Version
));
518 DEBUG((DEBUG_VERBOSE
, " UpdateImageTypeId - %g\n", &ImageHeader
->UpdateImageTypeId
));
519 DEBUG((DEBUG_VERBOSE
, " UpdateImageIndex - 0x%x\n", ImageHeader
->UpdateImageIndex
));
520 DEBUG((DEBUG_VERBOSE
, " UpdateImageSize - 0x%x\n", ImageHeader
->UpdateImageSize
));
521 DEBUG((DEBUG_VERBOSE
, " UpdateVendorCodeSize - 0x%x\n", ImageHeader
->UpdateVendorCodeSize
));
522 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
523 DEBUG((DEBUG_VERBOSE
, " UpdateHardwareInstance - 0x%lx\n", ImageHeader
->UpdateHardwareInstance
));
529 Dump all FMP information.
537 EFI_HANDLE
*HandleBuffer
;
538 UINTN NumberOfHandles
;
539 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
542 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
543 UINT32 FmpImageInfoDescriptorVer
;
544 UINT8 FmpImageInfoCount
;
545 UINTN DescriptorSize
;
546 UINT32 PackageVersion
;
547 CHAR16
*PackageVersionName
;
549 Status
= gBS
->LocateHandleBuffer (
551 &gEfiFirmwareManagementProtocolGuid
,
556 if (EFI_ERROR(Status
)) {
560 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
561 Status
= gBS
->HandleProtocol(
563 &gEfiFirmwareManagementProtocolGuid
,
566 if (EFI_ERROR(Status
)) {
571 Status
= Fmp
->GetImageInfo (
581 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
585 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
586 if (FmpImageInfoBuf
== NULL
) {
590 PackageVersionName
= NULL
;
591 Status
= Fmp
->GetImageInfo (
593 &ImageInfoSize
, // ImageInfoSize
594 FmpImageInfoBuf
, // ImageInfo
595 &FmpImageInfoDescriptorVer
, // DescriptorVersion
596 &FmpImageInfoCount
, // DescriptorCount
597 &DescriptorSize
, // DescriptorSize
598 &PackageVersion
, // PackageVersion
599 &PackageVersionName
// PackageVersionName
601 if (EFI_ERROR(Status
)) {
602 FreePool(FmpImageInfoBuf
);
606 DEBUG((DEBUG_INFO
, "FMP (%d) ImageInfo:\n", Index
));
608 ImageInfoSize
, // ImageInfoSize
609 FmpImageInfoBuf
, // ImageInfo
610 FmpImageInfoDescriptorVer
, // DescriptorVersion
611 FmpImageInfoCount
, // DescriptorCount
612 DescriptorSize
, // DescriptorSize
613 PackageVersion
, // PackageVersion
614 PackageVersionName
// PackageVersionName
617 if (PackageVersionName
!= NULL
) {
618 FreePool(PackageVersionName
);
621 FreePool(FmpImageInfoBuf
);
624 FreePool (HandleBuffer
);
630 Get FMP handle by ImageTypeId and HardwareInstance.
632 @param[in] UpdateImageTypeId Used to identify device firmware targeted by this update.
633 @param[in] UpdateHardwareInstance The HardwareInstance to target with this update.
634 @param[out] NoHandles The number of handles returned in HandleBuf.
635 @param[out] HandleBuf A pointer to the buffer to return the requested array of handles.
636 @param[out] ResetRequiredBuf A pointer to the buffer to return reset required flag for
637 the requested array of handles.
639 @retval EFI_SUCCESS The array of handles and their reset required flag were returned in
640 HandleBuf and ResetRequiredBuf, and the number of handles in HandleBuf
641 was returned in NoHandles.
642 @retval EFI_NOT_FOUND No handles match the search.
643 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
646 GetFmpHandleBufferByType (
647 IN EFI_GUID
*UpdateImageTypeId
,
648 IN UINT64 UpdateHardwareInstance
,
649 OUT UINTN
*NoHandles
, OPTIONAL
650 OUT EFI_HANDLE
**HandleBuf
, OPTIONAL
651 OUT BOOLEAN
**ResetRequiredBuf OPTIONAL
655 EFI_HANDLE
*HandleBuffer
;
656 UINTN NumberOfHandles
;
657 EFI_HANDLE
*MatchedHandleBuffer
;
658 BOOLEAN
*MatchedResetRequiredBuffer
;
659 UINTN MatchedNumberOfHandles
;
660 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
663 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
664 UINT32 FmpImageInfoDescriptorVer
;
665 UINT8 FmpImageInfoCount
;
666 UINTN DescriptorSize
;
667 UINT32 PackageVersion
;
668 CHAR16
*PackageVersionName
;
670 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*TempFmpImageInfo
;
672 if (NoHandles
!= NULL
) {
675 if (HandleBuf
!= NULL
) {
678 if (ResetRequiredBuf
!= NULL
) {
679 *ResetRequiredBuf
= NULL
;
682 Status
= gBS
->LocateHandleBuffer (
684 &gEfiFirmwareManagementProtocolGuid
,
689 if (EFI_ERROR(Status
)) {
693 MatchedNumberOfHandles
= 0;
695 MatchedHandleBuffer
= NULL
;
696 if (HandleBuf
!= NULL
) {
697 MatchedHandleBuffer
= AllocateZeroPool (sizeof(EFI_HANDLE
) * NumberOfHandles
);
698 if (MatchedHandleBuffer
== NULL
) {
699 FreePool (HandleBuffer
);
700 return EFI_OUT_OF_RESOURCES
;
704 MatchedResetRequiredBuffer
= NULL
;
705 if (ResetRequiredBuf
!= NULL
) {
706 MatchedResetRequiredBuffer
= AllocateZeroPool (sizeof(BOOLEAN
) * NumberOfHandles
);
707 if (MatchedResetRequiredBuffer
== NULL
) {
708 if (MatchedHandleBuffer
!= NULL
) {
709 FreePool (MatchedHandleBuffer
);
711 FreePool (HandleBuffer
);
712 return EFI_OUT_OF_RESOURCES
;
716 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
717 Status
= gBS
->HandleProtocol(
719 &gEfiFirmwareManagementProtocolGuid
,
722 if (EFI_ERROR(Status
)) {
727 Status
= Fmp
->GetImageInfo (
737 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
741 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
742 if (FmpImageInfoBuf
== NULL
) {
746 PackageVersionName
= NULL
;
747 Status
= Fmp
->GetImageInfo (
749 &ImageInfoSize
, // ImageInfoSize
750 FmpImageInfoBuf
, // ImageInfo
751 &FmpImageInfoDescriptorVer
, // DescriptorVersion
752 &FmpImageInfoCount
, // DescriptorCount
753 &DescriptorSize
, // DescriptorSize
754 &PackageVersion
, // PackageVersion
755 &PackageVersionName
// PackageVersionName
757 if (EFI_ERROR(Status
)) {
758 FreePool(FmpImageInfoBuf
);
762 if (PackageVersionName
!= NULL
) {
763 FreePool(PackageVersionName
);
766 TempFmpImageInfo
= FmpImageInfoBuf
;
767 for (Index2
= 0; Index2
< FmpImageInfoCount
; Index2
++) {
769 // Check if this FMP instance matches
771 if (CompareGuid(UpdateImageTypeId
, &TempFmpImageInfo
->ImageTypeId
)) {
772 if ((UpdateHardwareInstance
== 0) ||
773 ((FmpImageInfoDescriptorVer
>= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
) &&
774 (UpdateHardwareInstance
== TempFmpImageInfo
->HardwareInstance
))) {
775 if (MatchedHandleBuffer
!= NULL
) {
776 MatchedHandleBuffer
[MatchedNumberOfHandles
] = HandleBuffer
[Index
];
778 if (MatchedResetRequiredBuffer
!= NULL
) {
779 MatchedResetRequiredBuffer
[MatchedNumberOfHandles
] = (((TempFmpImageInfo
->AttributesSupported
&
780 IMAGE_ATTRIBUTE_RESET_REQUIRED
) != 0) &&
781 ((TempFmpImageInfo
->AttributesSetting
&
782 IMAGE_ATTRIBUTE_RESET_REQUIRED
) != 0));
784 MatchedNumberOfHandles
++;
788 TempFmpImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)TempFmpImageInfo
+ DescriptorSize
);
790 FreePool(FmpImageInfoBuf
);
793 FreePool (HandleBuffer
);
795 if (MatchedNumberOfHandles
== 0) {
796 return EFI_NOT_FOUND
;
799 if (NoHandles
!= NULL
) {
800 *NoHandles
= MatchedNumberOfHandles
;
802 if (HandleBuf
!= NULL
) {
803 *HandleBuf
= MatchedHandleBuffer
;
805 if (ResetRequiredBuf
!= NULL
) {
806 *ResetRequiredBuf
= MatchedResetRequiredBuffer
;
813 Return FmpImageInfoDescriptorVer by an FMP handle.
815 @param[in] Handle A FMP handle.
817 @return FmpImageInfoDescriptorVer associated with the FMP.
820 GetFmpImageInfoDescriptorVer (
825 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
827 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
828 UINT32 FmpImageInfoDescriptorVer
;
829 UINT8 FmpImageInfoCount
;
830 UINTN DescriptorSize
;
831 UINT32 PackageVersion
;
832 CHAR16
*PackageVersionName
;
834 Status
= gBS
->HandleProtocol(
836 &gEfiFirmwareManagementProtocolGuid
,
839 if (EFI_ERROR(Status
)) {
844 Status
= Fmp
->GetImageInfo (
854 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
858 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
859 if (FmpImageInfoBuf
== NULL
) {
863 PackageVersionName
= NULL
;
864 Status
= Fmp
->GetImageInfo (
866 &ImageInfoSize
, // ImageInfoSize
867 FmpImageInfoBuf
, // ImageInfo
868 &FmpImageInfoDescriptorVer
, // DescriptorVersion
869 &FmpImageInfoCount
, // DescriptorCount
870 &DescriptorSize
, // DescriptorSize
871 &PackageVersion
, // PackageVersion
872 &PackageVersionName
// PackageVersionName
874 if (EFI_ERROR(Status
)) {
875 FreePool(FmpImageInfoBuf
);
878 return FmpImageInfoDescriptorVer
;
884 @param[in] Handle A FMP handle.
885 @param[in] ImageHeader The payload image header.
886 @param[in] PayloadIndex The index of the payload.
888 @return The status of FMP->SetImage.
892 IN EFI_HANDLE Handle
,
893 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
,
894 IN UINTN PayloadIndex
898 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
902 EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS ProgressCallback
;
904 Status
= gBS
->HandleProtocol(
906 &gEfiFirmwareManagementProtocolGuid
,
909 if (EFI_ERROR(Status
)) {
914 // Lookup Firmware Management Progress Protocol before SetImage() is called
915 // This is an optional protocol that may not be present on Handle.
917 Status
= gBS
->HandleProtocol (
919 &gEdkiiFirmwareManagementProgressProtocolGuid
,
920 (VOID
**)&mFmpProgress
922 if (EFI_ERROR (Status
)) {
926 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
927 Image
= (UINT8
*)(ImageHeader
+ 1);
930 // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1,
931 // Header should exclude UpdateHardwareInstance field
933 Image
= (UINT8
*)ImageHeader
+ OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
936 if (ImageHeader
->UpdateVendorCodeSize
== 0) {
939 VendorCode
= Image
+ ImageHeader
->UpdateImageSize
;
942 DEBUG((DEBUG_INFO
, "Fmp->SetImage ...\n"));
943 DEBUG((DEBUG_INFO
, "ImageTypeId - %g, ", &ImageHeader
->UpdateImageTypeId
));
944 DEBUG((DEBUG_INFO
, "PayloadIndex - 0x%x, ", PayloadIndex
));
945 DEBUG((DEBUG_INFO
, "ImageIndex - 0x%x ", ImageHeader
->UpdateImageIndex
));
946 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
947 DEBUG((DEBUG_INFO
, "(UpdateHardwareInstance - 0x%x)", ImageHeader
->UpdateHardwareInstance
));
949 DEBUG((DEBUG_INFO
, "\n"));
952 // Before calling SetImage(), reset the progress bar to 0%
954 ProgressCallback
= UpdateImageProgress
;
955 Status
= UpdateImageProgress (0);
956 if (EFI_ERROR (Status
)) {
957 ProgressCallback
= NULL
;
960 Status
= Fmp
->SetImage(
962 ImageHeader
->UpdateImageIndex
, // ImageIndex
964 ImageHeader
->UpdateImageSize
, // ImageSize
965 VendorCode
, // VendorCode
966 ProgressCallback
, // Progress
967 &AbortReason
// AbortReason
970 // Set the progress bar to 100% after returning from SetImage()
972 if (ProgressCallback
!= NULL
) {
973 UpdateImageProgress (100);
976 DEBUG((DEBUG_INFO
, "Fmp->SetImage - %r\n", Status
));
977 if (AbortReason
!= NULL
) {
978 DEBUG ((DEBUG_ERROR
, "%s\n", AbortReason
));
979 FreePool(AbortReason
);
983 // Clear mFmpProgress after SetImage() returns
991 Start a UEFI image in the FMP payload.
993 @param[in] ImageBuffer A pointer to the memory location containing a copy of the image to be loaded..
994 @param[in] ImageSize The size in bytes of ImageBuffer.
996 @return The status of gBS->LoadImage and gBS->StartImage.
1000 IN VOID
*ImageBuffer
,
1004 MEMMAP_DEVICE_PATH MemMapNode
;
1006 EFI_HANDLE ImageHandle
;
1007 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
1010 SetDevicePathNodeLength (&MemMapNode
.Header
, sizeof (MemMapNode
));
1011 MemMapNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
1012 MemMapNode
.Header
.SubType
= HW_MEMMAP_DP
;
1013 MemMapNode
.MemoryType
= EfiBootServicesCode
;
1014 MemMapNode
.StartingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)ImageBuffer
;
1015 MemMapNode
.EndingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)((UINT8
*)ImageBuffer
+ ImageSize
- 1);
1017 DriverDevicePath
= AppendDevicePathNode (NULL
, &MemMapNode
.Header
);
1018 if (DriverDevicePath
== NULL
) {
1019 return EFI_OUT_OF_RESOURCES
;
1022 DEBUG((DEBUG_INFO
, "FmpCapsule: LoadImage ...\n"));
1023 Status
= gBS
->LoadImage(
1031 DEBUG((DEBUG_INFO
, "FmpCapsule: LoadImage - %r\n", Status
));
1032 if (EFI_ERROR(Status
)) {
1034 // With EFI_SECURITY_VIOLATION retval, the Image was loaded and an ImageHandle was created
1035 // with a valid EFI_LOADED_IMAGE_PROTOCOL, but the image can not be started right now.
1036 // If the caller doesn't have the option to defer the execution of an image, we should
1037 // unload image for the EFI_SECURITY_VIOLATION to avoid resource leak.
1039 if (Status
== EFI_SECURITY_VIOLATION
) {
1040 gBS
->UnloadImage (ImageHandle
);
1042 FreePool(DriverDevicePath
);
1046 DEBUG((DEBUG_INFO
, "FmpCapsule: StartImage ...\n"));
1047 Status
= gBS
->StartImage(
1052 DEBUG((DEBUG_INFO
, "FmpCapsule: StartImage - %r\n", Status
));
1053 if (EFI_ERROR(Status
)) {
1054 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
1057 FreePool(DriverDevicePath
);
1062 Record FMP capsule status.
1064 @param[in] Handle A FMP handle.
1065 @param[in] CapsuleHeader The capsule image header
1066 @param[in] CapsuleStatus The capsule process stauts
1067 @param[in] PayloadIndex FMP payload index
1068 @param[in] ImageHeader FMP image header
1069 @param[in] CapFileName Capsule file name
1072 RecordFmpCapsuleStatus (
1073 IN EFI_HANDLE Handle
, OPTIONAL
1074 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
1075 IN EFI_STATUS CapsuleStatus
,
1076 IN UINTN PayloadIndex
,
1077 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
,
1078 IN CHAR16
*CapFileName OPTIONAL
1082 EFI_DEVICE_PATH_PROTOCOL
*FmpDevicePath
;
1083 UINT32 FmpImageInfoDescriptorVer
;
1084 EFI_STATUS StatusEsrt
;
1085 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
1086 EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry
;
1088 FmpDevicePath
= NULL
;
1089 if (Handle
!= NULL
) {
1090 gBS
->HandleProtocol(
1092 &gEfiDevicePathProtocolGuid
,
1093 (VOID
**)&FmpDevicePath
1097 RecordFmpCapsuleStatusVariable (
1107 // Update corresponding ESRT entry LastAttemp Status
1109 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
1110 if (EFI_ERROR (Status
)) {
1114 if (Handle
== NULL
) {
1119 // Update EsrtEntry For V1, V2 FMP instance.
1120 // V3 FMP ESRT cache will be synced up through SyncEsrtFmp interface
1122 FmpImageInfoDescriptorVer
= GetFmpImageInfoDescriptorVer (Handle
);
1123 if (FmpImageInfoDescriptorVer
< EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
) {
1124 StatusEsrt
= EsrtProtocol
->GetEsrtEntry(&ImageHeader
->UpdateImageTypeId
, &EsrtEntry
);
1125 if (!EFI_ERROR(StatusEsrt
)){
1126 if (!EFI_ERROR(CapsuleStatus
)) {
1127 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_SUCCESS
;
1129 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL
;
1131 EsrtEntry
.LastAttemptVersion
= 0;
1132 EsrtProtocol
->UpdateEsrtEntry(&EsrtEntry
);
1138 Process Firmware management protocol data capsule.
1140 This function assumes the caller validated the capsule by using
1141 ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
1142 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
1143 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
1145 This function need support nested FMP capsule.
1147 @param[in] CapsuleHeader Points to a capsule header.
1148 @param[in] CapFileName Capsule file name.
1149 @param[out] ResetRequired Indicates whether reset is required or not.
1151 @retval EFI_SUCESS Process Capsule Image successfully.
1152 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1153 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1154 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1155 @retval EFI_NOT_READY No FMP protocol to handle this FMP capsule.
1158 ProcessFmpCapsuleImage (
1159 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
1160 IN CHAR16
*CapFileName
, OPTIONAL
1161 OUT BOOLEAN
*ResetRequired OPTIONAL
1165 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
1166 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
1167 UINT64
*ItemOffsetList
;
1170 EFI_HANDLE
*HandleBuffer
;
1171 BOOLEAN
*ResetRequiredBuffer
;
1172 UINTN NumberOfHandles
;
1174 UINT64 UpdateHardwareInstance
;
1179 if (!IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
1180 return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
), CapFileName
, ResetRequired
);
1186 DumpFmpCapsule(CapsuleHeader
);
1188 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
1190 if (FmpCapsuleHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
1191 return EFI_INVALID_PARAMETER
;
1193 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
1195 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
1198 // capsule in which driver count and payload count are both zero is not processed.
1205 // 1. Try to load & start all the drivers within capsule
1207 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
1208 if ((FmpCapsuleHeader
->PayloadItemCount
== 0) &&
1209 (Index
== (UINTN
)FmpCapsuleHeader
->EmbeddedDriverCount
- 1)) {
1211 // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
1213 DriverLen
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
- (UINTN
)ItemOffsetList
[Index
];
1215 DriverLen
= (UINTN
)ItemOffsetList
[Index
+ 1] - (UINTN
)ItemOffsetList
[Index
];
1218 Status
= StartFmpImage (
1219 (UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
],
1222 if (EFI_ERROR(Status
)) {
1223 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
1229 // 2. Route payload to right FMP instance
1231 DEBUG((DEBUG_INFO
, "FmpCapsule: route payload to right FMP instance ...\n"));
1236 // Check all the payload entry in capsule payload list
1238 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
1239 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
1241 UpdateHardwareInstance
= 0;
1242 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
1243 UpdateHardwareInstance
= ImageHeader
->UpdateHardwareInstance
;
1246 Status
= GetFmpHandleBufferByType (
1247 &ImageHeader
->UpdateImageTypeId
,
1248 UpdateHardwareInstance
,
1251 &ResetRequiredBuffer
1253 if (EFI_ERROR(Status
) ||
1254 (HandleBuffer
== NULL
) ||
1255 (ResetRequiredBuffer
== NULL
)) {
1257 RecordFmpCapsuleStatus (
1261 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1268 for (Index2
= 0; Index2
< NumberOfHandles
; Index2
++) {
1270 RecordFmpCapsuleStatus (
1271 HandleBuffer
[Index2
],
1274 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1281 Status
= SetFmpImageData (
1282 HandleBuffer
[Index2
],
1284 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
1286 if (Status
!= EFI_SUCCESS
) {
1289 if (ResetRequired
!= NULL
) {
1290 *ResetRequired
|= ResetRequiredBuffer
[Index2
];
1294 RecordFmpCapsuleStatus (
1295 HandleBuffer
[Index2
],
1298 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1303 if (HandleBuffer
!= NULL
) {
1304 FreePool(HandleBuffer
);
1306 if (ResetRequiredBuffer
!= NULL
) {
1307 FreePool(ResetRequiredBuffer
);
1312 return EFI_NOT_READY
;
1316 // always return SUCCESS to indicate this capsule is processed.
1317 // The status of SetImage is recorded in capsule result variable.
1323 Return if there is a FMP header below capsule header.
1325 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1327 @retval TRUE There is a FMP header below capsule header.
1328 @retval FALSE There is not a FMP header below capsule header
1331 IsNestedFmpCapsule (
1332 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1336 EFI_SYSTEM_RESOURCE_ENTRY
*EsrtEntry
;
1338 BOOLEAN EsrtGuidFound
;
1339 EFI_CAPSULE_HEADER
*NestedCapsuleHeader
;
1340 UINTN NestedCapsuleSize
;
1341 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
1342 EFI_SYSTEM_RESOURCE_ENTRY Entry
;
1344 EsrtGuidFound
= FALSE
;
1345 if (mIsVirtualAddrConverted
) {
1346 if(mEsrtTable
!= NULL
) {
1347 EsrtEntry
= (EFI_SYSTEM_RESOURCE_ENTRY
*)(mEsrtTable
+ 1);
1348 for (Index
= 0; Index
< mEsrtTable
->FwResourceCount
; Index
++, EsrtEntry
++) {
1349 if (CompareGuid(&EsrtEntry
->FwClass
, &CapsuleHeader
->CapsuleGuid
)) {
1350 EsrtGuidFound
= TRUE
;
1357 // Check ESRT protocol
1359 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
1360 if (!EFI_ERROR(Status
)) {
1361 Status
= EsrtProtocol
->GetEsrtEntry(&CapsuleHeader
->CapsuleGuid
, &Entry
);
1362 if (!EFI_ERROR(Status
)) {
1363 EsrtGuidFound
= TRUE
;
1368 // Check Firmware Management Protocols
1370 if (!EsrtGuidFound
) {
1371 Status
= GetFmpHandleBufferByType (
1372 &CapsuleHeader
->CapsuleGuid
,
1378 if (!EFI_ERROR(Status
)) {
1379 EsrtGuidFound
= TRUE
;
1383 if (!EsrtGuidFound
) {
1388 // Check nested capsule header
1389 // FMP GUID after ESRT one
1391 NestedCapsuleHeader
= (EFI_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
1392 NestedCapsuleSize
= (UINTN
)CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
- (UINTN
)NestedCapsuleHeader
;
1393 if (NestedCapsuleSize
< sizeof(EFI_CAPSULE_HEADER
)) {
1396 if (!IsValidCapsuleHeader(NestedCapsuleHeader
, NestedCapsuleSize
)) {
1399 if (!IsFmpCapsuleGuid(&NestedCapsuleHeader
->CapsuleGuid
)) {
1402 DEBUG ((DEBUG_INFO
, "IsNestedFmpCapsule\n"));
1407 Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
1409 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1411 @retval TRUE It is a system FMP.
1412 @retval FALSE It is a device FMP.
1416 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1419 if (IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
1422 if (IsNestedFmpCapsule(CapsuleHeader
)) {
1429 Those capsules supported by the firmwares.
1431 Caution: This function may receive untrusted input.
1433 @param[in] CapsuleHeader Points to a capsule header.
1435 @retval EFI_SUCESS Input capsule is supported by firmware.
1436 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
1437 @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
1441 SupportCapsuleImage (
1442 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1446 // check Display Capsule Guid
1448 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1453 // Check capsule file name capsule
1455 if (IsCapsuleNameCapsule(CapsuleHeader
)) {
1459 if (IsFmpCapsule(CapsuleHeader
)) {
1461 // Fake capsule header is valid case in QueryCapsuleCpapbilities().
1463 if (CapsuleHeader
->HeaderSize
== CapsuleHeader
->CapsuleImageSize
) {
1467 // Check layout of FMP capsule
1469 return ValidateFmpCapsule(CapsuleHeader
, NULL
);
1471 DEBUG((DEBUG_ERROR
, "Unknown Capsule Guid - %g\n", &CapsuleHeader
->CapsuleGuid
));
1472 return EFI_UNSUPPORTED
;
1476 The firmware implements to process the capsule image.
1478 Caution: This function may receive untrusted input.
1480 @param[in] CapsuleHeader Points to a capsule header.
1481 @param[in] CapFileName Capsule file name.
1482 @param[out] ResetRequired Indicates whether reset is required or not.
1484 @retval EFI_SUCESS Process Capsule Image successfully.
1485 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1486 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1487 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1491 ProcessThisCapsuleImage (
1492 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
1493 IN CHAR16
*CapFileName
, OPTIONAL
1494 OUT BOOLEAN
*ResetRequired OPTIONAL
1499 if (SupportCapsuleImage (CapsuleHeader
) != EFI_SUCCESS
) {
1500 RecordCapsuleStatusVariable(CapsuleHeader
, EFI_UNSUPPORTED
);
1501 return EFI_UNSUPPORTED
;
1505 // Display image in firmware update display capsule
1507 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1508 DEBUG((DEBUG_INFO
, "ProcessCapsuleImage for WindowsUxCapsule ...\n"));
1509 Status
= DisplayCapsuleImage(CapsuleHeader
);
1510 RecordCapsuleStatusVariable(CapsuleHeader
, Status
);
1515 // Check FMP capsule layout
1517 if (IsFmpCapsule (CapsuleHeader
)) {
1518 DEBUG((DEBUG_INFO
, "ProcessCapsuleImage for FmpCapsule ...\n"));
1519 DEBUG((DEBUG_INFO
, "ValidateFmpCapsule ...\n"));
1520 Status
= ValidateFmpCapsule(CapsuleHeader
, NULL
);
1521 DEBUG((DEBUG_INFO
, "ValidateFmpCapsule - %r\n", Status
));
1522 if (EFI_ERROR(Status
)) {
1523 RecordCapsuleStatusVariable(CapsuleHeader
, Status
);
1528 // Process EFI FMP Capsule
1530 DEBUG((DEBUG_INFO
, "ProcessFmpCapsuleImage ...\n"));
1531 Status
= ProcessFmpCapsuleImage(CapsuleHeader
, CapFileName
, ResetRequired
);
1532 DEBUG((DEBUG_INFO
, "ProcessFmpCapsuleImage - %r\n", Status
));
1537 return EFI_UNSUPPORTED
;
1541 The firmware implements to process the capsule image.
1543 Caution: This function may receive untrusted input.
1545 @param[in] CapsuleHeader Points to a capsule header.
1547 @retval EFI_SUCESS Process Capsule Image successfully.
1548 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1549 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1550 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1554 ProcessCapsuleImage (
1555 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1558 return ProcessThisCapsuleImage (CapsuleHeader
, NULL
, NULL
);
1562 Callback function executed when the EndOfDxe event group is signaled.
1564 @param[in] Event Event whose notification function is being invoked.
1565 @param[in] Context The pointer to the notification function's context, which
1566 is implementation-dependent.
1570 DxeCapsuleLibEndOfDxe (
1575 mDxeCapsuleLibEndOfDxe
= TRUE
;
1579 The constructor function.
1581 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1582 @param[in] SystemTable A pointer to the EFI System Table.
1584 @retval EFI_SUCCESS The constructor successfully .
1588 DxeCapsuleLibConstructor (
1589 IN EFI_HANDLE ImageHandle
,
1590 IN EFI_SYSTEM_TABLE
*SystemTable
1595 Status
= gBS
->CreateEventEx (
1598 DxeCapsuleLibEndOfDxe
,
1600 &gEfiEndOfDxeEventGroupGuid
,
1601 &mDxeCapsuleLibEndOfDxeEvent
1603 ASSERT_EFI_ERROR (Status
);
1605 InitCapsuleVariable();
1611 The destructor function closes the End of DXE event.
1613 @param ImageHandle The firmware allocated handle for the EFI image.
1614 @param SystemTable A pointer to the EFI System Table.
1616 @retval EFI_SUCCESS The destructor completed successfully.
1620 DxeCapsuleLibDestructor (
1621 IN EFI_HANDLE ImageHandle
,
1622 IN EFI_SYSTEM_TABLE
*SystemTable
1628 // Close the End of DXE event.
1630 Status
= gBS
->CloseEvent (mDxeCapsuleLibEndOfDxeEvent
);
1631 ASSERT_EFI_ERROR (Status
);