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
;
53 BOOLEAN mDxeCapsuleLibEndOfDxe
= FALSE
;
54 EFI_EVENT mDxeCapsuleLibEndOfDxeEvent
= NULL
;
57 Initialize capsule related variables.
65 Record capsule status variable.
67 @param[in] CapsuleHeader The capsule image header
68 @param[in] CapsuleStatus The capsule process stauts
70 @retval EFI_SUCCESS The capsule status variable is recorded.
71 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
74 RecordCapsuleStatusVariable (
75 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
76 IN EFI_STATUS CapsuleStatus
80 Record FMP capsule status variable.
82 @param[in] CapsuleHeader The capsule image header
83 @param[in] CapsuleStatus The capsule process stauts
84 @param[in] PayloadIndex FMP payload index
85 @param[in] ImageHeader FMP image header
86 @param[in] FmpDevicePath DevicePath associated with the FMP producer
88 @retval EFI_SUCCESS The capsule status variable is recorded.
89 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
92 RecordFmpCapsuleStatusVariable (
93 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
94 IN EFI_STATUS CapsuleStatus
,
95 IN UINTN PayloadIndex
,
96 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
,
97 IN EFI_DEVICE_PATH_PROTOCOL
*FmpDevicePath OPTIONAL
101 Function indicate the current completion progress of the firmware
102 update. Platform may override with own specific progress function.
104 @param[in] Completion A value between 1 and 100 indicating the current completion progress of the firmware update
106 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
110 Update_Image_Progress (
118 Return if this CapsuleGuid is a FMP capsule GUID or not.
120 @param[in] CapsuleGuid A pointer to EFI_GUID
122 @retval TRUE It is a FMP capsule GUID.
123 @retval FALSE It is not a FMP capsule GUID.
127 IN EFI_GUID
*CapsuleGuid
130 if (CompareGuid(&gEfiFmpCapsuleGuid
, CapsuleGuid
)) {
138 Validate if it is valid capsule header
140 Caution: This function may receive untrusted input.
142 This function assumes the caller provided correct CapsuleHeader pointer
145 This function validates the fields in EFI_CAPSULE_HEADER.
147 @param[in] CapsuleHeader Points to a capsule header.
148 @param[in] CapsuleSize Size of the whole capsule image.
152 IsValidCapsuleHeader (
153 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
154 IN UINT64 CapsuleSize
157 if (CapsuleHeader
->CapsuleImageSize
!= CapsuleSize
) {
160 if (CapsuleHeader
->HeaderSize
>= CapsuleHeader
->CapsuleImageSize
) {
167 Validate Fmp capsules layout.
169 Caution: This function may receive untrusted input.
171 This function assumes the caller validated the capsule by using
172 IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.
173 The capsule buffer size is CapsuleHeader->CapsuleImageSize.
175 This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
176 and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
178 This function need support nested FMP capsule.
180 @param[in] CapsuleHeader Points to a capsule header.
181 @param[out] EmbeddedDriverCount The EmbeddedDriverCount in the FMP capsule.
183 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
184 @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.
188 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
189 OUT UINT16
*EmbeddedDriverCount OPTIONAL
192 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
194 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
196 UINT64
*ItemOffsetList
;
199 UINTN FmpCapsuleSize
;
200 UINTN FmpCapsuleHeaderSize
;
202 UINTN FmpImageHeaderSize
;
204 if (!IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
205 return ValidateFmpCapsule ((EFI_CAPSULE_HEADER
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
), EmbeddedDriverCount
);
208 if (CapsuleHeader
->HeaderSize
>= CapsuleHeader
->CapsuleImageSize
) {
209 DEBUG((DEBUG_ERROR
, "HeaderSize(0x%x) >= CapsuleImageSize(0x%x)\n", CapsuleHeader
->HeaderSize
, CapsuleHeader
->CapsuleImageSize
));
210 return EFI_INVALID_PARAMETER
;
213 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
214 EndOfCapsule
= (UINT8
*) CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
;
215 FmpCapsuleSize
= (UINTN
)EndOfCapsule
- (UINTN
)FmpCapsuleHeader
;
217 if (FmpCapsuleSize
< sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
)) {
218 DEBUG((DEBUG_ERROR
, "FmpCapsuleSize(0x%x) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\n", FmpCapsuleSize
));
219 return EFI_INVALID_PARAMETER
;
222 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
223 if (FmpCapsuleHeader
->Version
!= EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
224 DEBUG((DEBUG_ERROR
, "FmpCapsuleHeader->Version(0x%x) != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION\n", FmpCapsuleHeader
->Version
));
225 return EFI_INVALID_PARAMETER
;
227 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
230 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
232 if ((FmpCapsuleSize
- sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
))/sizeof(UINT64
) < ItemNum
) {
233 DEBUG((DEBUG_ERROR
, "ItemNum(0x%x) too big\n", ItemNum
));
234 return EFI_INVALID_PARAMETER
;
236 FmpCapsuleHeaderSize
= sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
) + sizeof(UINT64
)*ItemNum
;
238 // Check ItemOffsetList
239 for (Index
= 0; Index
< ItemNum
; Index
++) {
240 if (ItemOffsetList
[Index
] >= FmpCapsuleSize
) {
241 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) >= FmpCapsuleSize(0x%x)\n", Index
, ItemOffsetList
[Index
], FmpCapsuleSize
));
242 return EFI_INVALID_PARAMETER
;
244 if (ItemOffsetList
[Index
] < FmpCapsuleHeaderSize
) {
245 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) < FmpCapsuleHeaderSize(0x%x)\n", Index
, ItemOffsetList
[Index
], FmpCapsuleHeaderSize
));
246 return EFI_INVALID_PARAMETER
;
249 // All the address in ItemOffsetList must be stored in ascending order
252 if (ItemOffsetList
[Index
] <= ItemOffsetList
[Index
- 1]) {
253 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) < ItemOffsetList[%d](0x%x)\n", Index
, ItemOffsetList
[Index
], Index
, ItemOffsetList
[Index
- 1]));
254 return EFI_INVALID_PARAMETER
;
259 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
260 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
261 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
262 if (Index
== ItemNum
- 1) {
263 EndOfPayload
= (UINT8
*)((UINTN
)EndOfCapsule
- (UINTN
)FmpCapsuleHeader
);
265 EndOfPayload
= (UINT8
*)(UINTN
)ItemOffsetList
[Index
+1];
267 FmpImageSize
= (UINTN
)EndOfPayload
- ItemOffsetList
[Index
];
269 if (FmpImageSize
< OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
)) {
270 DEBUG((DEBUG_ERROR
, "FmpImageSize(0x%lx) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER\n", FmpImageSize
));
271 return EFI_INVALID_PARAMETER
;
273 FmpImageHeaderSize
= sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
);
274 if ((ImageHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) ||
275 (ImageHeader
->Version
< 1)) {
276 DEBUG((DEBUG_ERROR
, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader
->Version
));
277 return EFI_INVALID_PARAMETER
;
279 if (ImageHeader
->Version
< EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
280 FmpImageHeaderSize
= OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
284 if (FmpImageSize
!= (UINT64
)FmpImageHeaderSize
+ (UINT64
)ImageHeader
->UpdateImageSize
+ (UINT64
)ImageHeader
->UpdateVendorCodeSize
) {
285 DEBUG((DEBUG_ERROR
, "FmpImageSize(0x%lx) mismatch, UpdateImageSize(0x%x) UpdateVendorCodeSize(0x%x)\n", FmpImageSize
, ImageHeader
->UpdateImageSize
, ImageHeader
->UpdateVendorCodeSize
));
286 return EFI_INVALID_PARAMETER
;
292 // No driver & payload element in FMP
294 EndOfPayload
= (UINT8
*)(FmpCapsuleHeader
+ 1);
295 if (EndOfPayload
!= EndOfCapsule
) {
296 DEBUG((DEBUG_ERROR
, "EndOfPayload(0x%x) mismatch, EndOfCapsule(0x%x)\n", EndOfPayload
, EndOfCapsule
));
297 return EFI_INVALID_PARAMETER
;
299 return EFI_UNSUPPORTED
;
302 if (EmbeddedDriverCount
!= NULL
) {
303 *EmbeddedDriverCount
= FmpCapsuleHeader
->EmbeddedDriverCount
;
310 Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
311 is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
312 buffer is passed in it will be used if it is big enough.
314 Caution: This function may receive untrusted input.
316 @param[in] BmpImage Pointer to BMP file
317 @param[in] BmpImageSize Number of bytes in BmpImage
318 @param[in, out] GopBlt Buffer containing GOP version of BmpImage.
319 @param[in, out] GopBltSize Size of GopBlt in bytes.
320 @param[out] PixelHeight Height of GopBlt/BmpImage in pixels
321 @param[out] PixelWidth Width of GopBlt/BmpImage in pixels
323 @retval EFI_SUCCESS GopBlt and GopBltSize are returned.
324 @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image
325 @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.
326 GopBltSize will contain the required size.
327 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.
334 IN UINTN BmpImageSize
,
335 IN OUT VOID
**GopBlt
,
336 IN OUT UINTN
*GopBltSize
,
337 OUT UINTN
*PixelHeight
,
338 OUT UINTN
*PixelWidth
343 BMP_IMAGE_HEADER
*BmpHeader
;
344 BMP_COLOR_MAP
*BmpColorMap
;
345 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
;
346 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
347 UINT64 BltBufferSize
;
352 UINT32 DataSizePerLine
;
356 if (sizeof (BMP_IMAGE_HEADER
) > BmpImageSize
) {
357 return EFI_INVALID_PARAMETER
;
360 BmpHeader
= (BMP_IMAGE_HEADER
*) BmpImage
;
362 if (BmpHeader
->CharB
!= 'B' || BmpHeader
->CharM
!= 'M') {
363 return EFI_UNSUPPORTED
;
367 // Doesn't support compress.
369 if (BmpHeader
->CompressionType
!= 0) {
370 return EFI_UNSUPPORTED
;
374 // Only support BITMAPINFOHEADER format.
375 // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER
377 if (BmpHeader
->HeaderSize
!= sizeof (BMP_IMAGE_HEADER
) - OFFSET_OF(BMP_IMAGE_HEADER
, HeaderSize
)) {
378 return EFI_UNSUPPORTED
;
382 // The data size in each line must be 4 byte alignment.
384 DataSizePerLine
= ((BmpHeader
->PixelWidth
* BmpHeader
->BitPerPixel
+ 31) >> 3) & (~0x3);
385 BltBufferSize
= MultU64x32 (DataSizePerLine
, BmpHeader
->PixelHeight
);
386 if (BltBufferSize
> (UINT32
) ~0) {
387 return EFI_INVALID_PARAMETER
;
390 if ((BmpHeader
->Size
!= BmpImageSize
) ||
391 (BmpHeader
->Size
< BmpHeader
->ImageOffset
) ||
392 (BmpHeader
->Size
- BmpHeader
->ImageOffset
!= BmpHeader
->PixelHeight
* DataSizePerLine
)) {
393 return EFI_INVALID_PARAMETER
;
397 // Calculate Color Map offset in the image.
400 BmpColorMap
= (BMP_COLOR_MAP
*) (Image
+ sizeof (BMP_IMAGE_HEADER
));
401 if (BmpHeader
->ImageOffset
< sizeof (BMP_IMAGE_HEADER
)) {
402 return EFI_INVALID_PARAMETER
;
405 if (BmpHeader
->ImageOffset
> sizeof (BMP_IMAGE_HEADER
)) {
406 switch (BmpHeader
->BitPerPixel
) {
421 // BMP file may has padding data between the bmp header section and the bmp data section.
423 if (BmpHeader
->ImageOffset
- sizeof (BMP_IMAGE_HEADER
) < sizeof (BMP_COLOR_MAP
) * ColorMapNum
) {
424 return EFI_INVALID_PARAMETER
;
429 // Calculate graphics image data address in the image
431 Image
= ((UINT8
*) BmpImage
) + BmpHeader
->ImageOffset
;
435 // Calculate the BltBuffer needed size.
437 BltBufferSize
= MultU64x32 ((UINT64
) BmpHeader
->PixelWidth
, BmpHeader
->PixelHeight
);
439 // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
441 if (BltBufferSize
> DivU64x32 ((UINTN
) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
))) {
442 return EFI_UNSUPPORTED
;
444 BltBufferSize
= MultU64x32 (BltBufferSize
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
447 if (*GopBlt
== NULL
) {
449 // GopBlt is not allocated by caller.
451 *GopBltSize
= (UINTN
) BltBufferSize
;
452 *GopBlt
= AllocatePool (*GopBltSize
);
454 if (*GopBlt
== NULL
) {
455 return EFI_OUT_OF_RESOURCES
;
459 // GopBlt has been allocated by caller.
461 if (*GopBltSize
< (UINTN
) BltBufferSize
) {
462 *GopBltSize
= (UINTN
) BltBufferSize
;
463 return EFI_BUFFER_TOO_SMALL
;
467 *PixelWidth
= BmpHeader
->PixelWidth
;
468 *PixelHeight
= BmpHeader
->PixelHeight
;
471 // Convert image from BMP to Blt buffer format
474 for (Height
= 0; Height
< BmpHeader
->PixelHeight
; Height
++) {
475 Blt
= &BltBuffer
[(BmpHeader
->PixelHeight
- Height
- 1) * BmpHeader
->PixelWidth
];
476 for (Width
= 0; Width
< BmpHeader
->PixelWidth
; Width
++, Image
++, Blt
++) {
477 switch (BmpHeader
->BitPerPixel
) {
480 // Convert 1-bit (2 colors) BMP to 24-bit color
482 for (Index
= 0; Index
< 8 && Width
< BmpHeader
->PixelWidth
; Index
++) {
483 Blt
->Red
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Red
;
484 Blt
->Green
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Green
;
485 Blt
->Blue
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Blue
;
496 // Convert 4-bit (16 colors) BMP Palette to 24-bit color
498 Index
= (*Image
) >> 4;
499 Blt
->Red
= BmpColorMap
[Index
].Red
;
500 Blt
->Green
= BmpColorMap
[Index
].Green
;
501 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
502 if (Width
< (BmpHeader
->PixelWidth
- 1)) {
505 Index
= (*Image
) & 0x0f;
506 Blt
->Red
= BmpColorMap
[Index
].Red
;
507 Blt
->Green
= BmpColorMap
[Index
].Green
;
508 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
514 // Convert 8-bit (256 colors) BMP Palette to 24-bit color
516 Blt
->Red
= BmpColorMap
[*Image
].Red
;
517 Blt
->Green
= BmpColorMap
[*Image
].Green
;
518 Blt
->Blue
= BmpColorMap
[*Image
].Blue
;
525 Blt
->Blue
= *Image
++;
526 Blt
->Green
= *Image
++;
532 // it is 32-bit BMP. Skip pixel's highest byte
534 Blt
->Blue
= *Image
++;
535 Blt
->Green
= *Image
++;
541 // Other bit format BMP is not supported.
547 return EFI_UNSUPPORTED
;
552 ImageIndex
= (UINTN
) Image
- (UINTN
) ImageHeader
;
553 if ((ImageIndex
% 4) != 0) {
555 // Bmp Image starts each row on a 32-bit boundary!
557 Image
= Image
+ (4 - (ImageIndex
% 4));
566 Those capsules supported by the firmwares.
568 Caution: This function may receive untrusted input.
570 @param[in] CapsuleHeader Points to a capsule header.
572 @retval EFI_SUCESS Input capsule is supported by firmware.
573 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
576 DisplayCapsuleImage (
577 IN EFI_CAPSULE_HEADER
*CapsuleHeader
580 DISPLAY_DISPLAY_PAYLOAD
*ImagePayload
;
583 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
587 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
589 ImagePayload
= (DISPLAY_DISPLAY_PAYLOAD
*)(CapsuleHeader
+ 1);
590 PayloadSize
= CapsuleHeader
->CapsuleImageSize
- sizeof(EFI_CAPSULE_HEADER
);
592 if (ImagePayload
->Version
!= 1) {
593 return EFI_UNSUPPORTED
;
595 if (CalculateCheckSum8((UINT8
*)CapsuleHeader
, CapsuleHeader
->CapsuleImageSize
) != 0) {
596 return EFI_UNSUPPORTED
;
599 // Only Support Bitmap by now
601 if (ImagePayload
->ImageType
!= 0) {
602 return EFI_UNSUPPORTED
;
608 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**)&GraphicsOutput
);
609 if (EFI_ERROR (Status
)) {
610 Status
= gBS
->LocateProtocol(&gEfiGraphicsOutputProtocolGuid
, NULL
, (VOID
**)&GraphicsOutput
);
611 if (EFI_ERROR(Status
)) {
612 return EFI_UNSUPPORTED
;
616 if (GraphicsOutput
->Mode
->Mode
!= ImagePayload
->Mode
) {
617 return EFI_UNSUPPORTED
;
623 Status
= ConvertBmpToGopBlt (
625 PayloadSize
- sizeof(DISPLAY_DISPLAY_PAYLOAD
),
632 if (EFI_ERROR (Status
)) {
636 Status
= GraphicsOutput
->Blt (
642 (UINTN
) ImagePayload
->OffsetX
,
643 (UINTN
) ImagePayload
->OffsetY
,
646 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
655 Dump FMP information.
657 @param[in] ImageInfoSize The size of ImageInfo, in bytes.
658 @param[in] ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
659 @param[in] DescriptorVersion The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
660 @param[in] DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
661 @param[in] DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
662 @param[in] PackageVersion The version of package.
663 @param[in] PackageVersionName The version name of package.
667 IN UINTN ImageInfoSize
,
668 IN EFI_FIRMWARE_IMAGE_DESCRIPTOR
*ImageInfo
,
669 IN UINT32 DescriptorVersion
,
670 IN UINT8 DescriptorCount
,
671 IN UINTN DescriptorSize
,
672 IN UINT32 PackageVersion
,
673 IN CHAR16
*PackageVersionName
676 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*CurrentImageInfo
;
679 DEBUG((DEBUG_VERBOSE
, " DescriptorVersion - 0x%x\n", DescriptorVersion
));
680 DEBUG((DEBUG_VERBOSE
, " DescriptorCount - 0x%x\n", DescriptorCount
));
681 DEBUG((DEBUG_VERBOSE
, " DescriptorSize - 0x%x\n", DescriptorSize
));
682 DEBUG((DEBUG_VERBOSE
, " PackageVersion - 0x%x\n", PackageVersion
));
683 DEBUG((DEBUG_VERBOSE
, " PackageVersionName - %s\n\n", PackageVersionName
));
684 CurrentImageInfo
= ImageInfo
;
685 for (Index
= 0; Index
< DescriptorCount
; Index
++) {
686 DEBUG((DEBUG_VERBOSE
, " ImageDescriptor (%d)\n", Index
));
687 DEBUG((DEBUG_VERBOSE
, " ImageIndex - 0x%x\n", CurrentImageInfo
->ImageIndex
));
688 DEBUG((DEBUG_VERBOSE
, " ImageTypeId - %g\n", &CurrentImageInfo
->ImageTypeId
));
689 DEBUG((DEBUG_VERBOSE
, " ImageId - 0x%lx\n", CurrentImageInfo
->ImageId
));
690 DEBUG((DEBUG_VERBOSE
, " ImageIdName - %s\n", CurrentImageInfo
->ImageIdName
));
691 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", CurrentImageInfo
->Version
));
692 DEBUG((DEBUG_VERBOSE
, " VersionName - %s\n", CurrentImageInfo
->VersionName
));
693 DEBUG((DEBUG_VERBOSE
, " Size - 0x%x\n", CurrentImageInfo
->Size
));
694 DEBUG((DEBUG_VERBOSE
, " AttributesSupported - 0x%lx\n", CurrentImageInfo
->AttributesSupported
));
695 DEBUG((DEBUG_VERBOSE
, " AttributesSetting - 0x%lx\n", CurrentImageInfo
->AttributesSetting
));
696 DEBUG((DEBUG_VERBOSE
, " Compatibilities - 0x%lx\n", CurrentImageInfo
->Compatibilities
));
697 if (DescriptorVersion
> 1) {
698 DEBUG((DEBUG_VERBOSE
, " LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo
->LowestSupportedImageVersion
));
699 if (DescriptorVersion
> 2) {
700 DEBUG((DEBUG_VERBOSE
, " LastAttemptVersion - 0x%x\n", CurrentImageInfo
->LastAttemptVersion
));
701 DEBUG((DEBUG_VERBOSE
, " LastAttemptStatus - 0x%x\n", CurrentImageInfo
->LastAttemptStatus
));
702 DEBUG((DEBUG_VERBOSE
, " HardwareInstance - 0x%lx\n", CurrentImageInfo
->HardwareInstance
));
706 // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
708 CurrentImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)CurrentImageInfo
+ DescriptorSize
);
713 Dump a non-nested FMP capsule.
715 @param[in] CapsuleHeader A pointer to CapsuleHeader
719 IN EFI_CAPSULE_HEADER
*CapsuleHeader
722 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
723 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
725 UINT64
*ItemOffsetList
;
727 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
729 DEBUG((DEBUG_VERBOSE
, "FmpCapsule:\n"));
730 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", FmpCapsuleHeader
->Version
));
731 DEBUG((DEBUG_VERBOSE
, " EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader
->EmbeddedDriverCount
));
732 DEBUG((DEBUG_VERBOSE
, " PayloadItemCount - 0x%x\n", FmpCapsuleHeader
->PayloadItemCount
));
734 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
735 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
736 DEBUG((DEBUG_VERBOSE
, " ItemOffsetList[%d] - 0x%lx\n", Index
, ItemOffsetList
[Index
]));
738 for (; Index
< (UINT32
)FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
; Index
++) {
739 DEBUG((DEBUG_VERBOSE
, " ItemOffsetList[%d] - 0x%lx\n", Index
, ItemOffsetList
[Index
]));
740 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
742 DEBUG((DEBUG_VERBOSE
, " ImageHeader:\n"));
743 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", ImageHeader
->Version
));
744 DEBUG((DEBUG_VERBOSE
, " UpdateImageTypeId - %g\n", &ImageHeader
->UpdateImageTypeId
));
745 DEBUG((DEBUG_VERBOSE
, " UpdateImageIndex - 0x%x\n", ImageHeader
->UpdateImageIndex
));
746 DEBUG((DEBUG_VERBOSE
, " UpdateImageSize - 0x%x\n", ImageHeader
->UpdateImageSize
));
747 DEBUG((DEBUG_VERBOSE
, " UpdateVendorCodeSize - 0x%x\n", ImageHeader
->UpdateVendorCodeSize
));
748 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
749 DEBUG((DEBUG_VERBOSE
, " UpdateHardwareInstance - 0x%lx\n", ImageHeader
->UpdateHardwareInstance
));
755 Dump all FMP information.
763 EFI_HANDLE
*HandleBuffer
;
764 UINTN NumberOfHandles
;
765 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
768 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
769 UINT32 FmpImageInfoDescriptorVer
;
770 UINT8 FmpImageInfoCount
;
771 UINTN DescriptorSize
;
772 UINT32 PackageVersion
;
773 CHAR16
*PackageVersionName
;
775 Status
= gBS
->LocateHandleBuffer (
777 &gEfiFirmwareManagementProtocolGuid
,
782 if (EFI_ERROR(Status
)) {
786 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
787 Status
= gBS
->HandleProtocol(
789 &gEfiFirmwareManagementProtocolGuid
,
792 if (EFI_ERROR(Status
)) {
797 Status
= Fmp
->GetImageInfo (
807 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
811 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
812 if (FmpImageInfoBuf
== NULL
) {
816 PackageVersionName
= NULL
;
817 Status
= Fmp
->GetImageInfo (
819 &ImageInfoSize
, // ImageInfoSize
820 FmpImageInfoBuf
, // ImageInfo
821 &FmpImageInfoDescriptorVer
, // DescriptorVersion
822 &FmpImageInfoCount
, // DescriptorCount
823 &DescriptorSize
, // DescriptorSize
824 &PackageVersion
, // PackageVersion
825 &PackageVersionName
// PackageVersionName
827 if (EFI_ERROR(Status
)) {
828 FreePool(FmpImageInfoBuf
);
832 DEBUG((DEBUG_INFO
, "FMP (%d) ImageInfo:\n", Index
));
834 ImageInfoSize
, // ImageInfoSize
835 FmpImageInfoBuf
, // ImageInfo
836 FmpImageInfoDescriptorVer
, // DescriptorVersion
837 FmpImageInfoCount
, // DescriptorCount
838 DescriptorSize
, // DescriptorSize
839 PackageVersion
, // PackageVersion
840 PackageVersionName
// PackageVersionName
843 if (PackageVersionName
!= NULL
) {
844 FreePool(PackageVersionName
);
847 FreePool(FmpImageInfoBuf
);
854 Get FMP handle by ImageTypeId and HardwareInstance.
856 @param[in] UpdateImageTypeId Used to identify device firmware targeted by this update.
857 @param[in] UpdateHardwareInstance The HardwareInstance to target with this update.
858 @param[in,out] NoHandles The number of handles returned in Buffer.
859 @param[out] Buffer[out] A pointer to the buffer to return the requested array of handles.
861 @retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of
862 handles in Buffer was returned in NoHandles.
863 @retval EFI_NOT_FOUND No handles match the search.
864 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
867 GetFmpHandleBufferByType (
868 IN EFI_GUID
*UpdateImageTypeId
,
869 IN UINT64 UpdateHardwareInstance
,
870 IN OUT UINTN
*NoHandles
,
871 OUT EFI_HANDLE
**Buffer
875 EFI_HANDLE
*HandleBuffer
;
876 UINTN NumberOfHandles
;
877 EFI_HANDLE
*MatchedHandleBuffer
;
878 UINTN MatchedNumberOfHandles
;
879 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
882 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
883 UINT32 FmpImageInfoDescriptorVer
;
884 UINT8 FmpImageInfoCount
;
885 UINTN DescriptorSize
;
886 UINT32 PackageVersion
;
887 CHAR16
*PackageVersionName
;
889 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*TempFmpImageInfo
;
894 Status
= gBS
->LocateHandleBuffer (
896 &gEfiFirmwareManagementProtocolGuid
,
901 if (EFI_ERROR(Status
)) {
905 MatchedNumberOfHandles
= 0;
906 MatchedHandleBuffer
= AllocateZeroPool (sizeof(EFI_HANDLE
) * NumberOfHandles
);
907 if (MatchedHandleBuffer
== NULL
) {
908 FreePool (HandleBuffer
);
909 return EFI_OUT_OF_RESOURCES
;
912 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
913 Status
= gBS
->HandleProtocol(
915 &gEfiFirmwareManagementProtocolGuid
,
918 if (EFI_ERROR(Status
)) {
923 Status
= Fmp
->GetImageInfo (
933 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
937 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
938 if (FmpImageInfoBuf
== NULL
) {
942 PackageVersionName
= NULL
;
943 Status
= Fmp
->GetImageInfo (
945 &ImageInfoSize
, // ImageInfoSize
946 FmpImageInfoBuf
, // ImageInfo
947 &FmpImageInfoDescriptorVer
, // DescriptorVersion
948 &FmpImageInfoCount
, // DescriptorCount
949 &DescriptorSize
, // DescriptorSize
950 &PackageVersion
, // PackageVersion
951 &PackageVersionName
// PackageVersionName
953 if (EFI_ERROR(Status
)) {
954 FreePool(FmpImageInfoBuf
);
958 if (PackageVersionName
!= NULL
) {
959 FreePool(PackageVersionName
);
962 TempFmpImageInfo
= FmpImageInfoBuf
;
963 for (Index2
= 0; Index2
< FmpImageInfoCount
; Index2
++) {
965 // Check if this FMP instance matches
967 if (CompareGuid(UpdateImageTypeId
, &TempFmpImageInfo
->ImageTypeId
)) {
968 if ((UpdateHardwareInstance
== 0) ||
969 ((FmpImageInfoDescriptorVer
>= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
) &&
970 (UpdateHardwareInstance
== TempFmpImageInfo
->HardwareInstance
))) {
971 MatchedHandleBuffer
[MatchedNumberOfHandles
] = HandleBuffer
[Index
];
972 MatchedNumberOfHandles
++;
976 TempFmpImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)TempFmpImageInfo
+ DescriptorSize
);
978 FreePool(FmpImageInfoBuf
);
981 if (MatchedNumberOfHandles
== 0) {
982 return EFI_NOT_FOUND
;
985 *NoHandles
= MatchedNumberOfHandles
;
986 *Buffer
= MatchedHandleBuffer
;
992 Return FmpImageInfoDescriptorVer by an FMP handle.
994 @param[in] Handle A FMP handle.
996 @return FmpImageInfoDescriptorVer associated with the FMP.
999 GetFmpImageInfoDescriptorVer (
1000 IN EFI_HANDLE Handle
1004 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
1005 UINTN ImageInfoSize
;
1006 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
1007 UINT32 FmpImageInfoDescriptorVer
;
1008 UINT8 FmpImageInfoCount
;
1009 UINTN DescriptorSize
;
1010 UINT32 PackageVersion
;
1011 CHAR16
*PackageVersionName
;
1013 Status
= gBS
->HandleProtocol(
1015 &gEfiFirmwareManagementProtocolGuid
,
1018 if (EFI_ERROR(Status
)) {
1023 Status
= Fmp
->GetImageInfo (
1033 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1037 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
1038 if (FmpImageInfoBuf
== NULL
) {
1042 PackageVersionName
= NULL
;
1043 Status
= Fmp
->GetImageInfo (
1045 &ImageInfoSize
, // ImageInfoSize
1046 FmpImageInfoBuf
, // ImageInfo
1047 &FmpImageInfoDescriptorVer
, // DescriptorVersion
1048 &FmpImageInfoCount
, // DescriptorCount
1049 &DescriptorSize
, // DescriptorSize
1050 &PackageVersion
, // PackageVersion
1051 &PackageVersionName
// PackageVersionName
1053 if (EFI_ERROR(Status
)) {
1054 FreePool(FmpImageInfoBuf
);
1057 return FmpImageInfoDescriptorVer
;
1063 @param[in] Handle A FMP handle.
1064 @param[in] ImageHeader The payload image header.
1065 @param[in] PayloadIndex The index of the payload.
1067 @return The status of FMP->SetImage.
1071 IN EFI_HANDLE Handle
,
1072 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
,
1073 IN UINTN PayloadIndex
1077 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
1080 CHAR16
*AbortReason
;
1082 Status
= gBS
->HandleProtocol(
1084 &gEfiFirmwareManagementProtocolGuid
,
1087 if (EFI_ERROR(Status
)) {
1091 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
1092 Image
= (UINT8
*)(ImageHeader
+ 1);
1095 // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1,
1096 // Header should exclude UpdateHardwareInstance field
1098 Image
= (UINT8
*)ImageHeader
+ OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
1101 if (ImageHeader
->UpdateVendorCodeSize
== 0) {
1104 VendorCode
= Image
+ ImageHeader
->UpdateImageSize
;
1107 DEBUG((DEBUG_INFO
, "Fmp->SetImage ...\n"));
1108 DEBUG((DEBUG_INFO
, "ImageTypeId - %g, ", &ImageHeader
->UpdateImageTypeId
));
1109 DEBUG((DEBUG_INFO
, "PayloadIndex - 0x%x, ", PayloadIndex
));
1110 DEBUG((DEBUG_INFO
, "ImageIndex - 0x%x ", ImageHeader
->UpdateImageIndex
));
1111 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
1112 DEBUG((DEBUG_INFO
, "(UpdateHardwareInstance - 0x%x)", ImageHeader
->UpdateHardwareInstance
));
1114 DEBUG((DEBUG_INFO
, "\n"));
1115 Status
= Fmp
->SetImage(
1117 ImageHeader
->UpdateImageIndex
, // ImageIndex
1119 ImageHeader
->UpdateImageSize
, // ImageSize
1120 VendorCode
, // VendorCode
1121 Update_Image_Progress
, // Progress
1122 &AbortReason
// AbortReason
1124 DEBUG((DEBUG_INFO
, "Fmp->SetImage - %r\n", Status
));
1125 if (AbortReason
!= NULL
) {
1126 DEBUG ((DEBUG_ERROR
, "%s\n", AbortReason
));
1127 FreePool(AbortReason
);
1134 Start a UEFI image in the FMP payload.
1136 @param[in] ImageBuffer A pointer to the memory location containing a copy of the image to be loaded..
1137 @param[in] ImageSize The size in bytes of ImageBuffer.
1139 @return The status of gBS->LoadImage and gBS->StartImage.
1143 IN VOID
*ImageBuffer
,
1147 MEMMAP_DEVICE_PATH MemMapNode
;
1149 EFI_HANDLE ImageHandle
;
1150 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
1153 SetDevicePathNodeLength (&MemMapNode
.Header
, sizeof (MemMapNode
));
1154 MemMapNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
1155 MemMapNode
.Header
.SubType
= HW_MEMMAP_DP
;
1156 MemMapNode
.MemoryType
= EfiBootServicesCode
;
1157 MemMapNode
.StartingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)ImageBuffer
;
1158 MemMapNode
.EndingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)((UINT8
*)ImageBuffer
+ ImageSize
- 1);
1160 DriverDevicePath
= AppendDevicePathNode (NULL
, &MemMapNode
.Header
);
1161 if (DriverDevicePath
== NULL
) {
1162 return EFI_OUT_OF_RESOURCES
;
1165 DEBUG((DEBUG_INFO
, "FmpCapsule: LoadImage ...\n"));
1166 Status
= gBS
->LoadImage(
1174 DEBUG((DEBUG_INFO
, "FmpCapsule: LoadImage - %r\n", Status
));
1175 if (EFI_ERROR(Status
)) {
1176 FreePool(DriverDevicePath
);
1180 DEBUG((DEBUG_INFO
, "FmpCapsule: StartImage ...\n"));
1181 Status
= gBS
->StartImage(
1186 DEBUG((DEBUG_INFO
, "FmpCapsule: StartImage - %r\n", Status
));
1187 if (EFI_ERROR(Status
)) {
1188 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
1191 FreePool(DriverDevicePath
);
1196 Record FMP capsule status.
1198 @param[in] Handle A FMP handle.
1199 @param[in] CapsuleHeader The capsule image header
1200 @param[in] CapsuleStatus The capsule process stauts
1201 @param[in] PayloadIndex FMP payload index
1202 @param[in] ImageHeader FMP image header
1205 RecordFmpCapsuleStatus (
1206 IN EFI_HANDLE Handle
, OPTIONAL
1207 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
1208 IN EFI_STATUS CapsuleStatus
,
1209 IN UINTN PayloadIndex
,
1210 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
1214 EFI_DEVICE_PATH_PROTOCOL
*FmpDevicePath
;
1215 UINT32 FmpImageInfoDescriptorVer
;
1216 EFI_STATUS StatusEsrt
;
1217 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
1218 EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry
;
1220 FmpDevicePath
= NULL
;
1221 if (Handle
!= NULL
) {
1222 gBS
->HandleProtocol(
1224 &gEfiDevicePathProtocolGuid
,
1225 (VOID
**)&FmpDevicePath
1229 RecordFmpCapsuleStatusVariable (
1238 // Update corresponding ESRT entry LastAttemp Status
1240 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
1241 if (EFI_ERROR (Status
)) {
1245 if (Handle
== NULL
) {
1250 // Update EsrtEntry For V1, V2 FMP instance.
1251 // V3 FMP ESRT cache will be synced up through EsrtSyncFmp interface
1253 FmpImageInfoDescriptorVer
= GetFmpImageInfoDescriptorVer (Handle
);
1254 if (FmpImageInfoDescriptorVer
< EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
) {
1255 StatusEsrt
= EsrtProtocol
->GetEsrtEntry(&ImageHeader
->UpdateImageTypeId
, &EsrtEntry
);
1256 if (!EFI_ERROR(StatusEsrt
)){
1257 if (!EFI_ERROR(CapsuleStatus
)) {
1258 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_SUCCESS
;
1260 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL
;
1262 EsrtEntry
.LastAttemptVersion
= 0;
1263 EsrtProtocol
->UpdateEsrtEntry(&EsrtEntry
);
1269 Process Firmware management protocol data capsule.
1271 This function assumes the caller validated the capsule by using
1272 ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
1273 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
1274 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
1276 This function need support nested FMP capsule.
1278 @param[in] CapsuleHeader Points to a capsule header.
1280 @retval EFI_SUCESS Process Capsule Image successfully.
1281 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1282 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1283 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1284 @retval EFI_NOT_READY No FMP protocol to handle this FMP capsule.
1287 ProcessFmpCapsuleImage (
1288 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1292 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
1293 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
1294 UINT64
*ItemOffsetList
;
1297 EFI_HANDLE
*HandleBuffer
;
1298 UINTN NumberOfHandles
;
1300 UINT64 UpdateHardwareInstance
;
1305 if (!IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
1306 return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
));
1312 DumpFmpCapsule(CapsuleHeader
);
1314 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
1316 if (FmpCapsuleHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
1317 return EFI_INVALID_PARAMETER
;
1319 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
1321 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
1324 // capsule in which driver count and payload count are both zero is not processed.
1331 // 1. Try to load & start all the drivers within capsule
1333 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
1334 if ((FmpCapsuleHeader
->PayloadItemCount
== 0) &&
1335 (Index
== (UINTN
)FmpCapsuleHeader
->EmbeddedDriverCount
- 1)) {
1337 // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
1339 DriverLen
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
- (UINTN
)ItemOffsetList
[Index
];
1341 DriverLen
= (UINTN
)ItemOffsetList
[Index
+ 1] - (UINTN
)ItemOffsetList
[Index
];
1344 Status
= StartFmpImage (
1345 (UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
],
1348 if (EFI_ERROR(Status
)) {
1349 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
1355 // 2. Route payload to right FMP instance
1357 DEBUG((DEBUG_INFO
, "FmpCapsule: route payload to right FMP instance ...\n"));
1362 // Check all the payload entry in capsule payload list
1364 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
1365 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
1367 UpdateHardwareInstance
= 0;
1368 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
1369 UpdateHardwareInstance
= ImageHeader
->UpdateHardwareInstance
;
1372 Status
= GetFmpHandleBufferByType (
1373 &ImageHeader
->UpdateImageTypeId
,
1374 UpdateHardwareInstance
,
1378 if (EFI_ERROR(Status
)) {
1380 RecordFmpCapsuleStatus (
1384 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1390 for (Index2
= 0; Index2
< NumberOfHandles
; Index2
++) {
1392 RecordFmpCapsuleStatus (
1393 HandleBuffer
[Index2
],
1396 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1402 Status
= SetFmpImageData (
1403 HandleBuffer
[Index2
],
1405 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
1407 if (Status
!= EFI_SUCCESS
) {
1411 RecordFmpCapsuleStatus (
1412 HandleBuffer
[Index2
],
1415 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1419 if (HandleBuffer
!= NULL
) {
1420 FreePool(HandleBuffer
);
1425 return EFI_NOT_READY
;
1429 // always return SUCCESS to indicate this capsule is processed.
1430 // The status of SetImage is recorded in capsule result variable.
1436 Return if there is a FMP header below capsule header.
1438 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1440 @retval TRUE There is a FMP header below capsule header.
1441 @retval FALSE There is not a FMP header below capsule header
1444 IsNestedFmpCapsule (
1445 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1449 EFI_SYSTEM_RESOURCE_TABLE
*Esrt
;
1450 EFI_SYSTEM_RESOURCE_ENTRY
*EsrtEntry
;
1452 BOOLEAN EsrtGuidFound
;
1453 EFI_CAPSULE_HEADER
*NestedCapsuleHeader
;
1454 UINTN NestedCapsuleSize
;
1455 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
1456 EFI_SYSTEM_RESOURCE_ENTRY Entry
;
1458 EsrtGuidFound
= FALSE
;
1459 if (mIsVirtualAddrConverted
) {
1460 if(mEsrtTable
!= NULL
) {
1461 EsrtEntry
= (EFI_SYSTEM_RESOURCE_ENTRY
*)(mEsrtTable
+ 1);
1462 for (Index
= 0; Index
< mEsrtTable
->FwResourceCount
; Index
++, EsrtEntry
++) {
1463 if (CompareGuid(&EsrtEntry
->FwClass
, &CapsuleHeader
->CapsuleGuid
)) {
1464 EsrtGuidFound
= TRUE
;
1471 // Check ESRT protocol
1473 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
1474 if (!EFI_ERROR(Status
)) {
1475 Status
= EsrtProtocol
->GetEsrtEntry(&CapsuleHeader
->CapsuleGuid
, &Entry
);
1476 if (!EFI_ERROR(Status
)) {
1477 EsrtGuidFound
= TRUE
;
1482 // Check ESRT configuration table
1484 if (!EsrtGuidFound
) {
1485 Status
= EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid
, (VOID
**)&Esrt
);
1486 if (!EFI_ERROR(Status
)) {
1487 ASSERT (Esrt
!= NULL
);
1488 EsrtEntry
= (VOID
*)(Esrt
+ 1);
1489 for (Index
= 0; Index
< Esrt
->FwResourceCount
; Index
++, EsrtEntry
++) {
1490 if (CompareGuid(&EsrtEntry
->FwClass
, &CapsuleHeader
->CapsuleGuid
)) {
1491 EsrtGuidFound
= TRUE
;
1498 if (!EsrtGuidFound
) {
1503 // Check nested capsule header
1504 // FMP GUID after ESRT one
1506 NestedCapsuleHeader
= (EFI_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
1507 NestedCapsuleSize
= (UINTN
)CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
- (UINTN
)NestedCapsuleHeader
;
1508 if (NestedCapsuleSize
< sizeof(EFI_CAPSULE_HEADER
)) {
1511 if (!IsValidCapsuleHeader(NestedCapsuleHeader
, NestedCapsuleSize
)) {
1514 if (!IsFmpCapsuleGuid(&NestedCapsuleHeader
->CapsuleGuid
)) {
1517 DEBUG ((DEBUG_INFO
, "IsNestedFmpCapsule\n"));
1522 Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
1524 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1526 @retval TRUE It is a system FMP.
1527 @retval FALSE It is a device FMP.
1531 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1534 if (IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
1537 if (IsNestedFmpCapsule(CapsuleHeader
)) {
1544 Those capsules supported by the firmwares.
1546 Caution: This function may receive untrusted input.
1548 @param[in] CapsuleHeader Points to a capsule header.
1550 @retval EFI_SUCESS Input capsule is supported by firmware.
1551 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
1552 @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
1556 SupportCapsuleImage (
1557 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1561 // check Display Capsule Guid
1563 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1567 if (IsFmpCapsule(CapsuleHeader
)) {
1569 // Check layout of FMP capsule
1571 return ValidateFmpCapsule(CapsuleHeader
, NULL
);
1573 DEBUG((DEBUG_ERROR
, "Unknown Capsule Guid - %g\n", &CapsuleHeader
->CapsuleGuid
));
1574 return EFI_UNSUPPORTED
;
1578 The firmware implements to process the capsule image.
1580 Caution: This function may receive untrusted input.
1582 @param[in] CapsuleHeader Points to a capsule header.
1584 @retval EFI_SUCESS Process Capsule Image successfully.
1585 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1586 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1587 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1591 ProcessCapsuleImage (
1592 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1597 if (SupportCapsuleImage (CapsuleHeader
) != EFI_SUCCESS
) {
1598 RecordCapsuleStatusVariable(CapsuleHeader
, EFI_UNSUPPORTED
);
1599 return EFI_UNSUPPORTED
;
1603 // Display image in firmware update display capsule
1605 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1606 DEBUG((DEBUG_INFO
, "ProcessCapsuleImage for WindowsUxCapsule ...\n"));
1607 Status
= DisplayCapsuleImage(CapsuleHeader
);
1608 RecordCapsuleStatusVariable(CapsuleHeader
, Status
);
1613 // Check FMP capsule layout
1615 if (IsFmpCapsule (CapsuleHeader
)) {
1616 DEBUG((DEBUG_INFO
, "ProcessCapsuleImage for FmpCapsule ...\n"));
1617 DEBUG((DEBUG_INFO
, "ValidateFmpCapsule ...\n"));
1618 Status
= ValidateFmpCapsule(CapsuleHeader
, NULL
);
1619 DEBUG((DEBUG_INFO
, "ValidateFmpCapsule - %r\n", Status
));
1620 if (EFI_ERROR(Status
)) {
1621 RecordCapsuleStatusVariable(CapsuleHeader
, Status
);
1626 // Press EFI FMP Capsule
1628 DEBUG((DEBUG_INFO
, "ProcessFmpCapsuleImage ...\n"));
1629 Status
= ProcessFmpCapsuleImage(CapsuleHeader
);
1630 DEBUG((DEBUG_INFO
, "ProcessFmpCapsuleImage - %r\n", Status
));
1635 return EFI_UNSUPPORTED
;
1639 Callback function executed when the EndOfDxe event group is signaled.
1641 @param[in] Event Event whose notification function is being invoked.
1642 @param[in] Context The pointer to the notification function's context, which
1643 is implementation-dependent.
1647 DxeCapsuleLibEndOfDxe (
1652 mDxeCapsuleLibEndOfDxe
= TRUE
;
1656 The constructor function.
1658 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1659 @param[in] SystemTable A pointer to the EFI System Table.
1661 @retval EFI_SUCCESS The constructor successfully .
1665 DxeCapsuleLibConstructor (
1666 IN EFI_HANDLE ImageHandle
,
1667 IN EFI_SYSTEM_TABLE
*SystemTable
1672 Status
= gBS
->CreateEventEx (
1675 DxeCapsuleLibEndOfDxe
,
1677 &gEfiEndOfDxeEventGroupGuid
,
1678 &mDxeCapsuleLibEndOfDxeEvent
1680 ASSERT_EFI_ERROR (Status
);
1682 InitCapsuleVariable();
1688 The destructor function closes the End of DXE event.
1690 @param ImageHandle The firmware allocated handle for the EFI image.
1691 @param SystemTable A pointer to the EFI System Table.
1693 @retval EFI_SUCCESS The destructor completed successfully.
1697 DxeCapsuleLibDestructor (
1698 IN EFI_HANDLE ImageHandle
,
1699 IN EFI_SYSTEM_TABLE
*SystemTable
1705 // Close the End of DXE event.
1707 Status
= gBS
->CloseEvent (mDxeCapsuleLibEndOfDxeEvent
);
1708 ASSERT_EFI_ERROR (Status
);