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
)) {
1033 FreePool(DriverDevicePath
);
1037 DEBUG((DEBUG_INFO
, "FmpCapsule: StartImage ...\n"));
1038 Status
= gBS
->StartImage(
1043 DEBUG((DEBUG_INFO
, "FmpCapsule: StartImage - %r\n", Status
));
1044 if (EFI_ERROR(Status
)) {
1045 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
1048 FreePool(DriverDevicePath
);
1053 Record FMP capsule status.
1055 @param[in] Handle A FMP handle.
1056 @param[in] CapsuleHeader The capsule image header
1057 @param[in] CapsuleStatus The capsule process stauts
1058 @param[in] PayloadIndex FMP payload index
1059 @param[in] ImageHeader FMP image header
1060 @param[in] CapFileName Capsule file name
1063 RecordFmpCapsuleStatus (
1064 IN EFI_HANDLE Handle
, OPTIONAL
1065 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
1066 IN EFI_STATUS CapsuleStatus
,
1067 IN UINTN PayloadIndex
,
1068 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
,
1069 IN CHAR16
*CapFileName OPTIONAL
1073 EFI_DEVICE_PATH_PROTOCOL
*FmpDevicePath
;
1074 UINT32 FmpImageInfoDescriptorVer
;
1075 EFI_STATUS StatusEsrt
;
1076 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
1077 EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry
;
1079 FmpDevicePath
= NULL
;
1080 if (Handle
!= NULL
) {
1081 gBS
->HandleProtocol(
1083 &gEfiDevicePathProtocolGuid
,
1084 (VOID
**)&FmpDevicePath
1088 RecordFmpCapsuleStatusVariable (
1098 // Update corresponding ESRT entry LastAttemp Status
1100 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
1101 if (EFI_ERROR (Status
)) {
1105 if (Handle
== NULL
) {
1110 // Update EsrtEntry For V1, V2 FMP instance.
1111 // V3 FMP ESRT cache will be synced up through SyncEsrtFmp interface
1113 FmpImageInfoDescriptorVer
= GetFmpImageInfoDescriptorVer (Handle
);
1114 if (FmpImageInfoDescriptorVer
< EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
) {
1115 StatusEsrt
= EsrtProtocol
->GetEsrtEntry(&ImageHeader
->UpdateImageTypeId
, &EsrtEntry
);
1116 if (!EFI_ERROR(StatusEsrt
)){
1117 if (!EFI_ERROR(CapsuleStatus
)) {
1118 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_SUCCESS
;
1120 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL
;
1122 EsrtEntry
.LastAttemptVersion
= 0;
1123 EsrtProtocol
->UpdateEsrtEntry(&EsrtEntry
);
1129 Process Firmware management protocol data capsule.
1131 This function assumes the caller validated the capsule by using
1132 ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
1133 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
1134 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
1136 This function need support nested FMP capsule.
1138 @param[in] CapsuleHeader Points to a capsule header.
1139 @param[in] CapFileName Capsule file name.
1140 @param[out] ResetRequired Indicates whether reset is required or not.
1142 @retval EFI_SUCESS Process Capsule Image successfully.
1143 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1144 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1145 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1146 @retval EFI_NOT_READY No FMP protocol to handle this FMP capsule.
1149 ProcessFmpCapsuleImage (
1150 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
1151 IN CHAR16
*CapFileName
, OPTIONAL
1152 OUT BOOLEAN
*ResetRequired OPTIONAL
1156 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
1157 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
1158 UINT64
*ItemOffsetList
;
1161 EFI_HANDLE
*HandleBuffer
;
1162 BOOLEAN
*ResetRequiredBuffer
;
1163 UINTN NumberOfHandles
;
1165 UINT64 UpdateHardwareInstance
;
1170 if (!IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
1171 return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
), CapFileName
, ResetRequired
);
1177 DumpFmpCapsule(CapsuleHeader
);
1179 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
1181 if (FmpCapsuleHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
1182 return EFI_INVALID_PARAMETER
;
1184 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
1186 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
1189 // capsule in which driver count and payload count are both zero is not processed.
1196 // 1. Try to load & start all the drivers within capsule
1198 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
1199 if ((FmpCapsuleHeader
->PayloadItemCount
== 0) &&
1200 (Index
== (UINTN
)FmpCapsuleHeader
->EmbeddedDriverCount
- 1)) {
1202 // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
1204 DriverLen
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
- (UINTN
)ItemOffsetList
[Index
];
1206 DriverLen
= (UINTN
)ItemOffsetList
[Index
+ 1] - (UINTN
)ItemOffsetList
[Index
];
1209 Status
= StartFmpImage (
1210 (UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
],
1213 if (EFI_ERROR(Status
)) {
1214 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
1220 // 2. Route payload to right FMP instance
1222 DEBUG((DEBUG_INFO
, "FmpCapsule: route payload to right FMP instance ...\n"));
1227 // Check all the payload entry in capsule payload list
1229 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
1230 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
1232 UpdateHardwareInstance
= 0;
1233 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
1234 UpdateHardwareInstance
= ImageHeader
->UpdateHardwareInstance
;
1237 Status
= GetFmpHandleBufferByType (
1238 &ImageHeader
->UpdateImageTypeId
,
1239 UpdateHardwareInstance
,
1242 &ResetRequiredBuffer
1244 if (EFI_ERROR(Status
) ||
1245 (HandleBuffer
== NULL
) ||
1246 (ResetRequiredBuffer
== NULL
)) {
1248 RecordFmpCapsuleStatus (
1252 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1259 for (Index2
= 0; Index2
< NumberOfHandles
; Index2
++) {
1261 RecordFmpCapsuleStatus (
1262 HandleBuffer
[Index2
],
1265 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1272 Status
= SetFmpImageData (
1273 HandleBuffer
[Index2
],
1275 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
1277 if (Status
!= EFI_SUCCESS
) {
1280 if (ResetRequired
!= NULL
) {
1281 *ResetRequired
|= ResetRequiredBuffer
[Index2
];
1285 RecordFmpCapsuleStatus (
1286 HandleBuffer
[Index2
],
1289 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1294 if (HandleBuffer
!= NULL
) {
1295 FreePool(HandleBuffer
);
1297 if (ResetRequiredBuffer
!= NULL
) {
1298 FreePool(ResetRequiredBuffer
);
1303 return EFI_NOT_READY
;
1307 // always return SUCCESS to indicate this capsule is processed.
1308 // The status of SetImage is recorded in capsule result variable.
1314 Return if there is a FMP header below capsule header.
1316 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1318 @retval TRUE There is a FMP header below capsule header.
1319 @retval FALSE There is not a FMP header below capsule header
1322 IsNestedFmpCapsule (
1323 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1327 EFI_SYSTEM_RESOURCE_ENTRY
*EsrtEntry
;
1329 BOOLEAN EsrtGuidFound
;
1330 EFI_CAPSULE_HEADER
*NestedCapsuleHeader
;
1331 UINTN NestedCapsuleSize
;
1332 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
1333 EFI_SYSTEM_RESOURCE_ENTRY Entry
;
1335 EsrtGuidFound
= FALSE
;
1336 if (mIsVirtualAddrConverted
) {
1337 if(mEsrtTable
!= NULL
) {
1338 EsrtEntry
= (EFI_SYSTEM_RESOURCE_ENTRY
*)(mEsrtTable
+ 1);
1339 for (Index
= 0; Index
< mEsrtTable
->FwResourceCount
; Index
++, EsrtEntry
++) {
1340 if (CompareGuid(&EsrtEntry
->FwClass
, &CapsuleHeader
->CapsuleGuid
)) {
1341 EsrtGuidFound
= TRUE
;
1348 // Check ESRT protocol
1350 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
1351 if (!EFI_ERROR(Status
)) {
1352 Status
= EsrtProtocol
->GetEsrtEntry(&CapsuleHeader
->CapsuleGuid
, &Entry
);
1353 if (!EFI_ERROR(Status
)) {
1354 EsrtGuidFound
= TRUE
;
1359 // Check Firmware Management Protocols
1361 if (!EsrtGuidFound
) {
1362 Status
= GetFmpHandleBufferByType (
1363 &CapsuleHeader
->CapsuleGuid
,
1369 if (!EFI_ERROR(Status
)) {
1370 EsrtGuidFound
= TRUE
;
1374 if (!EsrtGuidFound
) {
1379 // Check nested capsule header
1380 // FMP GUID after ESRT one
1382 NestedCapsuleHeader
= (EFI_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
1383 NestedCapsuleSize
= (UINTN
)CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
- (UINTN
)NestedCapsuleHeader
;
1384 if (NestedCapsuleSize
< sizeof(EFI_CAPSULE_HEADER
)) {
1387 if (!IsValidCapsuleHeader(NestedCapsuleHeader
, NestedCapsuleSize
)) {
1390 if (!IsFmpCapsuleGuid(&NestedCapsuleHeader
->CapsuleGuid
)) {
1393 DEBUG ((DEBUG_INFO
, "IsNestedFmpCapsule\n"));
1398 Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
1400 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1402 @retval TRUE It is a system FMP.
1403 @retval FALSE It is a device FMP.
1407 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1410 if (IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
1413 if (IsNestedFmpCapsule(CapsuleHeader
)) {
1420 Those capsules supported by the firmwares.
1422 Caution: This function may receive untrusted input.
1424 @param[in] CapsuleHeader Points to a capsule header.
1426 @retval EFI_SUCESS Input capsule is supported by firmware.
1427 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
1428 @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
1432 SupportCapsuleImage (
1433 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1437 // check Display Capsule Guid
1439 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1444 // Check capsule file name capsule
1446 if (IsCapsuleNameCapsule(CapsuleHeader
)) {
1450 if (IsFmpCapsule(CapsuleHeader
)) {
1452 // Fake capsule header is valid case in QueryCapsuleCpapbilities().
1454 if (CapsuleHeader
->HeaderSize
== CapsuleHeader
->CapsuleImageSize
) {
1458 // Check layout of FMP capsule
1460 return ValidateFmpCapsule(CapsuleHeader
, NULL
);
1462 DEBUG((DEBUG_ERROR
, "Unknown Capsule Guid - %g\n", &CapsuleHeader
->CapsuleGuid
));
1463 return EFI_UNSUPPORTED
;
1467 The firmware implements to process the capsule image.
1469 Caution: This function may receive untrusted input.
1471 @param[in] CapsuleHeader Points to a capsule header.
1472 @param[in] CapFileName Capsule file name.
1473 @param[out] ResetRequired Indicates whether reset is required or not.
1475 @retval EFI_SUCESS Process Capsule Image successfully.
1476 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1477 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1478 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1482 ProcessThisCapsuleImage (
1483 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
1484 IN CHAR16
*CapFileName
, OPTIONAL
1485 OUT BOOLEAN
*ResetRequired OPTIONAL
1490 if (SupportCapsuleImage (CapsuleHeader
) != EFI_SUCCESS
) {
1491 RecordCapsuleStatusVariable(CapsuleHeader
, EFI_UNSUPPORTED
);
1492 return EFI_UNSUPPORTED
;
1496 // Display image in firmware update display capsule
1498 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1499 DEBUG((DEBUG_INFO
, "ProcessCapsuleImage for WindowsUxCapsule ...\n"));
1500 Status
= DisplayCapsuleImage(CapsuleHeader
);
1501 RecordCapsuleStatusVariable(CapsuleHeader
, Status
);
1506 // Check FMP capsule layout
1508 if (IsFmpCapsule (CapsuleHeader
)) {
1509 DEBUG((DEBUG_INFO
, "ProcessCapsuleImage for FmpCapsule ...\n"));
1510 DEBUG((DEBUG_INFO
, "ValidateFmpCapsule ...\n"));
1511 Status
= ValidateFmpCapsule(CapsuleHeader
, NULL
);
1512 DEBUG((DEBUG_INFO
, "ValidateFmpCapsule - %r\n", Status
));
1513 if (EFI_ERROR(Status
)) {
1514 RecordCapsuleStatusVariable(CapsuleHeader
, Status
);
1519 // Process EFI FMP Capsule
1521 DEBUG((DEBUG_INFO
, "ProcessFmpCapsuleImage ...\n"));
1522 Status
= ProcessFmpCapsuleImage(CapsuleHeader
, CapFileName
, ResetRequired
);
1523 DEBUG((DEBUG_INFO
, "ProcessFmpCapsuleImage - %r\n", Status
));
1528 return EFI_UNSUPPORTED
;
1532 The firmware implements to process the capsule image.
1534 Caution: This function may receive untrusted input.
1536 @param[in] CapsuleHeader Points to a capsule header.
1538 @retval EFI_SUCESS Process Capsule Image successfully.
1539 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1540 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1541 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1545 ProcessCapsuleImage (
1546 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1549 return ProcessThisCapsuleImage (CapsuleHeader
, NULL
, NULL
);
1553 Callback function executed when the EndOfDxe event group is signaled.
1555 @param[in] Event Event whose notification function is being invoked.
1556 @param[in] Context The pointer to the notification function's context, which
1557 is implementation-dependent.
1561 DxeCapsuleLibEndOfDxe (
1566 mDxeCapsuleLibEndOfDxe
= TRUE
;
1570 The constructor function.
1572 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1573 @param[in] SystemTable A pointer to the EFI System Table.
1575 @retval EFI_SUCCESS The constructor successfully .
1579 DxeCapsuleLibConstructor (
1580 IN EFI_HANDLE ImageHandle
,
1581 IN EFI_SYSTEM_TABLE
*SystemTable
1586 Status
= gBS
->CreateEventEx (
1589 DxeCapsuleLibEndOfDxe
,
1591 &gEfiEndOfDxeEventGroupGuid
,
1592 &mDxeCapsuleLibEndOfDxeEvent
1594 ASSERT_EFI_ERROR (Status
);
1596 InitCapsuleVariable();
1602 The destructor function closes the End of DXE event.
1604 @param ImageHandle The firmware allocated handle for the EFI image.
1605 @param SystemTable A pointer to the EFI System Table.
1607 @retval EFI_SUCCESS The destructor completed successfully.
1611 DxeCapsuleLibDestructor (
1612 IN EFI_HANDLE ImageHandle
,
1613 IN EFI_SYSTEM_TABLE
*SystemTable
1619 // Close the End of DXE event.
1621 Status
= gBS
->CloseEvent (mDxeCapsuleLibEndOfDxeEvent
);
1622 ASSERT_EFI_ERROR (Status
);