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(), DisplayCapsuleImage(), ConvertBmpToGopBlt() will
11 receive untrusted input and do basic validation.
13 Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
14 This program and the accompanying materials
15 are licensed and made available under the terms and conditions of the BSD License
16 which accompanies this distribution. The full text of the license may be found at
17 http://opensource.org/licenses/bsd-license.php
19 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
20 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
26 #include <IndustryStandard/Bmp.h>
27 #include <IndustryStandard/WindowsUxCapsule.h>
29 #include <Guid/FmpCapsule.h>
30 #include <Guid/SystemResourceTable.h>
31 #include <Guid/EventGroup.h>
33 #include <Library/BaseLib.h>
34 #include <Library/DebugLib.h>
35 #include <Library/BaseMemoryLib.h>
36 #include <Library/DxeServicesTableLib.h>
37 #include <Library/UefiBootServicesTableLib.h>
38 #include <Library/UefiRuntimeServicesTableLib.h>
39 #include <Library/MemoryAllocationLib.h>
40 #include <Library/CapsuleLib.h>
41 #include <Library/DevicePathLib.h>
42 #include <Library/UefiLib.h>
43 #include <Library/PcdLib.h>
45 #include <Protocol/GraphicsOutput.h>
46 #include <Protocol/EsrtManagement.h>
47 #include <Protocol/FirmwareManagement.h>
48 #include <Protocol/DevicePath.h>
50 EFI_SYSTEM_RESOURCE_TABLE
*mEsrtTable
= NULL
;
51 BOOLEAN mIsVirtualAddrConverted
= FALSE
;
52 BOOLEAN mDxeCapsuleLibEndOfDxe
= FALSE
;
55 Initialize capsule related variables.
63 Record capsule status variable.
65 @param[in] CapsuleHeader The capsule image header
66 @param[in] CapsuleStatus The capsule process stauts
68 @retval EFI_SUCCESS The capsule status variable is recorded.
69 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
72 RecordCapsuleStatusVariable (
73 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
74 IN EFI_STATUS CapsuleStatus
78 Record FMP capsule status variable.
80 @param[in] CapsuleHeader The capsule image header
81 @param[in] CapsuleStatus The capsule process stauts
82 @param[in] PayloadIndex FMP payload index
83 @param[in] ImageHeader FMP image header
84 @param[in] FmpDevicePath DevicePath associated with the FMP producer
86 @retval EFI_SUCCESS The capsule status variable is recorded.
87 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
90 RecordFmpCapsuleStatusVariable (
91 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
92 IN EFI_STATUS CapsuleStatus
,
93 IN UINTN PayloadIndex
,
94 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
,
95 IN EFI_DEVICE_PATH_PROTOCOL
*FmpDevicePath 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 completion progress of the firmware update
104 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
108 Update_Image_Progress (
116 Return if this CapsuleGuid is a FMP capsule GUID or not.
118 @param[in] CapsuleGuid A pointer to EFI_GUID
120 @retval TRUE It is a FMP capsule GUID.
121 @retval FALSE It is not a FMP capsule GUID.
125 IN EFI_GUID
*CapsuleGuid
128 if (CompareGuid(&gEfiFmpCapsuleGuid
, CapsuleGuid
)) {
136 Validate if it is valid capsule header
138 Caution: This function may receive untrusted input.
140 This function assumes the caller provided correct CapsuleHeader pointer
143 This function validates the fields in EFI_CAPSULE_HEADER.
145 @param[in] CapsuleHeader Points to a capsule header.
146 @param[in] CapsuleSize Size of the whole capsule image.
150 IsValidCapsuleHeader (
151 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
152 IN UINT64 CapsuleSize
155 if (CapsuleHeader
->CapsuleImageSize
!= CapsuleSize
) {
158 if (CapsuleHeader
->HeaderSize
>= CapsuleHeader
->CapsuleImageSize
) {
165 Validate Fmp capsules layout.
167 Caution: This function may receive untrusted input.
169 This function assumes the caller validated the capsule by using
170 IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.
171 The capsule buffer size is CapsuleHeader->CapsuleImageSize.
173 This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
174 and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
176 This function need support nested FMP capsule.
178 @param[in] CapsuleHeader Points to a capsule header.
179 @param[out] EmbeddedDriverCount The EmbeddedDriverCount in the FMP capsule.
181 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
182 @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.
186 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
187 OUT UINT16
*EmbeddedDriverCount OPTIONAL
190 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
192 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
194 UINT64
*ItemOffsetList
;
197 UINTN FmpCapsuleSize
;
198 UINTN FmpCapsuleHeaderSize
;
200 UINTN FmpImageHeaderSize
;
202 if (!IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
203 return ValidateFmpCapsule ((EFI_CAPSULE_HEADER
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
), EmbeddedDriverCount
);
206 if (CapsuleHeader
->HeaderSize
>= CapsuleHeader
->CapsuleImageSize
) {
207 DEBUG((DEBUG_ERROR
, "HeaderSize(0x%x) >= CapsuleImageSize(0x%x)\n", CapsuleHeader
->HeaderSize
, CapsuleHeader
->CapsuleImageSize
));
208 return EFI_INVALID_PARAMETER
;
211 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
212 EndOfCapsule
= (UINT8
*) CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
;
213 FmpCapsuleSize
= (UINTN
)EndOfCapsule
- (UINTN
)FmpCapsuleHeader
;
215 if (FmpCapsuleSize
< sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
)) {
216 DEBUG((DEBUG_ERROR
, "FmpCapsuleSize(0x%x) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\n", FmpCapsuleSize
));
217 return EFI_INVALID_PARAMETER
;
220 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
221 if (FmpCapsuleHeader
->Version
!= EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
222 DEBUG((DEBUG_ERROR
, "FmpCapsuleHeader->Version(0x%x) != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION\n", FmpCapsuleHeader
->Version
));
223 return EFI_INVALID_PARAMETER
;
225 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
228 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
230 if ((FmpCapsuleSize
- sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
))/sizeof(UINT64
) < ItemNum
) {
231 DEBUG((DEBUG_ERROR
, "ItemNum(0x%x) too big\n", ItemNum
));
232 return EFI_INVALID_PARAMETER
;
234 FmpCapsuleHeaderSize
= sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
) + sizeof(UINT64
)*ItemNum
;
236 // Check ItemOffsetList
237 for (Index
= 0; Index
< ItemNum
; Index
++) {
238 if (ItemOffsetList
[Index
] >= FmpCapsuleSize
) {
239 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) >= FmpCapsuleSize(0x%x)\n", Index
, ItemOffsetList
[Index
], FmpCapsuleSize
));
240 return EFI_INVALID_PARAMETER
;
242 if (ItemOffsetList
[Index
] < FmpCapsuleHeaderSize
) {
243 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) < FmpCapsuleHeaderSize(0x%x)\n", Index
, ItemOffsetList
[Index
], FmpCapsuleHeaderSize
));
244 return EFI_INVALID_PARAMETER
;
247 // All the address in ItemOffsetList must be stored in ascending order
250 if (ItemOffsetList
[Index
] <= ItemOffsetList
[Index
- 1]) {
251 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) < ItemOffsetList[%d](0x%x)\n", Index
, ItemOffsetList
[Index
], Index
, ItemOffsetList
[Index
- 1]));
252 return EFI_INVALID_PARAMETER
;
257 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
258 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
259 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
260 if (Index
== ItemNum
- 1) {
261 EndOfPayload
= (UINT8
*)((UINTN
)EndOfCapsule
- (UINTN
)FmpCapsuleHeader
);
263 EndOfPayload
= (UINT8
*)(UINTN
)ItemOffsetList
[Index
+1];
265 FmpImageSize
= (UINTN
)EndOfPayload
- ItemOffsetList
[Index
];
267 if (FmpImageSize
< OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
)) {
268 DEBUG((DEBUG_ERROR
, "FmpImageSize(0x%lx) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER\n", FmpImageSize
));
269 return EFI_INVALID_PARAMETER
;
271 FmpImageHeaderSize
= sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
);
272 if ((ImageHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) ||
273 (ImageHeader
->Version
< 1)) {
274 DEBUG((DEBUG_ERROR
, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader
->Version
));
275 return EFI_INVALID_PARAMETER
;
277 if (ImageHeader
->Version
< EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
278 FmpImageHeaderSize
= OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
282 if (FmpImageSize
!= (UINT64
)FmpImageHeaderSize
+ (UINT64
)ImageHeader
->UpdateImageSize
+ (UINT64
)ImageHeader
->UpdateVendorCodeSize
) {
283 DEBUG((DEBUG_ERROR
, "FmpImageSize(0x%lx) mismatch, UpdateImageSize(0x%x) UpdateVendorCodeSize(0x%x)\n", FmpImageSize
, ImageHeader
->UpdateImageSize
, ImageHeader
->UpdateVendorCodeSize
));
284 return EFI_INVALID_PARAMETER
;
290 // No driver & payload element in FMP
292 EndOfPayload
= (UINT8
*)(FmpCapsuleHeader
+ 1);
293 if (EndOfPayload
!= EndOfCapsule
) {
294 DEBUG((DEBUG_ERROR
, "EndOfPayload(0x%x) mismatch, EndOfCapsule(0x%x)\n", EndOfPayload
, EndOfCapsule
));
295 return EFI_INVALID_PARAMETER
;
297 return EFI_UNSUPPORTED
;
300 if (EmbeddedDriverCount
!= NULL
) {
301 *EmbeddedDriverCount
= FmpCapsuleHeader
->EmbeddedDriverCount
;
308 Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
309 is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
310 buffer is passed in it will be used if it is big enough.
312 Caution: This function may receive untrusted input.
314 @param[in] BmpImage Pointer to BMP file
315 @param[in] BmpImageSize Number of bytes in BmpImage
316 @param[in, out] GopBlt Buffer containing GOP version of BmpImage.
317 @param[in, out] GopBltSize Size of GopBlt in bytes.
318 @param[out] PixelHeight Height of GopBlt/BmpImage in pixels
319 @param[out] PixelWidth Width of GopBlt/BmpImage in pixels
321 @retval EFI_SUCCESS GopBlt and GopBltSize are returned.
322 @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image
323 @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.
324 GopBltSize will contain the required size.
325 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.
332 IN UINTN BmpImageSize
,
333 IN OUT VOID
**GopBlt
,
334 IN OUT UINTN
*GopBltSize
,
335 OUT UINTN
*PixelHeight
,
336 OUT UINTN
*PixelWidth
341 BMP_IMAGE_HEADER
*BmpHeader
;
342 BMP_COLOR_MAP
*BmpColorMap
;
343 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
;
344 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
345 UINT64 BltBufferSize
;
350 UINT32 DataSizePerLine
;
354 if (sizeof (BMP_IMAGE_HEADER
) > BmpImageSize
) {
355 return EFI_INVALID_PARAMETER
;
358 BmpHeader
= (BMP_IMAGE_HEADER
*) BmpImage
;
360 if (BmpHeader
->CharB
!= 'B' || BmpHeader
->CharM
!= 'M') {
361 return EFI_UNSUPPORTED
;
365 // Doesn't support compress.
367 if (BmpHeader
->CompressionType
!= 0) {
368 return EFI_UNSUPPORTED
;
372 // Only support BITMAPINFOHEADER format.
373 // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER
375 if (BmpHeader
->HeaderSize
!= sizeof (BMP_IMAGE_HEADER
) - OFFSET_OF(BMP_IMAGE_HEADER
, HeaderSize
)) {
376 return EFI_UNSUPPORTED
;
380 // The data size in each line must be 4 byte alignment.
382 DataSizePerLine
= ((BmpHeader
->PixelWidth
* BmpHeader
->BitPerPixel
+ 31) >> 3) & (~0x3);
383 BltBufferSize
= MultU64x32 (DataSizePerLine
, BmpHeader
->PixelHeight
);
384 if (BltBufferSize
> (UINT32
) ~0) {
385 return EFI_INVALID_PARAMETER
;
388 if ((BmpHeader
->Size
!= BmpImageSize
) ||
389 (BmpHeader
->Size
< BmpHeader
->ImageOffset
) ||
390 (BmpHeader
->Size
- BmpHeader
->ImageOffset
!= BmpHeader
->PixelHeight
* DataSizePerLine
)) {
391 return EFI_INVALID_PARAMETER
;
395 // Calculate Color Map offset in the image.
398 BmpColorMap
= (BMP_COLOR_MAP
*) (Image
+ sizeof (BMP_IMAGE_HEADER
));
399 if (BmpHeader
->ImageOffset
< sizeof (BMP_IMAGE_HEADER
)) {
400 return EFI_INVALID_PARAMETER
;
403 if (BmpHeader
->ImageOffset
> sizeof (BMP_IMAGE_HEADER
)) {
404 switch (BmpHeader
->BitPerPixel
) {
419 // BMP file may has padding data between the bmp header section and the bmp data section.
421 if (BmpHeader
->ImageOffset
- sizeof (BMP_IMAGE_HEADER
) < sizeof (BMP_COLOR_MAP
) * ColorMapNum
) {
422 return EFI_INVALID_PARAMETER
;
427 // Calculate graphics image data address in the image
429 Image
= ((UINT8
*) BmpImage
) + BmpHeader
->ImageOffset
;
433 // Calculate the BltBuffer needed size.
435 BltBufferSize
= MultU64x32 ((UINT64
) BmpHeader
->PixelWidth
, BmpHeader
->PixelHeight
);
437 // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
439 if (BltBufferSize
> DivU64x32 ((UINTN
) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
))) {
440 return EFI_UNSUPPORTED
;
442 BltBufferSize
= MultU64x32 (BltBufferSize
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
445 if (*GopBlt
== NULL
) {
447 // GopBlt is not allocated by caller.
449 *GopBltSize
= (UINTN
) BltBufferSize
;
450 *GopBlt
= AllocatePool (*GopBltSize
);
452 if (*GopBlt
== NULL
) {
453 return EFI_OUT_OF_RESOURCES
;
457 // GopBlt has been allocated by caller.
459 if (*GopBltSize
< (UINTN
) BltBufferSize
) {
460 *GopBltSize
= (UINTN
) BltBufferSize
;
461 return EFI_BUFFER_TOO_SMALL
;
465 *PixelWidth
= BmpHeader
->PixelWidth
;
466 *PixelHeight
= BmpHeader
->PixelHeight
;
469 // Convert image from BMP to Blt buffer format
472 for (Height
= 0; Height
< BmpHeader
->PixelHeight
; Height
++) {
473 Blt
= &BltBuffer
[(BmpHeader
->PixelHeight
- Height
- 1) * BmpHeader
->PixelWidth
];
474 for (Width
= 0; Width
< BmpHeader
->PixelWidth
; Width
++, Image
++, Blt
++) {
475 switch (BmpHeader
->BitPerPixel
) {
478 // Convert 1-bit (2 colors) BMP to 24-bit color
480 for (Index
= 0; Index
< 8 && Width
< BmpHeader
->PixelWidth
; Index
++) {
481 Blt
->Red
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Red
;
482 Blt
->Green
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Green
;
483 Blt
->Blue
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Blue
;
494 // Convert 4-bit (16 colors) BMP Palette to 24-bit color
496 Index
= (*Image
) >> 4;
497 Blt
->Red
= BmpColorMap
[Index
].Red
;
498 Blt
->Green
= BmpColorMap
[Index
].Green
;
499 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
500 if (Width
< (BmpHeader
->PixelWidth
- 1)) {
503 Index
= (*Image
) & 0x0f;
504 Blt
->Red
= BmpColorMap
[Index
].Red
;
505 Blt
->Green
= BmpColorMap
[Index
].Green
;
506 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
512 // Convert 8-bit (256 colors) BMP Palette to 24-bit color
514 Blt
->Red
= BmpColorMap
[*Image
].Red
;
515 Blt
->Green
= BmpColorMap
[*Image
].Green
;
516 Blt
->Blue
= BmpColorMap
[*Image
].Blue
;
523 Blt
->Blue
= *Image
++;
524 Blt
->Green
= *Image
++;
530 // it is 32-bit BMP. Skip pixel's highest byte
532 Blt
->Blue
= *Image
++;
533 Blt
->Green
= *Image
++;
539 // Other bit format BMP is not supported.
545 return EFI_UNSUPPORTED
;
550 ImageIndex
= (UINTN
) Image
- (UINTN
) ImageHeader
;
551 if ((ImageIndex
% 4) != 0) {
553 // Bmp Image starts each row on a 32-bit boundary!
555 Image
= Image
+ (4 - (ImageIndex
% 4));
564 Those capsules supported by the firmwares.
566 Caution: This function may receive untrusted input.
568 @param[in] CapsuleHeader Points to a capsule header.
570 @retval EFI_SUCESS Input capsule is supported by firmware.
571 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
574 DisplayCapsuleImage (
575 IN EFI_CAPSULE_HEADER
*CapsuleHeader
578 DISPLAY_DISPLAY_PAYLOAD
*ImagePayload
;
581 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
585 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
587 ImagePayload
= (DISPLAY_DISPLAY_PAYLOAD
*)(CapsuleHeader
+ 1);
588 PayloadSize
= CapsuleHeader
->CapsuleImageSize
- sizeof(EFI_CAPSULE_HEADER
);
590 if (ImagePayload
->Version
!= 1) {
591 return EFI_UNSUPPORTED
;
593 if (CalculateCheckSum8((UINT8
*)CapsuleHeader
, CapsuleHeader
->CapsuleImageSize
) != 0) {
594 return EFI_UNSUPPORTED
;
597 // Only Support Bitmap by now
599 if (ImagePayload
->ImageType
!= 0) {
600 return EFI_UNSUPPORTED
;
606 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**)&GraphicsOutput
);
607 if (EFI_ERROR (Status
)) {
608 Status
= gBS
->LocateProtocol(&gEfiGraphicsOutputProtocolGuid
, NULL
, (VOID
**)&GraphicsOutput
);
609 if (EFI_ERROR(Status
)) {
610 return EFI_UNSUPPORTED
;
614 if (GraphicsOutput
->Mode
->Mode
!= ImagePayload
->Mode
) {
615 return EFI_UNSUPPORTED
;
621 Status
= ConvertBmpToGopBlt (
623 PayloadSize
- sizeof(DISPLAY_DISPLAY_PAYLOAD
),
630 if (EFI_ERROR (Status
)) {
634 Status
= GraphicsOutput
->Blt (
640 (UINTN
) ImagePayload
->OffsetX
,
641 (UINTN
) ImagePayload
->OffsetY
,
644 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
653 Dump FMP information.
655 @param[in] ImageInfoSize The size of ImageInfo, in bytes.
656 @param[in] ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
657 @param[in] DescriptorVersion The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
658 @param[in] DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
659 @param[in] DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
660 @param[in] PackageVersion The version of package.
661 @param[in] PackageVersionName The version name of package.
665 IN UINTN ImageInfoSize
,
666 IN EFI_FIRMWARE_IMAGE_DESCRIPTOR
*ImageInfo
,
667 IN UINT32 DescriptorVersion
,
668 IN UINT8 DescriptorCount
,
669 IN UINTN DescriptorSize
,
670 IN UINT32 PackageVersion
,
671 IN CHAR16
*PackageVersionName
674 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*CurrentImageInfo
;
677 DEBUG((DEBUG_VERBOSE
, " DescriptorVersion - 0x%x\n", DescriptorVersion
));
678 DEBUG((DEBUG_VERBOSE
, " DescriptorCount - 0x%x\n", DescriptorCount
));
679 DEBUG((DEBUG_VERBOSE
, " DescriptorSize - 0x%x\n", DescriptorSize
));
680 DEBUG((DEBUG_VERBOSE
, " PackageVersion - 0x%x\n", PackageVersion
));
681 DEBUG((DEBUG_VERBOSE
, " PackageVersionName - %s\n\n", PackageVersionName
));
682 CurrentImageInfo
= ImageInfo
;
683 for (Index
= 0; Index
< DescriptorCount
; Index
++) {
684 DEBUG((DEBUG_VERBOSE
, " ImageDescriptor (%d)\n", Index
));
685 DEBUG((DEBUG_VERBOSE
, " ImageIndex - 0x%x\n", CurrentImageInfo
->ImageIndex
));
686 DEBUG((DEBUG_VERBOSE
, " ImageTypeId - %g\n", &CurrentImageInfo
->ImageTypeId
));
687 DEBUG((DEBUG_VERBOSE
, " ImageId - 0x%lx\n", CurrentImageInfo
->ImageId
));
688 DEBUG((DEBUG_VERBOSE
, " ImageIdName - %s\n", CurrentImageInfo
->ImageIdName
));
689 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", CurrentImageInfo
->Version
));
690 DEBUG((DEBUG_VERBOSE
, " VersionName - %s\n", CurrentImageInfo
->VersionName
));
691 DEBUG((DEBUG_VERBOSE
, " Size - 0x%x\n", CurrentImageInfo
->Size
));
692 DEBUG((DEBUG_VERBOSE
, " AttributesSupported - 0x%lx\n", CurrentImageInfo
->AttributesSupported
));
693 DEBUG((DEBUG_VERBOSE
, " AttributesSetting - 0x%lx\n", CurrentImageInfo
->AttributesSetting
));
694 DEBUG((DEBUG_VERBOSE
, " Compatibilities - 0x%lx\n", CurrentImageInfo
->Compatibilities
));
695 if (DescriptorVersion
> 1) {
696 DEBUG((DEBUG_VERBOSE
, " LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo
->LowestSupportedImageVersion
));
697 if (DescriptorVersion
> 2) {
698 DEBUG((DEBUG_VERBOSE
, " LastAttemptVersion - 0x%x\n", CurrentImageInfo
->LastAttemptVersion
));
699 DEBUG((DEBUG_VERBOSE
, " LastAttemptStatus - 0x%x\n", CurrentImageInfo
->LastAttemptStatus
));
700 DEBUG((DEBUG_VERBOSE
, " HardwareInstance - 0x%lx\n", CurrentImageInfo
->HardwareInstance
));
704 // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
706 CurrentImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)CurrentImageInfo
+ DescriptorSize
);
711 Dump a non-nested FMP capsule.
713 @param[in] CapsuleHeader A pointer to CapsuleHeader
717 IN EFI_CAPSULE_HEADER
*CapsuleHeader
720 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
721 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
723 UINT64
*ItemOffsetList
;
725 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
727 DEBUG((DEBUG_VERBOSE
, "FmpCapsule:\n"));
728 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", FmpCapsuleHeader
->Version
));
729 DEBUG((DEBUG_VERBOSE
, " EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader
->EmbeddedDriverCount
));
730 DEBUG((DEBUG_VERBOSE
, " PayloadItemCount - 0x%x\n", FmpCapsuleHeader
->PayloadItemCount
));
732 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
733 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
734 DEBUG((DEBUG_VERBOSE
, " ItemOffsetList[%d] - 0x%lx\n", Index
, ItemOffsetList
[Index
]));
736 for (; Index
< (UINT32
)FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
; Index
++) {
737 DEBUG((DEBUG_VERBOSE
, " ItemOffsetList[%d] - 0x%lx\n", Index
, ItemOffsetList
[Index
]));
738 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
740 DEBUG((DEBUG_VERBOSE
, " ImageHeader:\n"));
741 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", ImageHeader
->Version
));
742 DEBUG((DEBUG_VERBOSE
, " UpdateImageTypeId - %g\n", &ImageHeader
->UpdateImageTypeId
));
743 DEBUG((DEBUG_VERBOSE
, " UpdateImageIndex - 0x%x\n", ImageHeader
->UpdateImageIndex
));
744 DEBUG((DEBUG_VERBOSE
, " UpdateImageSize - 0x%x\n", ImageHeader
->UpdateImageSize
));
745 DEBUG((DEBUG_VERBOSE
, " UpdateVendorCodeSize - 0x%x\n", ImageHeader
->UpdateVendorCodeSize
));
746 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
747 DEBUG((DEBUG_VERBOSE
, " UpdateHardwareInstance - 0x%lx\n", ImageHeader
->UpdateHardwareInstance
));
753 Dump all FMP information.
761 EFI_HANDLE
*HandleBuffer
;
762 UINTN NumberOfHandles
;
763 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
766 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
767 UINT32 FmpImageInfoDescriptorVer
;
768 UINT8 FmpImageInfoCount
;
769 UINTN DescriptorSize
;
770 UINT32 PackageVersion
;
771 CHAR16
*PackageVersionName
;
773 Status
= gBS
->LocateHandleBuffer (
775 &gEfiFirmwareManagementProtocolGuid
,
780 if (EFI_ERROR(Status
)) {
784 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
785 Status
= gBS
->HandleProtocol(
787 &gEfiFirmwareManagementProtocolGuid
,
790 if (EFI_ERROR(Status
)) {
795 Status
= Fmp
->GetImageInfo (
805 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
809 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
810 if (FmpImageInfoBuf
== NULL
) {
814 PackageVersionName
= NULL
;
815 Status
= Fmp
->GetImageInfo (
817 &ImageInfoSize
, // ImageInfoSize
818 FmpImageInfoBuf
, // ImageInfo
819 &FmpImageInfoDescriptorVer
, // DescriptorVersion
820 &FmpImageInfoCount
, // DescriptorCount
821 &DescriptorSize
, // DescriptorSize
822 &PackageVersion
, // PackageVersion
823 &PackageVersionName
// PackageVersionName
825 if (EFI_ERROR(Status
)) {
826 FreePool(FmpImageInfoBuf
);
830 DEBUG((DEBUG_INFO
, "FMP (%d) ImageInfo:\n", Index
));
832 ImageInfoSize
, // ImageInfoSize
833 FmpImageInfoBuf
, // ImageInfo
834 FmpImageInfoDescriptorVer
, // DescriptorVersion
835 FmpImageInfoCount
, // DescriptorCount
836 DescriptorSize
, // DescriptorSize
837 PackageVersion
, // PackageVersion
838 PackageVersionName
// PackageVersionName
841 if (PackageVersionName
!= NULL
) {
842 FreePool(PackageVersionName
);
845 FreePool(FmpImageInfoBuf
);
852 Get FMP handle by ImageTypeId and HardwareInstance.
854 @param[in] UpdateImageTypeId Used to identify device firmware targeted by this update.
855 @param[in] UpdateHardwareInstance The HardwareInstance to target with this update.
856 @param[in,out] NoHandles The number of handles returned in Buffer.
857 @param[out] Buffer[out] A pointer to the buffer to return the requested array of handles.
859 @retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of
860 handles in Buffer was returned in NoHandles.
861 @retval EFI_NOT_FOUND No handles match the search.
862 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
865 GetFmpHandleBufferByType (
866 IN EFI_GUID
*UpdateImageTypeId
,
867 IN UINT64 UpdateHardwareInstance
,
868 IN OUT UINTN
*NoHandles
,
869 OUT EFI_HANDLE
**Buffer
873 EFI_HANDLE
*HandleBuffer
;
874 UINTN NumberOfHandles
;
875 EFI_HANDLE
*MatchedHandleBuffer
;
876 UINTN MatchedNumberOfHandles
;
877 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
880 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
881 UINT32 FmpImageInfoDescriptorVer
;
882 UINT8 FmpImageInfoCount
;
883 UINTN DescriptorSize
;
884 UINT32 PackageVersion
;
885 CHAR16
*PackageVersionName
;
887 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*TempFmpImageInfo
;
892 Status
= gBS
->LocateHandleBuffer (
894 &gEfiFirmwareManagementProtocolGuid
,
899 if (EFI_ERROR(Status
)) {
903 MatchedNumberOfHandles
= 0;
904 MatchedHandleBuffer
= AllocateZeroPool (sizeof(EFI_HANDLE
) * NumberOfHandles
);
905 if (MatchedHandleBuffer
== NULL
) {
906 FreePool (HandleBuffer
);
907 return EFI_OUT_OF_RESOURCES
;
910 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
911 Status
= gBS
->HandleProtocol(
913 &gEfiFirmwareManagementProtocolGuid
,
916 if (EFI_ERROR(Status
)) {
921 Status
= Fmp
->GetImageInfo (
931 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
935 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
936 if (FmpImageInfoBuf
== NULL
) {
940 PackageVersionName
= NULL
;
941 Status
= Fmp
->GetImageInfo (
943 &ImageInfoSize
, // ImageInfoSize
944 FmpImageInfoBuf
, // ImageInfo
945 &FmpImageInfoDescriptorVer
, // DescriptorVersion
946 &FmpImageInfoCount
, // DescriptorCount
947 &DescriptorSize
, // DescriptorSize
948 &PackageVersion
, // PackageVersion
949 &PackageVersionName
// PackageVersionName
951 if (EFI_ERROR(Status
)) {
952 FreePool(FmpImageInfoBuf
);
956 if (PackageVersionName
!= NULL
) {
957 FreePool(PackageVersionName
);
960 TempFmpImageInfo
= FmpImageInfoBuf
;
961 for (Index2
= 0; Index2
< FmpImageInfoCount
; Index2
++) {
963 // Check if this FMP instance matches
965 if (CompareGuid(UpdateImageTypeId
, &TempFmpImageInfo
->ImageTypeId
)) {
966 if ((UpdateHardwareInstance
== 0) ||
967 ((FmpImageInfoDescriptorVer
>= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
) &&
968 (UpdateHardwareInstance
== TempFmpImageInfo
->HardwareInstance
))) {
969 MatchedHandleBuffer
[MatchedNumberOfHandles
] = HandleBuffer
[Index
];
970 MatchedNumberOfHandles
++;
974 TempFmpImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)TempFmpImageInfo
+ DescriptorSize
);
976 FreePool(FmpImageInfoBuf
);
979 if (MatchedNumberOfHandles
== 0) {
980 return EFI_NOT_FOUND
;
983 *NoHandles
= MatchedNumberOfHandles
;
984 *Buffer
= MatchedHandleBuffer
;
990 Return FmpImageInfoDescriptorVer by an FMP handle.
992 @param[in] Handle A FMP handle.
994 @return FmpImageInfoDescriptorVer associated with the FMP.
997 GetFmpImageInfoDescriptorVer (
1002 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
1003 UINTN ImageInfoSize
;
1004 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
1005 UINT32 FmpImageInfoDescriptorVer
;
1006 UINT8 FmpImageInfoCount
;
1007 UINTN DescriptorSize
;
1008 UINT32 PackageVersion
;
1009 CHAR16
*PackageVersionName
;
1011 Status
= gBS
->HandleProtocol(
1013 &gEfiFirmwareManagementProtocolGuid
,
1016 if (EFI_ERROR(Status
)) {
1021 Status
= Fmp
->GetImageInfo (
1031 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1035 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
1036 if (FmpImageInfoBuf
== NULL
) {
1040 PackageVersionName
= NULL
;
1041 Status
= Fmp
->GetImageInfo (
1043 &ImageInfoSize
, // ImageInfoSize
1044 FmpImageInfoBuf
, // ImageInfo
1045 &FmpImageInfoDescriptorVer
, // DescriptorVersion
1046 &FmpImageInfoCount
, // DescriptorCount
1047 &DescriptorSize
, // DescriptorSize
1048 &PackageVersion
, // PackageVersion
1049 &PackageVersionName
// PackageVersionName
1051 if (EFI_ERROR(Status
)) {
1052 FreePool(FmpImageInfoBuf
);
1055 return FmpImageInfoDescriptorVer
;
1061 @param[in] Handle A FMP handle.
1062 @param[in] ImageHeader The payload image header.
1063 @param[in] PayloadIndex The index of the payload.
1065 @return The status of FMP->SetImage.
1069 IN EFI_HANDLE Handle
,
1070 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
,
1071 IN UINTN PayloadIndex
1075 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
1078 CHAR16
*AbortReason
;
1080 Status
= gBS
->HandleProtocol(
1082 &gEfiFirmwareManagementProtocolGuid
,
1085 if (EFI_ERROR(Status
)) {
1089 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
1090 Image
= (UINT8
*)(ImageHeader
+ 1);
1093 // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1,
1094 // Header should exclude UpdateHardwareInstance field
1096 Image
= (UINT8
*)ImageHeader
+ OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
1099 if (ImageHeader
->UpdateVendorCodeSize
== 0) {
1102 VendorCode
= Image
+ ImageHeader
->UpdateImageSize
;
1105 DEBUG((DEBUG_INFO
, "Fmp->SetImage ...\n"));
1106 DEBUG((DEBUG_INFO
, "ImageTypeId - %g, ", &ImageHeader
->UpdateImageTypeId
));
1107 DEBUG((DEBUG_INFO
, "PayloadIndex - 0x%x, ", PayloadIndex
));
1108 DEBUG((DEBUG_INFO
, "ImageIndex - 0x%x ", ImageHeader
->UpdateImageIndex
));
1109 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
1110 DEBUG((DEBUG_INFO
, "(UpdateHardwareInstance - 0x%x)", ImageHeader
->UpdateHardwareInstance
));
1112 DEBUG((DEBUG_INFO
, "\n"));
1113 Status
= Fmp
->SetImage(
1115 ImageHeader
->UpdateImageIndex
, // ImageIndex
1117 ImageHeader
->UpdateImageSize
, // ImageSize
1118 VendorCode
, // VendorCode
1119 Update_Image_Progress
, // Progress
1120 &AbortReason
// AbortReason
1122 DEBUG((DEBUG_INFO
, "Fmp->SetImage - %r\n", Status
));
1123 if (AbortReason
!= NULL
) {
1124 DEBUG ((DEBUG_ERROR
, "%s\n", AbortReason
));
1125 FreePool(AbortReason
);
1132 Start a UEFI image in the FMP payload.
1134 @param[in] ImageBuffer A pointer to the memory location containing a copy of the image to be loaded..
1135 @param[in] ImageSize The size in bytes of ImageBuffer.
1137 @return The status of gBS->LoadImage and gBS->StartImage.
1141 IN VOID
*ImageBuffer
,
1145 MEMMAP_DEVICE_PATH MemMapNode
;
1147 EFI_HANDLE ImageHandle
;
1148 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
1151 SetDevicePathNodeLength (&MemMapNode
.Header
, sizeof (MemMapNode
));
1152 MemMapNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
1153 MemMapNode
.Header
.SubType
= HW_MEMMAP_DP
;
1154 MemMapNode
.MemoryType
= EfiBootServicesCode
;
1155 MemMapNode
.StartingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)ImageBuffer
;
1156 MemMapNode
.EndingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)((UINT8
*)ImageBuffer
+ ImageSize
- 1);
1158 DriverDevicePath
= AppendDevicePathNode (NULL
, &MemMapNode
.Header
);
1159 if (DriverDevicePath
== NULL
) {
1160 return EFI_OUT_OF_RESOURCES
;
1163 DEBUG((DEBUG_INFO
, "FmpCapsule: LoadImage ...\n"));
1164 Status
= gBS
->LoadImage(
1172 DEBUG((DEBUG_INFO
, "FmpCapsule: LoadImage - %r\n", Status
));
1173 if (EFI_ERROR(Status
)) {
1174 FreePool(DriverDevicePath
);
1178 DEBUG((DEBUG_INFO
, "FmpCapsule: StartImage ...\n"));
1179 Status
= gBS
->StartImage(
1184 DEBUG((DEBUG_INFO
, "FmpCapsule: StartImage - %r\n", Status
));
1185 if (EFI_ERROR(Status
)) {
1186 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
1189 FreePool(DriverDevicePath
);
1194 Record FMP capsule status.
1196 @param[in] Handle A FMP handle.
1197 @param[in] CapsuleHeader The capsule image header
1198 @param[in] CapsuleStatus The capsule process stauts
1199 @param[in] PayloadIndex FMP payload index
1200 @param[in] ImageHeader FMP image header
1203 RecordFmpCapsuleStatus (
1204 IN EFI_HANDLE Handle
, OPTIONAL
1205 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
1206 IN EFI_STATUS CapsuleStatus
,
1207 IN UINTN PayloadIndex
,
1208 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
1212 EFI_DEVICE_PATH_PROTOCOL
*FmpDevicePath
;
1213 UINT32 FmpImageInfoDescriptorVer
;
1214 EFI_STATUS StatusEsrt
;
1215 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
1216 EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry
;
1218 FmpDevicePath
= NULL
;
1219 if (Handle
!= NULL
) {
1220 gBS
->HandleProtocol(
1222 &gEfiDevicePathProtocolGuid
,
1223 (VOID
**)&FmpDevicePath
1227 RecordFmpCapsuleStatusVariable (
1236 // Update corresponding ESRT entry LastAttemp Status
1238 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
1239 if (EFI_ERROR (Status
)) {
1243 if (Handle
== NULL
) {
1248 // Update EsrtEntry For V1, V2 FMP instance.
1249 // V3 FMP ESRT cache will be synced up through EsrtSyncFmp interface
1251 FmpImageInfoDescriptorVer
= GetFmpImageInfoDescriptorVer (Handle
);
1252 if (FmpImageInfoDescriptorVer
< EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
) {
1253 StatusEsrt
= EsrtProtocol
->GetEsrtEntry(&ImageHeader
->UpdateImageTypeId
, &EsrtEntry
);
1254 if (!EFI_ERROR(StatusEsrt
)){
1255 if (!EFI_ERROR(CapsuleStatus
)) {
1256 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_SUCCESS
;
1258 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL
;
1260 EsrtEntry
.LastAttemptVersion
= 0;
1261 EsrtProtocol
->UpdateEsrtEntry(&EsrtEntry
);
1267 Process Firmware management protocol data capsule.
1269 This function assumes the caller validated the capsule by using
1270 ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
1271 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
1272 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
1274 This function need support nested FMP capsule.
1276 @param[in] CapsuleHeader Points to a capsule header.
1278 @retval EFI_SUCESS Process Capsule Image successfully.
1279 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1280 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1281 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1282 @retval EFI_NOT_READY No FMP protocol to handle this FMP capsule.
1285 ProcessFmpCapsuleImage (
1286 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1290 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
1291 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
1292 UINT64
*ItemOffsetList
;
1295 EFI_HANDLE
*HandleBuffer
;
1296 UINTN NumberOfHandles
;
1298 UINT64 UpdateHardwareInstance
;
1303 if (!IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
1304 return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
));
1310 DumpFmpCapsule(CapsuleHeader
);
1312 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
1314 if (FmpCapsuleHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
1315 return EFI_INVALID_PARAMETER
;
1317 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
1319 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
1322 // capsule in which driver count and payload count are both zero is not processed.
1329 // 1. Try to load & start all the drivers within capsule
1331 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
1332 if ((FmpCapsuleHeader
->PayloadItemCount
== 0) &&
1333 (Index
== (UINTN
)FmpCapsuleHeader
->EmbeddedDriverCount
- 1)) {
1335 // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
1337 DriverLen
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
- (UINTN
)ItemOffsetList
[Index
];
1339 DriverLen
= (UINTN
)ItemOffsetList
[Index
+ 1] - (UINTN
)ItemOffsetList
[Index
];
1342 Status
= StartFmpImage (
1343 (UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
],
1346 if (EFI_ERROR(Status
)) {
1347 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
1353 // 2. Route payload to right FMP instance
1355 DEBUG((DEBUG_INFO
, "FmpCapsule: route payload to right FMP instance ...\n"));
1360 // Check all the payload entry in capsule payload list
1362 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
1363 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
1365 UpdateHardwareInstance
= 0;
1366 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
1367 UpdateHardwareInstance
= ImageHeader
->UpdateHardwareInstance
;
1370 Status
= GetFmpHandleBufferByType (
1371 &ImageHeader
->UpdateImageTypeId
,
1372 UpdateHardwareInstance
,
1376 if (EFI_ERROR(Status
)) {
1378 RecordFmpCapsuleStatus (
1382 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1388 for (Index2
= 0; Index2
< NumberOfHandles
; Index2
++) {
1390 RecordFmpCapsuleStatus (
1391 HandleBuffer
[Index2
],
1394 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1400 Status
= SetFmpImageData (
1401 HandleBuffer
[Index2
],
1403 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
1405 if (Status
!= EFI_SUCCESS
) {
1409 RecordFmpCapsuleStatus (
1410 HandleBuffer
[Index2
],
1413 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1417 if (HandleBuffer
!= NULL
) {
1418 FreePool(HandleBuffer
);
1423 return EFI_NOT_READY
;
1427 // always return SUCCESS to indicate this capsule is processed.
1428 // The status of SetImage is recorded in capsule result variable.
1434 Return if there is a FMP header below capsule header.
1436 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1438 @retval TRUE There is a FMP header below capsule header.
1439 @retval FALSE There is not a FMP header below capsule header
1442 IsNestedFmpCapsule (
1443 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1447 EFI_SYSTEM_RESOURCE_TABLE
*Esrt
;
1448 EFI_SYSTEM_RESOURCE_ENTRY
*EsrtEntry
;
1450 BOOLEAN EsrtGuidFound
;
1451 EFI_CAPSULE_HEADER
*NestedCapsuleHeader
;
1452 UINTN NestedCapsuleSize
;
1453 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
1454 EFI_SYSTEM_RESOURCE_ENTRY Entry
;
1456 EsrtGuidFound
= FALSE
;
1459 // Check ESRT protocol
1461 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
1462 if (!EFI_ERROR(Status
)) {
1463 Status
= EsrtProtocol
->GetEsrtEntry(&CapsuleHeader
->CapsuleGuid
, &Entry
);
1464 if (!EFI_ERROR(Status
)) {
1465 EsrtGuidFound
= TRUE
;
1470 // Check ESRT configuration table
1472 if (!EsrtGuidFound
) {
1473 Status
= EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid
, (VOID
**)&Esrt
);
1474 if (!EFI_ERROR(Status
)) {
1475 ASSERT (Esrt
!= NULL
);
1476 EsrtEntry
= (VOID
*)(Esrt
+ 1);
1477 for (Index
= 0; Index
< Esrt
->FwResourceCount
; Index
++, EsrtEntry
++) {
1478 if (CompareGuid(&EsrtEntry
->FwClass
, &CapsuleHeader
->CapsuleGuid
)) {
1479 EsrtGuidFound
= TRUE
;
1485 if (!EsrtGuidFound
) {
1490 // Check nested capsule header
1491 // FMP GUID after ESRT one
1493 NestedCapsuleHeader
= (EFI_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
1494 NestedCapsuleSize
= (UINTN
)CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
- (UINTN
)NestedCapsuleHeader
;
1495 if (NestedCapsuleSize
< sizeof(EFI_CAPSULE_HEADER
)) {
1498 if (!IsValidCapsuleHeader(NestedCapsuleHeader
, NestedCapsuleSize
)) {
1501 if (!IsFmpCapsuleGuid(&NestedCapsuleHeader
->CapsuleGuid
)) {
1504 DEBUG ((DEBUG_INFO
, "IsNestedFmpCapsule\n"));
1509 Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
1511 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1513 @retval TRUE It is a system FMP.
1514 @retval FALSE It is a device FMP.
1518 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1521 if (IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
1524 if (IsNestedFmpCapsule(CapsuleHeader
)) {
1531 Those capsules supported by the firmwares.
1533 Caution: This function may receive untrusted input.
1535 @param[in] CapsuleHeader Points to a capsule header.
1537 @retval EFI_SUCESS Input capsule is supported by firmware.
1538 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
1539 @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
1543 SupportCapsuleImage (
1544 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1548 // check Display Capsule Guid
1550 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1554 if (IsFmpCapsule(CapsuleHeader
)) {
1556 // Check layout of FMP capsule
1558 return ValidateFmpCapsule(CapsuleHeader
, NULL
);
1560 DEBUG((DEBUG_ERROR
, "Unknown Capsule Guid - %g\n", &CapsuleHeader
->CapsuleGuid
));
1561 return EFI_UNSUPPORTED
;
1565 The firmware implements to process the capsule image.
1567 Caution: This function may receive untrusted input.
1569 @param[in] CapsuleHeader Points to a capsule header.
1571 @retval EFI_SUCESS Process Capsule Image successfully.
1572 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1573 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1574 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1578 ProcessCapsuleImage (
1579 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1584 if (SupportCapsuleImage (CapsuleHeader
) != EFI_SUCCESS
) {
1585 RecordCapsuleStatusVariable(CapsuleHeader
, EFI_UNSUPPORTED
);
1586 return EFI_UNSUPPORTED
;
1590 // Display image in firmware update display capsule
1592 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1593 DEBUG((DEBUG_INFO
, "ProcessCapsuleImage for WindowsUxCapsule ...\n"));
1594 Status
= DisplayCapsuleImage(CapsuleHeader
);
1595 RecordCapsuleStatusVariable(CapsuleHeader
, Status
);
1600 // Check FMP capsule layout
1602 if (IsFmpCapsule (CapsuleHeader
)) {
1603 DEBUG((DEBUG_INFO
, "ProcessCapsuleImage for FmpCapsule ...\n"));
1604 DEBUG((DEBUG_INFO
, "ValidateFmpCapsule ...\n"));
1605 Status
= ValidateFmpCapsule(CapsuleHeader
, NULL
);
1606 DEBUG((DEBUG_INFO
, "ValidateFmpCapsule - %r\n", Status
));
1607 if (EFI_ERROR(Status
)) {
1608 RecordCapsuleStatusVariable(CapsuleHeader
, Status
);
1613 // Press EFI FMP Capsule
1615 DEBUG((DEBUG_INFO
, "ProcessFmpCapsuleImage ...\n"));
1616 Status
= ProcessFmpCapsuleImage(CapsuleHeader
);
1617 DEBUG((DEBUG_INFO
, "ProcessFmpCapsuleImage - %r\n", Status
));
1622 return EFI_UNSUPPORTED
;
1626 Callback function executed when the EndOfDxe event group is signaled.
1628 @param[in] Event Event whose notification function is being invoked.
1629 @param[in] Context The pointer to the notification function's context, which
1630 is implementation-dependent.
1634 DxeCapsuleLibEndOfDxe (
1639 mDxeCapsuleLibEndOfDxe
= TRUE
;
1643 The constructor function.
1645 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1646 @param[in] SystemTable A pointer to the EFI System Table.
1648 @retval EFI_SUCCESS The constructor successfully .
1652 DxeCapsuleLibConstructor (
1653 IN EFI_HANDLE ImageHandle
,
1654 IN EFI_SYSTEM_TABLE
*SystemTable
1657 EFI_EVENT EndOfDxeEvent
;
1660 Status
= gBS
->CreateEventEx (
1663 DxeCapsuleLibEndOfDxe
,
1665 &gEfiEndOfDxeEventGroupGuid
,
1668 ASSERT_EFI_ERROR (Status
);
1670 InitCapsuleVariable();