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 BOOLEAN mDxeCapsuleLibEndOfDxe
= FALSE
;
51 EFI_EVENT mDxeCapsuleLibEndOfDxeEvent
= NULL
;
54 Initialize capsule related variables.
62 Record capsule status variable.
64 @param[in] CapsuleHeader The capsule image header
65 @param[in] CapsuleStatus The capsule process stauts
67 @retval EFI_SUCCESS The capsule status variable is recorded.
68 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
71 RecordCapsuleStatusVariable (
72 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
73 IN EFI_STATUS CapsuleStatus
77 Record FMP capsule status variable.
79 @param[in] CapsuleHeader The capsule image header
80 @param[in] CapsuleStatus The capsule process stauts
81 @param[in] PayloadIndex FMP payload index
82 @param[in] ImageHeader FMP image header
83 @param[in] FmpDevicePath DevicePath associated with the FMP producer
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
98 Function indicate the current completion progress of the firmware
99 update. Platform may override with own specific progress function.
101 @param[in] Completion A value between 1 and 100 indicating the current completion progress of the firmware update
103 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
107 Update_Image_Progress (
115 Return if this CapsuleGuid is a FMP capsule GUID or not.
117 @param[in] CapsuleGuid A pointer to EFI_GUID
119 @retval TRUE It is a FMP capsule GUID.
120 @retval FALSE It is not a FMP capsule GUID.
124 IN EFI_GUID
*CapsuleGuid
127 if (CompareGuid(&gEfiFmpCapsuleGuid
, CapsuleGuid
)) {
135 Validate if it is valid capsule header
137 Caution: This function may receive untrusted input.
139 This function assumes the caller provided correct CapsuleHeader pointer
142 This function validates the fields in EFI_CAPSULE_HEADER.
144 @param[in] CapsuleHeader Points to a capsule header.
145 @param[in] CapsuleSize Size of the whole capsule image.
149 IsValidCapsuleHeader (
150 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
151 IN UINT64 CapsuleSize
154 if (CapsuleHeader
->CapsuleImageSize
!= CapsuleSize
) {
157 if (CapsuleHeader
->HeaderSize
>= CapsuleHeader
->CapsuleImageSize
) {
164 Validate Fmp capsules layout.
166 Caution: This function may receive untrusted input.
168 This function assumes the caller validated the capsule by using
169 IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.
170 The capsule buffer size is CapsuleHeader->CapsuleImageSize.
172 This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
173 and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
175 This function need support nested FMP capsule.
177 @param[in] CapsuleHeader Points to a capsule header.
178 @param[out] EmbeddedDriverCount The EmbeddedDriverCount in the FMP capsule.
180 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
181 @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.
185 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
186 OUT UINT16
*EmbeddedDriverCount OPTIONAL
189 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
191 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
193 UINT64
*ItemOffsetList
;
196 UINTN FmpCapsuleSize
;
197 UINTN FmpCapsuleHeaderSize
;
199 UINTN FmpImageHeaderSize
;
201 if (!IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
202 return ValidateFmpCapsule ((EFI_CAPSULE_HEADER
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
), EmbeddedDriverCount
);
205 if (CapsuleHeader
->HeaderSize
>= CapsuleHeader
->CapsuleImageSize
) {
206 DEBUG((DEBUG_ERROR
, "HeaderSize(0x%x) >= CapsuleImageSize(0x%x)\n", CapsuleHeader
->HeaderSize
, CapsuleHeader
->CapsuleImageSize
));
207 return EFI_INVALID_PARAMETER
;
210 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
211 EndOfCapsule
= (UINT8
*) CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
;
212 FmpCapsuleSize
= (UINTN
)EndOfCapsule
- (UINTN
)FmpCapsuleHeader
;
214 if (FmpCapsuleSize
< sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
)) {
215 DEBUG((DEBUG_ERROR
, "FmpCapsuleSize(0x%x) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\n", FmpCapsuleSize
));
216 return EFI_INVALID_PARAMETER
;
219 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
220 if (FmpCapsuleHeader
->Version
!= EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
221 DEBUG((DEBUG_ERROR
, "FmpCapsuleHeader->Version(0x%x) != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION\n", FmpCapsuleHeader
->Version
));
222 return EFI_INVALID_PARAMETER
;
224 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
227 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
229 if ((FmpCapsuleSize
- sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
))/sizeof(UINT64
) < ItemNum
) {
230 DEBUG((DEBUG_ERROR
, "ItemNum(0x%x) too big\n", ItemNum
));
231 return EFI_INVALID_PARAMETER
;
233 FmpCapsuleHeaderSize
= sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
) + sizeof(UINT64
)*ItemNum
;
235 // Check ItemOffsetList
236 for (Index
= 0; Index
< ItemNum
; Index
++) {
237 if (ItemOffsetList
[Index
] >= FmpCapsuleSize
) {
238 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) >= FmpCapsuleSize(0x%x)\n", Index
, ItemOffsetList
[Index
], FmpCapsuleSize
));
239 return EFI_INVALID_PARAMETER
;
241 if (ItemOffsetList
[Index
] < FmpCapsuleHeaderSize
) {
242 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) < FmpCapsuleHeaderSize(0x%x)\n", Index
, ItemOffsetList
[Index
], FmpCapsuleHeaderSize
));
243 return EFI_INVALID_PARAMETER
;
246 // All the address in ItemOffsetList must be stored in ascending order
249 if (ItemOffsetList
[Index
] <= ItemOffsetList
[Index
- 1]) {
250 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) < ItemOffsetList[%d](0x%x)\n", Index
, ItemOffsetList
[Index
], Index
, ItemOffsetList
[Index
- 1]));
251 return EFI_INVALID_PARAMETER
;
256 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
257 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
258 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
259 if (Index
== ItemNum
- 1) {
260 EndOfPayload
= (UINT8
*)((UINTN
)EndOfCapsule
- (UINTN
)FmpCapsuleHeader
);
262 EndOfPayload
= (UINT8
*)(UINTN
)ItemOffsetList
[Index
+1];
264 FmpImageSize
= (UINTN
)EndOfPayload
- ItemOffsetList
[Index
];
266 if (FmpImageSize
< OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
)) {
267 DEBUG((DEBUG_ERROR
, "FmpImageSize(0x%lx) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER\n", FmpImageSize
));
268 return EFI_INVALID_PARAMETER
;
270 FmpImageHeaderSize
= sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
);
271 if ((ImageHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) ||
272 (ImageHeader
->Version
< 1)) {
273 DEBUG((DEBUG_ERROR
, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader
->Version
));
274 return EFI_INVALID_PARAMETER
;
276 if (ImageHeader
->Version
< EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
277 FmpImageHeaderSize
= OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
281 if (FmpImageSize
!= (UINT64
)FmpImageHeaderSize
+ (UINT64
)ImageHeader
->UpdateImageSize
+ (UINT64
)ImageHeader
->UpdateVendorCodeSize
) {
282 DEBUG((DEBUG_ERROR
, "FmpImageSize(0x%lx) mismatch, UpdateImageSize(0x%x) UpdateVendorCodeSize(0x%x)\n", FmpImageSize
, ImageHeader
->UpdateImageSize
, ImageHeader
->UpdateVendorCodeSize
));
283 return EFI_INVALID_PARAMETER
;
289 // No driver & payload element in FMP
291 EndOfPayload
= (UINT8
*)(FmpCapsuleHeader
+ 1);
292 if (EndOfPayload
!= EndOfCapsule
) {
293 DEBUG((DEBUG_ERROR
, "EndOfPayload(0x%x) mismatch, EndOfCapsule(0x%x)\n", EndOfPayload
, EndOfCapsule
));
294 return EFI_INVALID_PARAMETER
;
296 return EFI_UNSUPPORTED
;
299 if (EmbeddedDriverCount
!= NULL
) {
300 *EmbeddedDriverCount
= FmpCapsuleHeader
->EmbeddedDriverCount
;
307 Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
308 is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
309 buffer is passed in it will be used if it is big enough.
311 Caution: This function may receive untrusted input.
313 @param[in] BmpImage Pointer to BMP file
314 @param[in] BmpImageSize Number of bytes in BmpImage
315 @param[in, out] GopBlt Buffer containing GOP version of BmpImage.
316 @param[in, out] GopBltSize Size of GopBlt in bytes.
317 @param[out] PixelHeight Height of GopBlt/BmpImage in pixels
318 @param[out] PixelWidth Width of GopBlt/BmpImage in pixels
320 @retval EFI_SUCCESS GopBlt and GopBltSize are returned.
321 @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image
322 @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.
323 GopBltSize will contain the required size.
324 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.
331 IN UINTN BmpImageSize
,
332 IN OUT VOID
**GopBlt
,
333 IN OUT UINTN
*GopBltSize
,
334 OUT UINTN
*PixelHeight
,
335 OUT UINTN
*PixelWidth
340 BMP_IMAGE_HEADER
*BmpHeader
;
341 BMP_COLOR_MAP
*BmpColorMap
;
342 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
;
343 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
344 UINT64 BltBufferSize
;
349 UINT32 DataSizePerLine
;
353 if (sizeof (BMP_IMAGE_HEADER
) > BmpImageSize
) {
354 return EFI_INVALID_PARAMETER
;
357 BmpHeader
= (BMP_IMAGE_HEADER
*) BmpImage
;
359 if (BmpHeader
->CharB
!= 'B' || BmpHeader
->CharM
!= 'M') {
360 return EFI_UNSUPPORTED
;
364 // Doesn't support compress.
366 if (BmpHeader
->CompressionType
!= 0) {
367 return EFI_UNSUPPORTED
;
371 // Only support BITMAPINFOHEADER format.
372 // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER
374 if (BmpHeader
->HeaderSize
!= sizeof (BMP_IMAGE_HEADER
) - OFFSET_OF(BMP_IMAGE_HEADER
, HeaderSize
)) {
375 return EFI_UNSUPPORTED
;
379 // The data size in each line must be 4 byte alignment.
381 DataSizePerLine
= ((BmpHeader
->PixelWidth
* BmpHeader
->BitPerPixel
+ 31) >> 3) & (~0x3);
382 BltBufferSize
= MultU64x32 (DataSizePerLine
, BmpHeader
->PixelHeight
);
383 if (BltBufferSize
> (UINT32
) ~0) {
384 return EFI_INVALID_PARAMETER
;
387 if ((BmpHeader
->Size
!= BmpImageSize
) ||
388 (BmpHeader
->Size
< BmpHeader
->ImageOffset
) ||
389 (BmpHeader
->Size
- BmpHeader
->ImageOffset
!= BmpHeader
->PixelHeight
* DataSizePerLine
)) {
390 return EFI_INVALID_PARAMETER
;
394 // Calculate Color Map offset in the image.
397 BmpColorMap
= (BMP_COLOR_MAP
*) (Image
+ sizeof (BMP_IMAGE_HEADER
));
398 if (BmpHeader
->ImageOffset
< sizeof (BMP_IMAGE_HEADER
)) {
399 return EFI_INVALID_PARAMETER
;
402 if (BmpHeader
->ImageOffset
> sizeof (BMP_IMAGE_HEADER
)) {
403 switch (BmpHeader
->BitPerPixel
) {
418 // BMP file may has padding data between the bmp header section and the bmp data section.
420 if (BmpHeader
->ImageOffset
- sizeof (BMP_IMAGE_HEADER
) < sizeof (BMP_COLOR_MAP
) * ColorMapNum
) {
421 return EFI_INVALID_PARAMETER
;
426 // Calculate graphics image data address in the image
428 Image
= ((UINT8
*) BmpImage
) + BmpHeader
->ImageOffset
;
432 // Calculate the BltBuffer needed size.
434 BltBufferSize
= MultU64x32 ((UINT64
) BmpHeader
->PixelWidth
, BmpHeader
->PixelHeight
);
436 // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
438 if (BltBufferSize
> DivU64x32 ((UINTN
) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
))) {
439 return EFI_UNSUPPORTED
;
441 BltBufferSize
= MultU64x32 (BltBufferSize
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
444 if (*GopBlt
== NULL
) {
446 // GopBlt is not allocated by caller.
448 *GopBltSize
= (UINTN
) BltBufferSize
;
449 *GopBlt
= AllocatePool (*GopBltSize
);
451 if (*GopBlt
== NULL
) {
452 return EFI_OUT_OF_RESOURCES
;
456 // GopBlt has been allocated by caller.
458 if (*GopBltSize
< (UINTN
) BltBufferSize
) {
459 *GopBltSize
= (UINTN
) BltBufferSize
;
460 return EFI_BUFFER_TOO_SMALL
;
464 *PixelWidth
= BmpHeader
->PixelWidth
;
465 *PixelHeight
= BmpHeader
->PixelHeight
;
468 // Convert image from BMP to Blt buffer format
471 for (Height
= 0; Height
< BmpHeader
->PixelHeight
; Height
++) {
472 Blt
= &BltBuffer
[(BmpHeader
->PixelHeight
- Height
- 1) * BmpHeader
->PixelWidth
];
473 for (Width
= 0; Width
< BmpHeader
->PixelWidth
; Width
++, Image
++, Blt
++) {
474 switch (BmpHeader
->BitPerPixel
) {
477 // Convert 1-bit (2 colors) BMP to 24-bit color
479 for (Index
= 0; Index
< 8 && Width
< BmpHeader
->PixelWidth
; Index
++) {
480 Blt
->Red
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Red
;
481 Blt
->Green
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Green
;
482 Blt
->Blue
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Blue
;
493 // Convert 4-bit (16 colors) BMP Palette to 24-bit color
495 Index
= (*Image
) >> 4;
496 Blt
->Red
= BmpColorMap
[Index
].Red
;
497 Blt
->Green
= BmpColorMap
[Index
].Green
;
498 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
499 if (Width
< (BmpHeader
->PixelWidth
- 1)) {
502 Index
= (*Image
) & 0x0f;
503 Blt
->Red
= BmpColorMap
[Index
].Red
;
504 Blt
->Green
= BmpColorMap
[Index
].Green
;
505 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
511 // Convert 8-bit (256 colors) BMP Palette to 24-bit color
513 Blt
->Red
= BmpColorMap
[*Image
].Red
;
514 Blt
->Green
= BmpColorMap
[*Image
].Green
;
515 Blt
->Blue
= BmpColorMap
[*Image
].Blue
;
522 Blt
->Blue
= *Image
++;
523 Blt
->Green
= *Image
++;
529 // it is 32-bit BMP. Skip pixel's highest byte
531 Blt
->Blue
= *Image
++;
532 Blt
->Green
= *Image
++;
538 // Other bit format BMP is not supported.
544 return EFI_UNSUPPORTED
;
549 ImageIndex
= (UINTN
) Image
- (UINTN
) ImageHeader
;
550 if ((ImageIndex
% 4) != 0) {
552 // Bmp Image starts each row on a 32-bit boundary!
554 Image
= Image
+ (4 - (ImageIndex
% 4));
563 Those capsules supported by the firmwares.
565 Caution: This function may receive untrusted input.
567 @param[in] CapsuleHeader Points to a capsule header.
569 @retval EFI_SUCESS Input capsule is supported by firmware.
570 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
573 DisplayCapsuleImage (
574 IN EFI_CAPSULE_HEADER
*CapsuleHeader
577 DISPLAY_DISPLAY_PAYLOAD
*ImagePayload
;
580 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
584 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
586 ImagePayload
= (DISPLAY_DISPLAY_PAYLOAD
*)(CapsuleHeader
+ 1);
587 PayloadSize
= CapsuleHeader
->CapsuleImageSize
- sizeof(EFI_CAPSULE_HEADER
);
589 if (ImagePayload
->Version
!= 1) {
590 return EFI_UNSUPPORTED
;
592 if (CalculateCheckSum8((UINT8
*)CapsuleHeader
, CapsuleHeader
->CapsuleImageSize
) != 0) {
593 return EFI_UNSUPPORTED
;
596 // Only Support Bitmap by now
598 if (ImagePayload
->ImageType
!= 0) {
599 return EFI_UNSUPPORTED
;
605 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**)&GraphicsOutput
);
606 if (EFI_ERROR (Status
)) {
607 Status
= gBS
->LocateProtocol(&gEfiGraphicsOutputProtocolGuid
, NULL
, (VOID
**)&GraphicsOutput
);
608 if (EFI_ERROR(Status
)) {
609 return EFI_UNSUPPORTED
;
613 if (GraphicsOutput
->Mode
->Mode
!= ImagePayload
->Mode
) {
614 return EFI_UNSUPPORTED
;
620 Status
= ConvertBmpToGopBlt (
622 PayloadSize
- sizeof(DISPLAY_DISPLAY_PAYLOAD
),
629 if (EFI_ERROR (Status
)) {
633 Status
= GraphicsOutput
->Blt (
639 (UINTN
) ImagePayload
->OffsetX
,
640 (UINTN
) ImagePayload
->OffsetY
,
643 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
652 Dump FMP information.
654 @param[in] ImageInfoSize The size of ImageInfo, in bytes.
655 @param[in] ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
656 @param[in] DescriptorVersion The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
657 @param[in] DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
658 @param[in] DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
659 @param[in] PackageVersion The version of package.
660 @param[in] PackageVersionName The version name of package.
664 IN UINTN ImageInfoSize
,
665 IN EFI_FIRMWARE_IMAGE_DESCRIPTOR
*ImageInfo
,
666 IN UINT32 DescriptorVersion
,
667 IN UINT8 DescriptorCount
,
668 IN UINTN DescriptorSize
,
669 IN UINT32 PackageVersion
,
670 IN CHAR16
*PackageVersionName
673 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*CurrentImageInfo
;
676 DEBUG((DEBUG_VERBOSE
, " DescriptorVersion - 0x%x\n", DescriptorVersion
));
677 DEBUG((DEBUG_VERBOSE
, " DescriptorCount - 0x%x\n", DescriptorCount
));
678 DEBUG((DEBUG_VERBOSE
, " DescriptorSize - 0x%x\n", DescriptorSize
));
679 DEBUG((DEBUG_VERBOSE
, " PackageVersion - 0x%x\n", PackageVersion
));
680 DEBUG((DEBUG_VERBOSE
, " PackageVersionName - %s\n\n", PackageVersionName
));
681 CurrentImageInfo
= ImageInfo
;
682 for (Index
= 0; Index
< DescriptorCount
; Index
++) {
683 DEBUG((DEBUG_VERBOSE
, " ImageDescriptor (%d)\n", Index
));
684 DEBUG((DEBUG_VERBOSE
, " ImageIndex - 0x%x\n", CurrentImageInfo
->ImageIndex
));
685 DEBUG((DEBUG_VERBOSE
, " ImageTypeId - %g\n", &CurrentImageInfo
->ImageTypeId
));
686 DEBUG((DEBUG_VERBOSE
, " ImageId - 0x%lx\n", CurrentImageInfo
->ImageId
));
687 DEBUG((DEBUG_VERBOSE
, " ImageIdName - %s\n", CurrentImageInfo
->ImageIdName
));
688 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", CurrentImageInfo
->Version
));
689 DEBUG((DEBUG_VERBOSE
, " VersionName - %s\n", CurrentImageInfo
->VersionName
));
690 DEBUG((DEBUG_VERBOSE
, " Size - 0x%x\n", CurrentImageInfo
->Size
));
691 DEBUG((DEBUG_VERBOSE
, " AttributesSupported - 0x%lx\n", CurrentImageInfo
->AttributesSupported
));
692 DEBUG((DEBUG_VERBOSE
, " AttributesSetting - 0x%lx\n", CurrentImageInfo
->AttributesSetting
));
693 DEBUG((DEBUG_VERBOSE
, " Compatibilities - 0x%lx\n", CurrentImageInfo
->Compatibilities
));
694 if (DescriptorVersion
> 1) {
695 DEBUG((DEBUG_VERBOSE
, " LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo
->LowestSupportedImageVersion
));
696 if (DescriptorVersion
> 2) {
697 DEBUG((DEBUG_VERBOSE
, " LastAttemptVersion - 0x%x\n", CurrentImageInfo
->LastAttemptVersion
));
698 DEBUG((DEBUG_VERBOSE
, " LastAttemptStatus - 0x%x\n", CurrentImageInfo
->LastAttemptStatus
));
699 DEBUG((DEBUG_VERBOSE
, " HardwareInstance - 0x%lx\n", CurrentImageInfo
->HardwareInstance
));
703 // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
705 CurrentImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)CurrentImageInfo
+ DescriptorSize
);
710 Dump a non-nested FMP capsule.
712 @param[in] CapsuleHeader A pointer to CapsuleHeader
716 IN EFI_CAPSULE_HEADER
*CapsuleHeader
719 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
720 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
722 UINT64
*ItemOffsetList
;
724 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
726 DEBUG((DEBUG_VERBOSE
, "FmpCapsule:\n"));
727 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", FmpCapsuleHeader
->Version
));
728 DEBUG((DEBUG_VERBOSE
, " EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader
->EmbeddedDriverCount
));
729 DEBUG((DEBUG_VERBOSE
, " PayloadItemCount - 0x%x\n", FmpCapsuleHeader
->PayloadItemCount
));
731 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
732 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
733 DEBUG((DEBUG_VERBOSE
, " ItemOffsetList[%d] - 0x%lx\n", Index
, ItemOffsetList
[Index
]));
735 for (; Index
< (UINT32
)FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
; Index
++) {
736 DEBUG((DEBUG_VERBOSE
, " ItemOffsetList[%d] - 0x%lx\n", Index
, ItemOffsetList
[Index
]));
737 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
739 DEBUG((DEBUG_VERBOSE
, " ImageHeader:\n"));
740 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", ImageHeader
->Version
));
741 DEBUG((DEBUG_VERBOSE
, " UpdateImageTypeId - %g\n", &ImageHeader
->UpdateImageTypeId
));
742 DEBUG((DEBUG_VERBOSE
, " UpdateImageIndex - 0x%x\n", ImageHeader
->UpdateImageIndex
));
743 DEBUG((DEBUG_VERBOSE
, " UpdateImageSize - 0x%x\n", ImageHeader
->UpdateImageSize
));
744 DEBUG((DEBUG_VERBOSE
, " UpdateVendorCodeSize - 0x%x\n", ImageHeader
->UpdateVendorCodeSize
));
745 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
746 DEBUG((DEBUG_VERBOSE
, " UpdateHardwareInstance - 0x%lx\n", ImageHeader
->UpdateHardwareInstance
));
752 Dump all FMP information.
760 EFI_HANDLE
*HandleBuffer
;
761 UINTN NumberOfHandles
;
762 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
765 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
766 UINT32 FmpImageInfoDescriptorVer
;
767 UINT8 FmpImageInfoCount
;
768 UINTN DescriptorSize
;
769 UINT32 PackageVersion
;
770 CHAR16
*PackageVersionName
;
772 Status
= gBS
->LocateHandleBuffer (
774 &gEfiFirmwareManagementProtocolGuid
,
779 if (EFI_ERROR(Status
)) {
783 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
784 Status
= gBS
->HandleProtocol(
786 &gEfiFirmwareManagementProtocolGuid
,
789 if (EFI_ERROR(Status
)) {
794 Status
= Fmp
->GetImageInfo (
804 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
808 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
809 if (FmpImageInfoBuf
== NULL
) {
813 PackageVersionName
= NULL
;
814 Status
= Fmp
->GetImageInfo (
816 &ImageInfoSize
, // ImageInfoSize
817 FmpImageInfoBuf
, // ImageInfo
818 &FmpImageInfoDescriptorVer
, // DescriptorVersion
819 &FmpImageInfoCount
, // DescriptorCount
820 &DescriptorSize
, // DescriptorSize
821 &PackageVersion
, // PackageVersion
822 &PackageVersionName
// PackageVersionName
824 if (EFI_ERROR(Status
)) {
825 FreePool(FmpImageInfoBuf
);
829 DEBUG((DEBUG_INFO
, "FMP (%d) ImageInfo:\n", Index
));
831 ImageInfoSize
, // ImageInfoSize
832 FmpImageInfoBuf
, // ImageInfo
833 FmpImageInfoDescriptorVer
, // DescriptorVersion
834 FmpImageInfoCount
, // DescriptorCount
835 DescriptorSize
, // DescriptorSize
836 PackageVersion
, // PackageVersion
837 PackageVersionName
// PackageVersionName
840 if (PackageVersionName
!= NULL
) {
841 FreePool(PackageVersionName
);
844 FreePool(FmpImageInfoBuf
);
851 Get FMP handle by ImageTypeId and HardwareInstance.
853 @param[in] UpdateImageTypeId Used to identify device firmware targeted by this update.
854 @param[in] UpdateHardwareInstance The HardwareInstance to target with this update.
855 @param[in,out] NoHandles The number of handles returned in Buffer.
856 @param[out] Buffer[out] A pointer to the buffer to return the requested array of handles.
858 @retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of
859 handles in Buffer was returned in NoHandles.
860 @retval EFI_NOT_FOUND No handles match the search.
861 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
864 GetFmpHandleBufferByType (
865 IN EFI_GUID
*UpdateImageTypeId
,
866 IN UINT64 UpdateHardwareInstance
,
867 IN OUT UINTN
*NoHandles
,
868 OUT EFI_HANDLE
**Buffer
872 EFI_HANDLE
*HandleBuffer
;
873 UINTN NumberOfHandles
;
874 EFI_HANDLE
*MatchedHandleBuffer
;
875 UINTN MatchedNumberOfHandles
;
876 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
879 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
880 UINT32 FmpImageInfoDescriptorVer
;
881 UINT8 FmpImageInfoCount
;
882 UINTN DescriptorSize
;
883 UINT32 PackageVersion
;
884 CHAR16
*PackageVersionName
;
886 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*TempFmpImageInfo
;
891 Status
= gBS
->LocateHandleBuffer (
893 &gEfiFirmwareManagementProtocolGuid
,
898 if (EFI_ERROR(Status
)) {
902 MatchedNumberOfHandles
= 0;
903 MatchedHandleBuffer
= AllocateZeroPool (sizeof(EFI_HANDLE
) * NumberOfHandles
);
904 if (MatchedHandleBuffer
== NULL
) {
905 FreePool (HandleBuffer
);
906 return EFI_OUT_OF_RESOURCES
;
909 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
910 Status
= gBS
->HandleProtocol(
912 &gEfiFirmwareManagementProtocolGuid
,
915 if (EFI_ERROR(Status
)) {
920 Status
= Fmp
->GetImageInfo (
930 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
934 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
935 if (FmpImageInfoBuf
== NULL
) {
939 PackageVersionName
= NULL
;
940 Status
= Fmp
->GetImageInfo (
942 &ImageInfoSize
, // ImageInfoSize
943 FmpImageInfoBuf
, // ImageInfo
944 &FmpImageInfoDescriptorVer
, // DescriptorVersion
945 &FmpImageInfoCount
, // DescriptorCount
946 &DescriptorSize
, // DescriptorSize
947 &PackageVersion
, // PackageVersion
948 &PackageVersionName
// PackageVersionName
950 if (EFI_ERROR(Status
)) {
951 FreePool(FmpImageInfoBuf
);
955 if (PackageVersionName
!= NULL
) {
956 FreePool(PackageVersionName
);
959 TempFmpImageInfo
= FmpImageInfoBuf
;
960 for (Index2
= 0; Index2
< FmpImageInfoCount
; Index2
++) {
962 // Check if this FMP instance matches
964 if (CompareGuid(UpdateImageTypeId
, &TempFmpImageInfo
->ImageTypeId
)) {
965 if ((UpdateHardwareInstance
== 0) ||
966 ((FmpImageInfoDescriptorVer
>= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
) &&
967 (UpdateHardwareInstance
== TempFmpImageInfo
->HardwareInstance
))) {
968 MatchedHandleBuffer
[MatchedNumberOfHandles
] = HandleBuffer
[Index
];
969 MatchedNumberOfHandles
++;
973 TempFmpImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)TempFmpImageInfo
+ DescriptorSize
);
975 FreePool(FmpImageInfoBuf
);
978 if (MatchedNumberOfHandles
== 0) {
979 return EFI_NOT_FOUND
;
982 *NoHandles
= MatchedNumberOfHandles
;
983 *Buffer
= MatchedHandleBuffer
;
989 Return FmpImageInfoDescriptorVer by an FMP handle.
991 @param[in] Handle A FMP handle.
993 @return FmpImageInfoDescriptorVer associated with the FMP.
996 GetFmpImageInfoDescriptorVer (
1001 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
1002 UINTN ImageInfoSize
;
1003 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
1004 UINT32 FmpImageInfoDescriptorVer
;
1005 UINT8 FmpImageInfoCount
;
1006 UINTN DescriptorSize
;
1007 UINT32 PackageVersion
;
1008 CHAR16
*PackageVersionName
;
1010 Status
= gBS
->HandleProtocol(
1012 &gEfiFirmwareManagementProtocolGuid
,
1015 if (EFI_ERROR(Status
)) {
1020 Status
= Fmp
->GetImageInfo (
1030 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1034 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
1035 if (FmpImageInfoBuf
== NULL
) {
1039 PackageVersionName
= NULL
;
1040 Status
= Fmp
->GetImageInfo (
1042 &ImageInfoSize
, // ImageInfoSize
1043 FmpImageInfoBuf
, // ImageInfo
1044 &FmpImageInfoDescriptorVer
, // DescriptorVersion
1045 &FmpImageInfoCount
, // DescriptorCount
1046 &DescriptorSize
, // DescriptorSize
1047 &PackageVersion
, // PackageVersion
1048 &PackageVersionName
// PackageVersionName
1050 if (EFI_ERROR(Status
)) {
1051 FreePool(FmpImageInfoBuf
);
1054 return FmpImageInfoDescriptorVer
;
1060 @param[in] Handle A FMP handle.
1061 @param[in] ImageHeader The payload image header.
1062 @param[in] PayloadIndex The index of the payload.
1064 @return The status of FMP->SetImage.
1068 IN EFI_HANDLE Handle
,
1069 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
,
1070 IN UINTN PayloadIndex
1074 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
1077 CHAR16
*AbortReason
;
1079 Status
= gBS
->HandleProtocol(
1081 &gEfiFirmwareManagementProtocolGuid
,
1084 if (EFI_ERROR(Status
)) {
1088 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
1089 Image
= (UINT8
*)(ImageHeader
+ 1);
1092 // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1,
1093 // Header should exclude UpdateHardwareInstance field
1095 Image
= (UINT8
*)ImageHeader
+ OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
1098 if (ImageHeader
->UpdateVendorCodeSize
== 0) {
1101 VendorCode
= Image
+ ImageHeader
->UpdateImageSize
;
1104 DEBUG((DEBUG_INFO
, "Fmp->SetImage ...\n"));
1105 DEBUG((DEBUG_INFO
, "ImageTypeId - %g, ", &ImageHeader
->UpdateImageTypeId
));
1106 DEBUG((DEBUG_INFO
, "PayloadIndex - 0x%x, ", PayloadIndex
));
1107 DEBUG((DEBUG_INFO
, "ImageIndex - 0x%x ", ImageHeader
->UpdateImageIndex
));
1108 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
1109 DEBUG((DEBUG_INFO
, "(UpdateHardwareInstance - 0x%x)", ImageHeader
->UpdateHardwareInstance
));
1111 DEBUG((DEBUG_INFO
, "\n"));
1112 Status
= Fmp
->SetImage(
1114 ImageHeader
->UpdateImageIndex
, // ImageIndex
1116 ImageHeader
->UpdateImageSize
, // ImageSize
1117 VendorCode
, // VendorCode
1118 Update_Image_Progress
, // Progress
1119 &AbortReason
// AbortReason
1121 DEBUG((DEBUG_INFO
, "Fmp->SetImage - %r\n", Status
));
1122 if (AbortReason
!= NULL
) {
1123 DEBUG ((DEBUG_ERROR
, "%s\n", AbortReason
));
1124 FreePool(AbortReason
);
1131 Start a UEFI image in the FMP payload.
1133 @param[in] ImageBuffer A pointer to the memory location containing a copy of the image to be loaded..
1134 @param[in] ImageSize The size in bytes of ImageBuffer.
1136 @return The status of gBS->LoadImage and gBS->StartImage.
1140 IN VOID
*ImageBuffer
,
1144 MEMMAP_DEVICE_PATH MemMapNode
;
1146 EFI_HANDLE ImageHandle
;
1147 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
1150 SetDevicePathNodeLength (&MemMapNode
.Header
, sizeof (MemMapNode
));
1151 MemMapNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
1152 MemMapNode
.Header
.SubType
= HW_MEMMAP_DP
;
1153 MemMapNode
.MemoryType
= EfiBootServicesCode
;
1154 MemMapNode
.StartingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)ImageBuffer
;
1155 MemMapNode
.EndingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)((UINT8
*)ImageBuffer
+ ImageSize
- 1);
1157 DriverDevicePath
= AppendDevicePathNode (NULL
, &MemMapNode
.Header
);
1158 if (DriverDevicePath
== NULL
) {
1159 return EFI_OUT_OF_RESOURCES
;
1162 DEBUG((DEBUG_INFO
, "FmpCapsule: LoadImage ...\n"));
1163 Status
= gBS
->LoadImage(
1171 DEBUG((DEBUG_INFO
, "FmpCapsule: LoadImage - %r\n", Status
));
1172 if (EFI_ERROR(Status
)) {
1173 FreePool(DriverDevicePath
);
1177 DEBUG((DEBUG_INFO
, "FmpCapsule: StartImage ...\n"));
1178 Status
= gBS
->StartImage(
1183 DEBUG((DEBUG_INFO
, "FmpCapsule: StartImage - %r\n", Status
));
1184 if (EFI_ERROR(Status
)) {
1185 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
1188 FreePool(DriverDevicePath
);
1193 Record FMP capsule status.
1195 @param[in] Handle A FMP handle.
1196 @param[in] CapsuleHeader The capsule image header
1197 @param[in] CapsuleStatus The capsule process stauts
1198 @param[in] PayloadIndex FMP payload index
1199 @param[in] ImageHeader FMP image header
1202 RecordFmpCapsuleStatus (
1203 IN EFI_HANDLE Handle
, OPTIONAL
1204 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
1205 IN EFI_STATUS CapsuleStatus
,
1206 IN UINTN PayloadIndex
,
1207 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
1211 EFI_DEVICE_PATH_PROTOCOL
*FmpDevicePath
;
1212 UINT32 FmpImageInfoDescriptorVer
;
1213 EFI_STATUS StatusEsrt
;
1214 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
1215 EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry
;
1217 FmpDevicePath
= NULL
;
1218 if (Handle
!= NULL
) {
1219 gBS
->HandleProtocol(
1221 &gEfiDevicePathProtocolGuid
,
1222 (VOID
**)&FmpDevicePath
1226 RecordFmpCapsuleStatusVariable (
1235 // Update corresponding ESRT entry LastAttemp Status
1237 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
1238 if (EFI_ERROR (Status
)) {
1242 if (Handle
== NULL
) {
1247 // Update EsrtEntry For V1, V2 FMP instance.
1248 // V3 FMP ESRT cache will be synced up through EsrtSyncFmp interface
1250 FmpImageInfoDescriptorVer
= GetFmpImageInfoDescriptorVer (Handle
);
1251 if (FmpImageInfoDescriptorVer
< EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
) {
1252 StatusEsrt
= EsrtProtocol
->GetEsrtEntry(&ImageHeader
->UpdateImageTypeId
, &EsrtEntry
);
1253 if (!EFI_ERROR(StatusEsrt
)){
1254 if (!EFI_ERROR(CapsuleStatus
)) {
1255 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_SUCCESS
;
1257 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL
;
1259 EsrtEntry
.LastAttemptVersion
= 0;
1260 EsrtProtocol
->UpdateEsrtEntry(&EsrtEntry
);
1266 Process Firmware management protocol data capsule.
1268 This function assumes the caller validated the capsule by using
1269 ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
1270 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
1271 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
1273 This function need support nested FMP capsule.
1275 @param[in] CapsuleHeader Points to a capsule header.
1277 @retval EFI_SUCESS Process Capsule Image successfully.
1278 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1279 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1280 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1281 @retval EFI_NOT_READY No FMP protocol to handle this FMP capsule.
1284 ProcessFmpCapsuleImage (
1285 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1289 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
1290 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
1291 UINT64
*ItemOffsetList
;
1294 EFI_HANDLE
*HandleBuffer
;
1295 UINTN NumberOfHandles
;
1297 UINT64 UpdateHardwareInstance
;
1302 if (!IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
1303 return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
));
1309 DumpFmpCapsule(CapsuleHeader
);
1311 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
1313 if (FmpCapsuleHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
1314 return EFI_INVALID_PARAMETER
;
1316 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
1318 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
1321 // capsule in which driver count and payload count are both zero is not processed.
1328 // 1. Try to load & start all the drivers within capsule
1330 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
1331 if ((FmpCapsuleHeader
->PayloadItemCount
== 0) &&
1332 (Index
== (UINTN
)FmpCapsuleHeader
->EmbeddedDriverCount
- 1)) {
1334 // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
1336 DriverLen
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
- (UINTN
)ItemOffsetList
[Index
];
1338 DriverLen
= (UINTN
)ItemOffsetList
[Index
+ 1] - (UINTN
)ItemOffsetList
[Index
];
1341 Status
= StartFmpImage (
1342 (UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
],
1345 if (EFI_ERROR(Status
)) {
1346 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
1352 // 2. Route payload to right FMP instance
1354 DEBUG((DEBUG_INFO
, "FmpCapsule: route payload to right FMP instance ...\n"));
1359 // Check all the payload entry in capsule payload list
1361 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
1362 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
1364 UpdateHardwareInstance
= 0;
1365 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
1366 UpdateHardwareInstance
= ImageHeader
->UpdateHardwareInstance
;
1369 Status
= GetFmpHandleBufferByType (
1370 &ImageHeader
->UpdateImageTypeId
,
1371 UpdateHardwareInstance
,
1375 if (EFI_ERROR(Status
)) {
1377 RecordFmpCapsuleStatus (
1381 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1387 for (Index2
= 0; Index2
< NumberOfHandles
; Index2
++) {
1389 RecordFmpCapsuleStatus (
1390 HandleBuffer
[Index2
],
1393 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1399 Status
= SetFmpImageData (
1400 HandleBuffer
[Index2
],
1402 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
1404 if (Status
!= EFI_SUCCESS
) {
1408 RecordFmpCapsuleStatus (
1409 HandleBuffer
[Index2
],
1412 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1416 if (HandleBuffer
!= NULL
) {
1417 FreePool(HandleBuffer
);
1422 return EFI_NOT_READY
;
1426 // always return SUCCESS to indicate this capsule is processed.
1427 // The status of SetImage is recorded in capsule result variable.
1433 Return if there is a FMP header below capsule header.
1435 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1437 @retval TRUE There is a FMP header below capsule header.
1438 @retval FALSE There is not a FMP header below capsule header
1441 IsNestedFmpCapsule (
1442 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1446 EFI_SYSTEM_RESOURCE_TABLE
*Esrt
;
1447 EFI_SYSTEM_RESOURCE_ENTRY
*EsrtEntry
;
1449 BOOLEAN EsrtGuidFound
;
1450 EFI_CAPSULE_HEADER
*NestedCapsuleHeader
;
1451 UINTN NestedCapsuleSize
;
1452 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
1453 EFI_SYSTEM_RESOURCE_ENTRY Entry
;
1455 EsrtGuidFound
= FALSE
;
1456 if (mIsVirtualAddrConverted
) {
1457 if(mEsrtTable
!= NULL
) {
1458 EsrtEntry
= (EFI_SYSTEM_RESOURCE_ENTRY
*)(mEsrtTable
+ 1);
1459 for (Index
= 0; Index
< mEsrtTable
->FwResourceCount
; Index
++, EsrtEntry
++) {
1460 if (CompareGuid(&EsrtEntry
->FwClass
, &CapsuleHeader
->CapsuleGuid
)) {
1461 EsrtGuidFound
= TRUE
;
1468 // Check ESRT protocol
1470 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
1471 if (!EFI_ERROR(Status
)) {
1472 Status
= EsrtProtocol
->GetEsrtEntry(&CapsuleHeader
->CapsuleGuid
, &Entry
);
1473 if (!EFI_ERROR(Status
)) {
1474 EsrtGuidFound
= TRUE
;
1479 // Check ESRT configuration table
1481 if (!EsrtGuidFound
) {
1482 Status
= EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid
, (VOID
**)&Esrt
);
1483 if (!EFI_ERROR(Status
)) {
1484 ASSERT (Esrt
!= NULL
);
1485 EsrtEntry
= (VOID
*)(Esrt
+ 1);
1486 for (Index
= 0; Index
< Esrt
->FwResourceCount
; Index
++, EsrtEntry
++) {
1487 if (CompareGuid(&EsrtEntry
->FwClass
, &CapsuleHeader
->CapsuleGuid
)) {
1488 EsrtGuidFound
= TRUE
;
1495 if (!EsrtGuidFound
) {
1500 // Check nested capsule header
1501 // FMP GUID after ESRT one
1503 NestedCapsuleHeader
= (EFI_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
1504 NestedCapsuleSize
= (UINTN
)CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
- (UINTN
)NestedCapsuleHeader
;
1505 if (NestedCapsuleSize
< sizeof(EFI_CAPSULE_HEADER
)) {
1508 if (!IsValidCapsuleHeader(NestedCapsuleHeader
, NestedCapsuleSize
)) {
1511 if (!IsFmpCapsuleGuid(&NestedCapsuleHeader
->CapsuleGuid
)) {
1514 DEBUG ((DEBUG_INFO
, "IsNestedFmpCapsule\n"));
1519 Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
1521 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1523 @retval TRUE It is a system FMP.
1524 @retval FALSE It is a device FMP.
1528 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1531 if (IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
1534 if (IsNestedFmpCapsule(CapsuleHeader
)) {
1541 Those capsules supported by the firmwares.
1543 Caution: This function may receive untrusted input.
1545 @param[in] CapsuleHeader Points to a capsule header.
1547 @retval EFI_SUCESS Input capsule is supported by firmware.
1548 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
1549 @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
1553 SupportCapsuleImage (
1554 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1558 // check Display Capsule Guid
1560 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1564 if (IsFmpCapsule(CapsuleHeader
)) {
1566 // Check layout of FMP capsule
1568 return ValidateFmpCapsule(CapsuleHeader
, NULL
);
1570 DEBUG((DEBUG_ERROR
, "Unknown Capsule Guid - %g\n", &CapsuleHeader
->CapsuleGuid
));
1571 return EFI_UNSUPPORTED
;
1575 The firmware implements to process the capsule image.
1577 Caution: This function may receive untrusted input.
1579 @param[in] CapsuleHeader Points to a capsule header.
1581 @retval EFI_SUCESS Process Capsule Image successfully.
1582 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1583 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1584 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1588 ProcessCapsuleImage (
1589 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1594 if (SupportCapsuleImage (CapsuleHeader
) != EFI_SUCCESS
) {
1595 RecordCapsuleStatusVariable(CapsuleHeader
, EFI_UNSUPPORTED
);
1596 return EFI_UNSUPPORTED
;
1600 // Display image in firmware update display capsule
1602 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1603 DEBUG((DEBUG_INFO
, "ProcessCapsuleImage for WindowsUxCapsule ...\n"));
1604 Status
= DisplayCapsuleImage(CapsuleHeader
);
1605 RecordCapsuleStatusVariable(CapsuleHeader
, Status
);
1610 // Check FMP capsule layout
1612 if (IsFmpCapsule (CapsuleHeader
)) {
1613 DEBUG((DEBUG_INFO
, "ProcessCapsuleImage for FmpCapsule ...\n"));
1614 DEBUG((DEBUG_INFO
, "ValidateFmpCapsule ...\n"));
1615 Status
= ValidateFmpCapsule(CapsuleHeader
, NULL
);
1616 DEBUG((DEBUG_INFO
, "ValidateFmpCapsule - %r\n", Status
));
1617 if (EFI_ERROR(Status
)) {
1618 RecordCapsuleStatusVariable(CapsuleHeader
, Status
);
1623 // Press EFI FMP Capsule
1625 DEBUG((DEBUG_INFO
, "ProcessFmpCapsuleImage ...\n"));
1626 Status
= ProcessFmpCapsuleImage(CapsuleHeader
);
1627 DEBUG((DEBUG_INFO
, "ProcessFmpCapsuleImage - %r\n", Status
));
1632 return EFI_UNSUPPORTED
;
1636 Callback function executed when the EndOfDxe event group is signaled.
1638 @param[in] Event Event whose notification function is being invoked.
1639 @param[in] Context The pointer to the notification function's context, which
1640 is implementation-dependent.
1644 DxeCapsuleLibEndOfDxe (
1649 mDxeCapsuleLibEndOfDxe
= TRUE
;
1653 The constructor function.
1655 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1656 @param[in] SystemTable A pointer to the EFI System Table.
1658 @retval EFI_SUCCESS The constructor successfully .
1662 DxeCapsuleLibConstructor (
1663 IN EFI_HANDLE ImageHandle
,
1664 IN EFI_SYSTEM_TABLE
*SystemTable
1669 Status
= gBS
->CreateEventEx (
1672 DxeCapsuleLibEndOfDxe
,
1674 &gEfiEndOfDxeEventGroupGuid
,
1675 &mDxeCapsuleLibEndOfDxeEvent
1677 ASSERT_EFI_ERROR (Status
);
1679 InitCapsuleVariable();
1685 The destructor function closes the End of DXE event.
1687 @param ImageHandle The firmware allocated handle for the EFI image.
1688 @param SystemTable A pointer to the EFI System Table.
1690 @retval EFI_SUCCESS The destructor completed successfully.
1694 DxeCapsuleLibDestructor (
1695 IN EFI_HANDLE ImageHandle
,
1696 IN EFI_SYSTEM_TABLE
*SystemTable
1702 // Close the End of DXE event.
1704 Status
= gBS
->CloseEvent (mDxeCapsuleLibEndOfDxeEvent
);
1705 ASSERT_EFI_ERROR (Status
);