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, 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 mAreAllImagesProcessed
;
52 EFI_SYSTEM_RESOURCE_TABLE
*mEsrtTable
= NULL
;
53 BOOLEAN mIsVirtualAddrConverted
= FALSE
;
54 BOOLEAN mDxeCapsuleLibEndOfDxe
= FALSE
;
57 Initialize capsule related variables.
65 Check if this FMP capsule is processed.
67 @param[in] CapsuleHeader The capsule image header
68 @param[in] PayloadIndex FMP payload index
69 @param[in] ImageHeader FMP image header
71 @retval TRUE This FMP capsule is processed.
72 @retval FALSE This FMP capsule is not processed.
75 IsFmpCapsuleProcessed (
76 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
77 IN UINTN PayloadIndex
,
78 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
82 Record capsule status variable.
84 @param[in] CapsuleHeader The capsule image header
85 @param[in] CapsuleStatus The capsule process stauts
87 @retval EFI_SUCCESS The capsule status variable is recorded.
88 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
91 RecordCapsuleStatusVariable (
92 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
93 IN EFI_STATUS CapsuleStatus
97 Record FMP capsule status variable.
99 @param[in] CapsuleHeader The capsule image header
100 @param[in] CapsuleStatus The capsule process stauts
101 @param[in] PayloadIndex FMP payload index
102 @param[in] ImageHeader FMP image header
103 @param[in] FmpDevicePath DevicePath associated with the FMP producer
105 @retval EFI_SUCCESS The capsule status variable is recorded.
106 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
109 RecordFmpCapsuleStatusVariable (
110 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
111 IN EFI_STATUS CapsuleStatus
,
112 IN UINTN PayloadIndex
,
113 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
,
114 IN EFI_DEVICE_PATH_PROTOCOL
*FmpDevicePath OPTIONAL
118 Function indicate the current completion progress of the firmware
119 update. Platform may override with own specific progress function.
121 @param[in] Completion A value between 1 and 100 indicating the current completion progress of the firmware update
123 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
127 Update_Image_Progress (
135 Return if this CapsuleGuid is a FMP capsule GUID or not.
137 @param[in] CapsuleGuid A pointer to EFI_GUID
139 @retval TRUE It is a FMP capsule GUID.
140 @retval FALSE It is not a FMP capsule GUID.
144 IN EFI_GUID
*CapsuleGuid
147 if (CompareGuid(&gEfiFmpCapsuleGuid
, CapsuleGuid
)) {
155 Validate if it is valid capsule header
157 Caution: This function may receive untrusted input.
159 This function assumes the caller provided correct CapsuleHeader pointer
162 This function validates the fields in EFI_CAPSULE_HEADER.
164 @param[in] CapsuleHeader Points to a capsule header.
165 @param[in] CapsuleSize Size of the whole capsule image.
169 IsValidCapsuleHeader (
170 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
171 IN UINT64 CapsuleSize
174 if (CapsuleHeader
->CapsuleImageSize
!= CapsuleSize
) {
177 if (CapsuleHeader
->HeaderSize
>= CapsuleHeader
->CapsuleImageSize
) {
184 Validate Fmp capsules layout.
186 Caution: This function may receive untrusted input.
188 This function assumes the caller validated the capsule by using
189 IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.
190 The capsule buffer size is CapsuleHeader->CapsuleImageSize.
192 This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
193 and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
195 This function need support nested FMP capsule.
197 @param[in] CapsuleHeader Points to a capsule header.
198 @param[out] EmbeddedDriverCount The EmbeddedDriverCount in the FMP capsule.
200 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
201 @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.
205 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
206 OUT UINT16
*EmbeddedDriverCount OPTIONAL
209 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
211 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
213 UINT64
*ItemOffsetList
;
216 UINTN FmpCapsuleSize
;
217 UINTN FmpCapsuleHeaderSize
;
219 UINTN FmpImageHeaderSize
;
221 if (!IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
222 return ValidateFmpCapsule ((EFI_CAPSULE_HEADER
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
), EmbeddedDriverCount
);
225 if (CapsuleHeader
->HeaderSize
>= CapsuleHeader
->CapsuleImageSize
) {
226 DEBUG((DEBUG_ERROR
, "HeaderSize(0x%x) >= CapsuleImageSize(0x%x)\n", CapsuleHeader
->HeaderSize
, CapsuleHeader
->CapsuleImageSize
));
227 return EFI_INVALID_PARAMETER
;
230 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
231 EndOfCapsule
= (UINT8
*) CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
;
232 FmpCapsuleSize
= (UINTN
)EndOfCapsule
- (UINTN
)FmpCapsuleHeader
;
234 if (FmpCapsuleSize
< sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
)) {
235 DEBUG((DEBUG_ERROR
, "FmpCapsuleSize(0x%x) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\n", FmpCapsuleSize
));
236 return EFI_INVALID_PARAMETER
;
239 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
240 if (FmpCapsuleHeader
->Version
!= EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
241 DEBUG((DEBUG_ERROR
, "FmpCapsuleHeader->Version(0x%x) != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION\n", FmpCapsuleHeader
->Version
));
242 return EFI_INVALID_PARAMETER
;
244 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
247 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
249 if ((FmpCapsuleSize
- sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
))/sizeof(UINT64
) < ItemNum
) {
250 DEBUG((DEBUG_ERROR
, "ItemNum(0x%x) too big\n", ItemNum
));
251 return EFI_INVALID_PARAMETER
;
253 FmpCapsuleHeaderSize
= sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
) + sizeof(UINT64
)*ItemNum
;
255 // Check ItemOffsetList
256 for (Index
= 0; Index
< ItemNum
; Index
++) {
257 if (ItemOffsetList
[Index
] >= FmpCapsuleSize
) {
258 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) >= FmpCapsuleSize(0x%x)\n", Index
, ItemOffsetList
[Index
], FmpCapsuleSize
));
259 return EFI_INVALID_PARAMETER
;
261 if (ItemOffsetList
[Index
] < FmpCapsuleHeaderSize
) {
262 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) < FmpCapsuleHeaderSize(0x%x)\n", Index
, ItemOffsetList
[Index
], FmpCapsuleHeaderSize
));
263 return EFI_INVALID_PARAMETER
;
266 // All the address in ItemOffsetList must be stored in ascending order
269 if (ItemOffsetList
[Index
] <= ItemOffsetList
[Index
- 1]) {
270 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) < ItemOffsetList[%d](0x%x)\n", Index
, ItemOffsetList
[Index
], Index
, ItemOffsetList
[Index
- 1]));
271 return EFI_INVALID_PARAMETER
;
276 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
277 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
278 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
279 if (Index
== ItemNum
- 1) {
280 EndOfPayload
= (UINT8
*)((UINTN
)EndOfCapsule
- (UINTN
)FmpCapsuleHeader
);
282 EndOfPayload
= (UINT8
*)(UINTN
)ItemOffsetList
[Index
+1];
284 FmpImageSize
= (UINTN
)EndOfPayload
- ItemOffsetList
[Index
];
286 if (FmpImageSize
< OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
)) {
287 DEBUG((DEBUG_ERROR
, "FmpImageSize(0x%lx) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER\n", FmpImageSize
));
288 return EFI_INVALID_PARAMETER
;
290 FmpImageHeaderSize
= sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
);
291 if ((ImageHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) ||
292 (ImageHeader
->Version
< 1)) {
293 DEBUG((DEBUG_ERROR
, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader
->Version
));
294 return EFI_INVALID_PARAMETER
;
296 if (ImageHeader
->Version
< EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
297 FmpImageHeaderSize
= OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
301 if (FmpImageSize
!= (UINT64
)FmpImageHeaderSize
+ (UINT64
)ImageHeader
->UpdateImageSize
+ (UINT64
)ImageHeader
->UpdateVendorCodeSize
) {
302 DEBUG((DEBUG_ERROR
, "FmpImageSize(0x%lx) mismatch, UpdateImageSize(0x%x) UpdateVendorCodeSize(0x%x)\n", FmpImageSize
, ImageHeader
->UpdateImageSize
, ImageHeader
->UpdateVendorCodeSize
));
303 return EFI_INVALID_PARAMETER
;
309 // No driver & payload element in FMP
311 EndOfPayload
= (UINT8
*)(FmpCapsuleHeader
+ 1);
312 if (EndOfPayload
!= EndOfCapsule
) {
313 DEBUG((DEBUG_ERROR
, "EndOfPayload(0x%x) mismatch, EndOfCapsule(0x%x)\n", EndOfPayload
, EndOfCapsule
));
314 return EFI_INVALID_PARAMETER
;
316 return EFI_UNSUPPORTED
;
319 if (EmbeddedDriverCount
!= NULL
) {
320 *EmbeddedDriverCount
= FmpCapsuleHeader
->EmbeddedDriverCount
;
327 Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
328 is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
329 buffer is passed in it will be used if it is big enough.
331 Caution: This function may receive untrusted input.
333 @param[in] BmpImage Pointer to BMP file
334 @param[in] BmpImageSize Number of bytes in BmpImage
335 @param[in, out] GopBlt Buffer containing GOP version of BmpImage.
336 @param[in, out] GopBltSize Size of GopBlt in bytes.
337 @param[out] PixelHeight Height of GopBlt/BmpImage in pixels
338 @param[out] PixelWidth Width of GopBlt/BmpImage in pixels
340 @retval EFI_SUCCESS GopBlt and GopBltSize are returned.
341 @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image
342 @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.
343 GopBltSize will contain the required size.
344 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.
351 IN UINTN BmpImageSize
,
352 IN OUT VOID
**GopBlt
,
353 IN OUT UINTN
*GopBltSize
,
354 OUT UINTN
*PixelHeight
,
355 OUT UINTN
*PixelWidth
360 BMP_IMAGE_HEADER
*BmpHeader
;
361 BMP_COLOR_MAP
*BmpColorMap
;
362 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
;
363 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
364 UINT64 BltBufferSize
;
369 UINT32 DataSizePerLine
;
373 if (sizeof (BMP_IMAGE_HEADER
) > BmpImageSize
) {
374 return EFI_INVALID_PARAMETER
;
377 BmpHeader
= (BMP_IMAGE_HEADER
*) BmpImage
;
379 if (BmpHeader
->CharB
!= 'B' || BmpHeader
->CharM
!= 'M') {
380 return EFI_UNSUPPORTED
;
384 // Doesn't support compress.
386 if (BmpHeader
->CompressionType
!= 0) {
387 return EFI_UNSUPPORTED
;
391 // Only support BITMAPINFOHEADER format.
392 // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER
394 if (BmpHeader
->HeaderSize
!= sizeof (BMP_IMAGE_HEADER
) - OFFSET_OF(BMP_IMAGE_HEADER
, HeaderSize
)) {
395 return EFI_UNSUPPORTED
;
399 // The data size in each line must be 4 byte alignment.
401 DataSizePerLine
= ((BmpHeader
->PixelWidth
* BmpHeader
->BitPerPixel
+ 31) >> 3) & (~0x3);
402 BltBufferSize
= MultU64x32 (DataSizePerLine
, BmpHeader
->PixelHeight
);
403 if (BltBufferSize
> (UINT32
) ~0) {
404 return EFI_INVALID_PARAMETER
;
407 if ((BmpHeader
->Size
!= BmpImageSize
) ||
408 (BmpHeader
->Size
< BmpHeader
->ImageOffset
) ||
409 (BmpHeader
->Size
- BmpHeader
->ImageOffset
!= BmpHeader
->PixelHeight
* DataSizePerLine
)) {
410 return EFI_INVALID_PARAMETER
;
414 // Calculate Color Map offset in the image.
417 BmpColorMap
= (BMP_COLOR_MAP
*) (Image
+ sizeof (BMP_IMAGE_HEADER
));
418 if (BmpHeader
->ImageOffset
< sizeof (BMP_IMAGE_HEADER
)) {
419 return EFI_INVALID_PARAMETER
;
422 if (BmpHeader
->ImageOffset
> sizeof (BMP_IMAGE_HEADER
)) {
423 switch (BmpHeader
->BitPerPixel
) {
438 // BMP file may has padding data between the bmp header section and the bmp data section.
440 if (BmpHeader
->ImageOffset
- sizeof (BMP_IMAGE_HEADER
) < sizeof (BMP_COLOR_MAP
) * ColorMapNum
) {
441 return EFI_INVALID_PARAMETER
;
446 // Calculate graphics image data address in the image
448 Image
= ((UINT8
*) BmpImage
) + BmpHeader
->ImageOffset
;
452 // Calculate the BltBuffer needed size.
454 BltBufferSize
= MultU64x32 ((UINT64
) BmpHeader
->PixelWidth
, BmpHeader
->PixelHeight
);
456 // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
458 if (BltBufferSize
> DivU64x32 ((UINTN
) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
))) {
459 return EFI_UNSUPPORTED
;
461 BltBufferSize
= MultU64x32 (BltBufferSize
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
464 if (*GopBlt
== NULL
) {
466 // GopBlt is not allocated by caller.
468 *GopBltSize
= (UINTN
) BltBufferSize
;
469 *GopBlt
= AllocatePool (*GopBltSize
);
471 if (*GopBlt
== NULL
) {
472 return EFI_OUT_OF_RESOURCES
;
476 // GopBlt has been allocated by caller.
478 if (*GopBltSize
< (UINTN
) BltBufferSize
) {
479 *GopBltSize
= (UINTN
) BltBufferSize
;
480 return EFI_BUFFER_TOO_SMALL
;
484 *PixelWidth
= BmpHeader
->PixelWidth
;
485 *PixelHeight
= BmpHeader
->PixelHeight
;
488 // Convert image from BMP to Blt buffer format
491 for (Height
= 0; Height
< BmpHeader
->PixelHeight
; Height
++) {
492 Blt
= &BltBuffer
[(BmpHeader
->PixelHeight
- Height
- 1) * BmpHeader
->PixelWidth
];
493 for (Width
= 0; Width
< BmpHeader
->PixelWidth
; Width
++, Image
++, Blt
++) {
494 switch (BmpHeader
->BitPerPixel
) {
497 // Convert 1-bit (2 colors) BMP to 24-bit color
499 for (Index
= 0; Index
< 8 && Width
< BmpHeader
->PixelWidth
; Index
++) {
500 Blt
->Red
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Red
;
501 Blt
->Green
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Green
;
502 Blt
->Blue
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Blue
;
513 // Convert 4-bit (16 colors) BMP Palette to 24-bit color
515 Index
= (*Image
) >> 4;
516 Blt
->Red
= BmpColorMap
[Index
].Red
;
517 Blt
->Green
= BmpColorMap
[Index
].Green
;
518 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
519 if (Width
< (BmpHeader
->PixelWidth
- 1)) {
522 Index
= (*Image
) & 0x0f;
523 Blt
->Red
= BmpColorMap
[Index
].Red
;
524 Blt
->Green
= BmpColorMap
[Index
].Green
;
525 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
531 // Convert 8-bit (256 colors) BMP Palette to 24-bit color
533 Blt
->Red
= BmpColorMap
[*Image
].Red
;
534 Blt
->Green
= BmpColorMap
[*Image
].Green
;
535 Blt
->Blue
= BmpColorMap
[*Image
].Blue
;
542 Blt
->Blue
= *Image
++;
543 Blt
->Green
= *Image
++;
549 // it is 32-bit BMP. Skip pixel's highest byte
551 Blt
->Blue
= *Image
++;
552 Blt
->Green
= *Image
++;
558 // Other bit format BMP is not supported.
564 return EFI_UNSUPPORTED
;
569 ImageIndex
= (UINTN
) (Image
- ImageHeader
);
570 if ((ImageIndex
% 4) != 0) {
572 // Bmp Image starts each row on a 32-bit boundary!
574 Image
= Image
+ (4 - (ImageIndex
% 4));
583 Those capsules supported by the firmwares.
585 Caution: This function may receive untrusted input.
587 @param[in] CapsuleHeader Points to a capsule header.
589 @retval EFI_SUCESS Input capsule is supported by firmware.
590 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
593 DisplayCapsuleImage (
594 IN EFI_CAPSULE_HEADER
*CapsuleHeader
597 DISPLAY_DISPLAY_PAYLOAD
*ImagePayload
;
600 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
604 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
606 ImagePayload
= (DISPLAY_DISPLAY_PAYLOAD
*)(CapsuleHeader
+ 1);
607 PayloadSize
= (UINTN
)(CapsuleHeader
->CapsuleImageSize
- sizeof(EFI_CAPSULE_HEADER
));
609 if (ImagePayload
->Version
!= 1) {
610 return EFI_UNSUPPORTED
;
612 if (CalculateCheckSum8((UINT8
*)CapsuleHeader
, CapsuleHeader
->CapsuleImageSize
) != 0) {
613 return EFI_UNSUPPORTED
;
616 // Only Support Bitmap by now
618 if (ImagePayload
->ImageType
!= 0) {
619 return EFI_UNSUPPORTED
;
625 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**)&GraphicsOutput
);
626 if (EFI_ERROR (Status
)) {
627 Status
= gBS
->LocateProtocol(&gEfiGraphicsOutputProtocolGuid
, NULL
, (VOID
**)&GraphicsOutput
);
628 if (EFI_ERROR(Status
)) {
629 return EFI_UNSUPPORTED
;
633 if (GraphicsOutput
->Mode
->Mode
!= ImagePayload
->Mode
) {
634 return EFI_UNSUPPORTED
;
640 Status
= ConvertBmpToGopBlt (
642 PayloadSize
- sizeof(DISPLAY_DISPLAY_PAYLOAD
),
649 if (EFI_ERROR (Status
)) {
653 Status
= GraphicsOutput
->Blt (
659 (UINTN
) ImagePayload
->OffsetX
,
660 (UINTN
) ImagePayload
->OffsetY
,
663 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
672 Dump FMP information.
674 @param[in] ImageInfoSize The size of ImageInfo, in bytes.
675 @param[in] ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
676 @param[in] DescriptorVersion The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
677 @param[in] DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
678 @param[in] DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
679 @param[in] PackageVersion The version of package.
680 @param[in] PackageVersionName The version name of package.
684 IN UINTN ImageInfoSize
,
685 IN EFI_FIRMWARE_IMAGE_DESCRIPTOR
*ImageInfo
,
686 IN UINT32 DescriptorVersion
,
687 IN UINT8 DescriptorCount
,
688 IN UINTN DescriptorSize
,
689 IN UINT32 PackageVersion
,
690 IN CHAR16
*PackageVersionName
693 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*CurrentImageInfo
;
696 DEBUG((DEBUG_VERBOSE
, " DescriptorVersion - 0x%x\n", DescriptorVersion
));
697 DEBUG((DEBUG_VERBOSE
, " DescriptorCount - 0x%x\n", DescriptorCount
));
698 DEBUG((DEBUG_VERBOSE
, " DescriptorSize - 0x%x\n", DescriptorSize
));
699 DEBUG((DEBUG_VERBOSE
, " PackageVersion - 0x%x\n", PackageVersion
));
700 DEBUG((DEBUG_VERBOSE
, " PackageVersionName - %s\n\n", PackageVersionName
));
701 CurrentImageInfo
= ImageInfo
;
702 for (Index
= 0; Index
< DescriptorCount
; Index
++) {
703 DEBUG((DEBUG_VERBOSE
, " ImageDescriptor (%d)\n", Index
));
704 DEBUG((DEBUG_VERBOSE
, " ImageIndex - 0x%x\n", CurrentImageInfo
->ImageIndex
));
705 DEBUG((DEBUG_VERBOSE
, " ImageTypeId - %g\n", &CurrentImageInfo
->ImageTypeId
));
706 DEBUG((DEBUG_VERBOSE
, " ImageId - 0x%lx\n", CurrentImageInfo
->ImageId
));
707 DEBUG((DEBUG_VERBOSE
, " ImageIdName - %s\n", CurrentImageInfo
->ImageIdName
));
708 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", CurrentImageInfo
->Version
));
709 DEBUG((DEBUG_VERBOSE
, " VersionName - %s\n", CurrentImageInfo
->VersionName
));
710 DEBUG((DEBUG_VERBOSE
, " Size - 0x%x\n", CurrentImageInfo
->Size
));
711 DEBUG((DEBUG_VERBOSE
, " AttributesSupported - 0x%lx\n", CurrentImageInfo
->AttributesSupported
));
712 DEBUG((DEBUG_VERBOSE
, " AttributesSetting - 0x%lx\n", CurrentImageInfo
->AttributesSetting
));
713 DEBUG((DEBUG_VERBOSE
, " Compatibilities - 0x%lx\n", CurrentImageInfo
->Compatibilities
));
714 if (DescriptorVersion
> 1) {
715 DEBUG((DEBUG_VERBOSE
, " LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo
->LowestSupportedImageVersion
));
716 if (DescriptorVersion
> 2) {
717 DEBUG((DEBUG_VERBOSE
, " LastAttemptVersion - 0x%x\n", CurrentImageInfo
->LastAttemptVersion
));
718 DEBUG((DEBUG_VERBOSE
, " LastAttemptStatus - 0x%x\n", CurrentImageInfo
->LastAttemptStatus
));
719 DEBUG((DEBUG_VERBOSE
, " HardwareInstance - 0x%lx\n", CurrentImageInfo
->HardwareInstance
));
723 // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
725 CurrentImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)CurrentImageInfo
+ DescriptorSize
);
730 Dump a non-nested FMP capsule.
732 @param[in] CapsuleHeader A pointer to CapsuleHeader
736 IN EFI_CAPSULE_HEADER
*CapsuleHeader
739 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
740 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
742 UINT64
*ItemOffsetList
;
744 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
746 DEBUG((DEBUG_VERBOSE
, "FmpCapsule:\n"));
747 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", FmpCapsuleHeader
->Version
));
748 DEBUG((DEBUG_VERBOSE
, " EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader
->EmbeddedDriverCount
));
749 DEBUG((DEBUG_VERBOSE
, " PayloadItemCount - 0x%x\n", FmpCapsuleHeader
->PayloadItemCount
));
751 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
752 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
753 DEBUG((DEBUG_VERBOSE
, " ItemOffsetList[%d] - 0x%lx\n", Index
, ItemOffsetList
[Index
]));
755 for (; Index
< (UINTN
)(FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
); Index
++) {
756 DEBUG((DEBUG_VERBOSE
, " ItemOffsetList[%d] - 0x%lx\n", Index
, ItemOffsetList
[Index
]));
757 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
759 DEBUG((DEBUG_VERBOSE
, " ImageHeader:\n"));
760 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", ImageHeader
->Version
));
761 DEBUG((DEBUG_VERBOSE
, " UpdateImageTypeId - %g\n", &ImageHeader
->UpdateImageTypeId
));
762 DEBUG((DEBUG_VERBOSE
, " UpdateImageIndex - 0x%x\n", ImageHeader
->UpdateImageIndex
));
763 DEBUG((DEBUG_VERBOSE
, " UpdateImageSize - 0x%x\n", ImageHeader
->UpdateImageSize
));
764 DEBUG((DEBUG_VERBOSE
, " UpdateVendorCodeSize - 0x%x\n", ImageHeader
->UpdateVendorCodeSize
));
765 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
766 DEBUG((DEBUG_VERBOSE
, " UpdateHardwareInstance - 0x%lx\n", ImageHeader
->UpdateHardwareInstance
));
772 Process Firmware management protocol data capsule.
774 This function assumes the caller validated the capsule by using
775 ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
776 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
777 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
779 This function need support nested FMP capsule.
781 @param[in] CapsuleHeader Points to a capsule header.
782 @param[out] AreAllImagesProcessed If all the FMP images in the capsule are processed.
784 @retval EFI_SUCESS Process Capsule Image successfully.
785 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
786 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
787 @retval EFI_OUT_OF_RESOURCES Not enough memory.
790 ProcessFmpCapsuleImage (
791 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
792 OUT BOOLEAN
*AreAllImagesProcessed
796 EFI_STATUS StatusEsrt
;
797 EFI_STATUS StatusRet
;
798 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
799 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
801 EFI_HANDLE ImageHandle
;
802 UINT64
*ItemOffsetList
;
806 EFI_HANDLE
*HandleBuffer
;
807 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
808 UINTN NumberOfHandles
;
809 UINTN DescriptorSize
;
810 UINT8 FmpImageInfoCount
;
811 UINT32 FmpImageInfoDescriptorVer
;
813 UINT32 PackageVersion
;
814 CHAR16
*PackageVersionName
;
816 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
817 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*TempFmpImageInfo
;
821 MEMMAP_DEVICE_PATH MemMapNode
;
822 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
823 EFI_DEVICE_PATH_PROTOCOL
*FmpDevicePath
;
824 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
825 EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry
;
828 if (!IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
829 return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
), AreAllImagesProcessed
);
832 ASSERT(AreAllImagesProcessed
!= NULL
);
834 Status
= EFI_SUCCESS
;
835 StatusRet
= EFI_NOT_FOUND
;
838 DriverDevicePath
= NULL
;
840 *AreAllImagesProcessed
= FALSE
;
842 DumpFmpCapsule(CapsuleHeader
);
844 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
846 if (FmpCapsuleHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
847 return EFI_INVALID_PARAMETER
;
849 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
851 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
854 // capsule in which driver count and payload count are both zero is not processed.
857 *AreAllImagesProcessed
= TRUE
;
862 // Update corresponding ESRT entry LastAttemp Status
864 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
865 if (EFI_ERROR (Status
)) {
870 // 1. Try to load & start all the drivers within capsule
872 SetDevicePathNodeLength (&MemMapNode
.Header
, sizeof (MemMapNode
));
873 MemMapNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
874 MemMapNode
.Header
.SubType
= HW_MEMMAP_DP
;
875 MemMapNode
.MemoryType
= EfiBootServicesCode
;
876 MemMapNode
.StartingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)CapsuleHeader
;
877 MemMapNode
.EndingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
- 1);
879 DriverDevicePath
= AppendDevicePathNode (NULL
, &MemMapNode
.Header
);
880 if (DriverDevicePath
== NULL
) {
881 return EFI_OUT_OF_RESOURCES
;
884 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
885 if (FmpCapsuleHeader
->PayloadItemCount
== 0 && Index
== (UINTN
)FmpCapsuleHeader
->EmbeddedDriverCount
- 1) {
887 // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
889 DriverLen
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
- (UINTN
)ItemOffsetList
[Index
];
891 DriverLen
= (UINTN
)ItemOffsetList
[Index
+ 1] - (UINTN
)ItemOffsetList
[Index
];
894 DEBUG((DEBUG_INFO
, "FmpCapsule: LoadImage ...\n"));
895 Status
= gBS
->LoadImage(
899 (UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
],
903 DEBUG((DEBUG_INFO
, "FmpCapsule: LoadImage - %r\n", Status
));
904 if (EFI_ERROR(Status
)) {
909 DEBUG((DEBUG_INFO
, "FmpCapsule: StartImage ...\n"));
910 Status
= gBS
->StartImage(
915 DEBUG((DEBUG_INFO
, "FmpCapsule: StartImage - %r\n", Status
));
916 if (EFI_ERROR(Status
)) {
917 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
924 // 2. Route payload to right FMP instance
926 DEBUG((DEBUG_INFO
, "FmpCapsule: route payload to right FMP instance ...\n"));
928 Status
= gBS
->LocateHandleBuffer (
930 &gEfiFirmwareManagementProtocolGuid
,
936 if (!EFI_ERROR(Status
)) {
937 for(Index1
= 0; Index1
< NumberOfHandles
; Index1
++) {
938 Status
= gBS
->HandleProtocol(
939 HandleBuffer
[Index1
],
940 &gEfiFirmwareManagementProtocolGuid
,
943 if (EFI_ERROR(Status
)) {
947 FmpDevicePath
= NULL
;
949 HandleBuffer
[Index1
],
950 &gEfiDevicePathProtocolGuid
,
951 (VOID
**)&FmpDevicePath
955 Status
= Fmp
->GetImageInfo (
965 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
969 FmpImageInfoBuf
= NULL
;
970 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
971 if (FmpImageInfoBuf
== NULL
) {
972 StatusRet
= EFI_OUT_OF_RESOURCES
;
976 PackageVersionName
= NULL
;
977 Status
= Fmp
->GetImageInfo (
979 &ImageInfoSize
, // ImageInfoSize
980 FmpImageInfoBuf
, // ImageInfo
981 &FmpImageInfoDescriptorVer
, // DescriptorVersion
982 &FmpImageInfoCount
, // DescriptorCount
983 &DescriptorSize
, // DescriptorSize
984 &PackageVersion
, // PackageVersion
985 &PackageVersionName
// PackageVersionName
989 // If FMP GetInformation interface failed, skip this resource
991 if (EFI_ERROR(Status
)) {
992 FreePool(FmpImageInfoBuf
);
996 DEBUG((DEBUG_INFO
, "FMP (%d) ImageInfo:\n", Index
));
998 ImageInfoSize
, // ImageInfoSize
999 FmpImageInfoBuf
, // ImageInfo
1000 FmpImageInfoDescriptorVer
, // DescriptorVersion
1001 FmpImageInfoCount
, // DescriptorCount
1002 DescriptorSize
, // DescriptorSize
1003 PackageVersion
, // PackageVersion
1004 PackageVersionName
// PackageVersionName
1007 if (PackageVersionName
!= NULL
) {
1008 FreePool(PackageVersionName
);
1011 TempFmpImageInfo
= FmpImageInfoBuf
;
1012 for (Index2
= 0; Index2
< FmpImageInfoCount
; Index2
++) {
1014 // Check all the payload entry in capsule payload list
1016 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
1017 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
1019 if (IsFmpCapsuleProcessed(CapsuleHeader
, Index
- FmpCapsuleHeader
->EmbeddedDriverCount
, ImageHeader
)) {
1020 DEBUG((DEBUG_INFO
, "FMP Capsule already processed (%g):", CapsuleHeader
));
1021 DEBUG((DEBUG_INFO
, "ImageTypeId - %g, ", &ImageHeader
->UpdateImageTypeId
));
1022 DEBUG((DEBUG_INFO
, "PayloadIndex - 0x%x, ImageIndex - 0x%x\n", Index
- FmpCapsuleHeader
->EmbeddedDriverCount
, ImageHeader
->UpdateImageIndex
));
1026 if (CompareGuid(&ImageHeader
->UpdateImageTypeId
, &TempFmpImageInfo
->ImageTypeId
)) {
1028 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
1029 if(ImageHeader
->UpdateHardwareInstance
!= 0){
1031 // FMP Version is >=2 & UpdateHardwareInstance Skip 2 case
1032 // 1. FMP Image info Version < 3
1033 // 2. HardwareInstance doesn't match
1035 if (FmpImageInfoDescriptorVer
< EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
||
1036 ImageHeader
->UpdateHardwareInstance
!= TempFmpImageInfo
->HardwareInstance
) {
1040 Image
= (UINT8
*)(ImageHeader
+ 1);
1043 // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1, only match ImageTypeId.
1044 // Header should exclude UpdateHardwareInstance field
1046 Image
= (UINT8
*)ImageHeader
+ OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
1049 if (ImageHeader
->UpdateVendorCodeSize
== 0) {
1052 VendorCode
= Image
+ ImageHeader
->UpdateImageSize
;
1054 DEBUG((DEBUG_INFO
, "Fmp->SetImage ...\n"));
1055 Status
= Fmp
->SetImage(
1057 ImageHeader
->UpdateImageIndex
, // ImageIndex
1059 ImageHeader
->UpdateImageSize
, // ImageSize
1060 VendorCode
, // VendorCode
1061 Update_Image_Progress
, // Progress
1062 &AbortReason
// AbortReason
1064 DEBUG((DEBUG_INFO
, "Fmp->SetImage - %r\n", Status
));
1065 if (AbortReason
!= NULL
) {
1066 DEBUG ((DEBUG_ERROR
, "%s\n", AbortReason
));
1067 FreePool(AbortReason
);
1069 RecordFmpCapsuleStatusVariable(
1070 CapsuleHeader
, // CapsuleGuid
1071 Status
, // CapsuleStatus
1072 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
, // PayloadIndex
1073 ImageHeader
, // ImageHeader
1074 FmpDevicePath
// FmpDevicePath
1076 if (StatusRet
!= EFI_SUCCESS
) {
1080 // Update EsrtEntry For V1, V2 FMP instance. V3 FMP ESRT cache will be synced up through EsrtSyncFmp interface
1082 if (FmpImageInfoDescriptorVer
< EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
&& EsrtProtocol
!= NULL
) {
1083 StatusEsrt
= EsrtProtocol
->GetEsrtEntry(&TempFmpImageInfo
->ImageTypeId
, &EsrtEntry
);
1084 if (!EFI_ERROR(StatusEsrt
)){
1085 if (!EFI_ERROR(Status
)) {
1086 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_SUCCESS
;
1088 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL
;
1090 EsrtEntry
.LastAttemptVersion
= 0;
1091 EsrtProtocol
->UpdateEsrtEntry(&EsrtEntry
);
1097 // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
1099 TempFmpImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)TempFmpImageInfo
+ DescriptorSize
);
1101 FreePool(FmpImageInfoBuf
);
1106 // final check for AreAllImagesProcessed
1108 *AreAllImagesProcessed
= TRUE
;
1109 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
1110 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
1112 if (!IsFmpCapsuleProcessed(CapsuleHeader
, Index
- FmpCapsuleHeader
->EmbeddedDriverCount
, ImageHeader
)) {
1113 *AreAllImagesProcessed
= FALSE
;
1120 if (HandleBuffer
!= NULL
) {
1121 FreePool(HandleBuffer
);
1124 if (DriverDevicePath
!= NULL
) {
1125 FreePool(DriverDevicePath
);
1132 Return if there is a FMP header below capsule header.
1134 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1136 @retval TRUE There is a FMP header below capsule header.
1137 @retval FALSE There is not a FMP header below capsule header
1140 IsNestedFmpCapsule (
1141 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1145 EFI_SYSTEM_RESOURCE_TABLE
*Esrt
;
1146 EFI_SYSTEM_RESOURCE_ENTRY
*EsrtEntry
;
1148 BOOLEAN EsrtGuidFound
;
1149 EFI_CAPSULE_HEADER
*NestedCapsuleHeader
;
1150 UINTN NestedCapsuleSize
;
1151 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
1152 EFI_SYSTEM_RESOURCE_ENTRY Entry
;
1154 EsrtGuidFound
= FALSE
;
1157 // Check ESRT protocol
1159 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
1160 if (!EFI_ERROR(Status
)) {
1161 Status
= EsrtProtocol
->GetEsrtEntry(&CapsuleHeader
->CapsuleGuid
, &Entry
);
1162 if (!EFI_ERROR(Status
)) {
1163 EsrtGuidFound
= TRUE
;
1168 // Check ESRT configuration table
1170 if (!EsrtGuidFound
) {
1171 Status
= EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid
, (VOID
**)&Esrt
);
1172 if (!EFI_ERROR(Status
)) {
1173 ASSERT (Esrt
!= NULL
);
1174 EsrtEntry
= (VOID
*)(Esrt
+ 1);
1175 for (Index
= 0; Index
< Esrt
->FwResourceCount
; Index
++, EsrtEntry
++) {
1176 if (CompareGuid(&EsrtEntry
->FwClass
, &CapsuleHeader
->CapsuleGuid
)) {
1177 EsrtGuidFound
= TRUE
;
1183 if (!EsrtGuidFound
) {
1188 // Check nested capsule header
1189 // FMP GUID after ESRT one
1191 NestedCapsuleHeader
= (EFI_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
1192 NestedCapsuleSize
= (UINTN
)CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
- (UINTN
)NestedCapsuleHeader
;
1193 if (NestedCapsuleSize
< sizeof(EFI_CAPSULE_HEADER
)) {
1196 if (!IsValidCapsuleHeader(NestedCapsuleHeader
, NestedCapsuleSize
)) {
1199 if (!IsFmpCapsuleGuid(&NestedCapsuleHeader
->CapsuleGuid
)) {
1202 DEBUG ((DEBUG_INFO
, "IsNestedFmpCapsule\n"));
1207 Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
1209 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1211 @retval TRUE It is a system FMP.
1212 @retval FALSE It is a device FMP.
1216 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1219 if (IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
1222 if (IsNestedFmpCapsule(CapsuleHeader
)) {
1229 Those capsules supported by the firmwares.
1231 Caution: This function may receive untrusted input.
1233 @param[in] CapsuleHeader Points to a capsule header.
1235 @retval EFI_SUCESS Input capsule is supported by firmware.
1236 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
1237 @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
1241 SupportCapsuleImage (
1242 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1246 // check Display Capsule Guid
1248 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1252 if (IsFmpCapsule(CapsuleHeader
)) {
1254 // Check layout of FMP capsule
1256 return ValidateFmpCapsule(CapsuleHeader
, NULL
);
1258 DEBUG((DEBUG_ERROR
, "Unknown Capsule Guid - %g\n", &CapsuleHeader
->CapsuleGuid
));
1259 return EFI_UNSUPPORTED
;
1263 The firmware implements to process the capsule image.
1265 Caution: This function may receive untrusted input.
1267 @param[in] CapsuleHeader Points to a capsule header.
1269 @retval EFI_SUCESS Process Capsule Image successfully.
1270 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1271 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1272 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1276 ProcessCapsuleImage (
1277 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1281 BOOLEAN AreAllImagesProcessed
;
1283 if (SupportCapsuleImage (CapsuleHeader
) != EFI_SUCCESS
) {
1284 return EFI_UNSUPPORTED
;
1288 // Display image in firmware update display capsule
1290 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1291 DEBUG((DEBUG_INFO
, "ProcessCapsuleImage for WindowsUxCapsule ...\n"));
1292 Status
= DisplayCapsuleImage(CapsuleHeader
);
1293 RecordCapsuleStatusVariable(CapsuleHeader
, Status
);
1298 // Check FMP capsule layout
1300 if (IsFmpCapsule (CapsuleHeader
)) {
1301 DEBUG((DEBUG_INFO
, "ProcessCapsuleImage for FmpCapsule ...\n"));
1302 DEBUG((DEBUG_INFO
, "ValidateFmpCapsule ...\n"));
1303 Status
= ValidateFmpCapsule(CapsuleHeader
, NULL
);
1304 DEBUG((DEBUG_INFO
, "ValidateFmpCapsule - %r\n", Status
));
1305 if (EFI_ERROR(Status
)) {
1310 // Press EFI FMP Capsule
1312 DEBUG((DEBUG_INFO
, "ProcessFmpCapsuleImage ...\n"));
1313 Status
= ProcessFmpCapsuleImage(CapsuleHeader
, &AreAllImagesProcessed
);
1314 DEBUG((DEBUG_INFO
, "ProcessFmpCapsuleImage - %r\n", Status
));
1316 if (!AreAllImagesProcessed
) {
1317 mAreAllImagesProcessed
= FALSE
;
1323 return EFI_UNSUPPORTED
;
1327 Callback function executed when the EndOfDxe event group is signaled.
1329 @param[in] Event Event whose notification function is being invoked.
1330 @param[in] Context The pointer to the notification function's context, which
1331 is implementation-dependent.
1335 DxeCapsuleLibEndOfDxe (
1340 mDxeCapsuleLibEndOfDxe
= TRUE
;
1344 The constructor function.
1346 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1347 @param[in] SystemTable A pointer to the EFI System Table.
1349 @retval EFI_SUCCESS The constructor successfully .
1353 DxeCapsuleLibConstructor (
1354 IN EFI_HANDLE ImageHandle
,
1355 IN EFI_SYSTEM_TABLE
*SystemTable
1358 EFI_EVENT EndOfDxeEvent
;
1361 Status
= gBS
->CreateEventEx (
1364 DxeCapsuleLibEndOfDxe
,
1366 &gEfiEndOfDxeEventGroupGuid
,
1369 ASSERT_EFI_ERROR (Status
);
1371 InitCapsuleVariable();