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
104 @retval EFI_SUCCESS The capsule status variable is recorded.
105 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
108 RecordFmpCapsuleStatusVariable (
109 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
110 IN EFI_STATUS CapsuleStatus
,
111 IN UINTN PayloadIndex
,
112 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
116 Function indicate the current completion progress of the firmware
117 update. Platform may override with own specific progress function.
119 @param[in] Completion A value between 1 and 100 indicating the current completion progress of the firmware update
121 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
125 Update_Image_Progress (
133 Return if this CapsuleGuid is a FMP capsule GUID or not.
135 @param[in] CapsuleGuid A pointer to EFI_GUID
137 @retval TRUE It is a FMP capsule GUID.
138 @retval FALSE It is not a FMP capsule GUID.
142 IN EFI_GUID
*CapsuleGuid
145 if (CompareGuid(&gEfiFmpCapsuleGuid
, CapsuleGuid
)) {
153 Validate if it is valid capsule header
155 Caution: This function may receive untrusted input.
157 This function assumes the caller provided correct CapsuleHeader pointer
160 This function validates the fields in EFI_CAPSULE_HEADER.
162 @param[in] CapsuleHeader Points to a capsule header.
163 @param[in] CapsuleSize Size of the whole capsule image.
167 IsValidCapsuleHeader (
168 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
169 IN UINT64 CapsuleSize
172 if (CapsuleHeader
->CapsuleImageSize
!= CapsuleSize
) {
175 if (CapsuleHeader
->HeaderSize
>= CapsuleHeader
->CapsuleImageSize
) {
182 Validate Fmp capsules layout.
184 Caution: This function may receive untrusted input.
186 This function assumes the caller validated the capsule by using
187 IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.
188 The capsule buffer size is CapsuleHeader->CapsuleImageSize.
190 This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
191 and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
193 This function need support nested FMP capsule.
195 @param[in] CapsuleHeader Points to a capsule header.
196 @param[out] EmbeddedDriverCount The EmbeddedDriverCount in the FMP capsule.
198 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
199 @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.
203 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
204 OUT UINT16
*EmbeddedDriverCount OPTIONAL
207 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
209 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
211 UINT64
*ItemOffsetList
;
214 UINTN FmpCapsuleSize
;
215 UINTN FmpCapsuleHeaderSize
;
217 UINTN FmpImageHeaderSize
;
219 if (!IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
220 return ValidateFmpCapsule ((EFI_CAPSULE_HEADER
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
), EmbeddedDriverCount
);
223 if (CapsuleHeader
->HeaderSize
>= CapsuleHeader
->CapsuleImageSize
) {
224 DEBUG((DEBUG_ERROR
, "HeaderSize(0x%x) >= CapsuleImageSize(0x%x)\n", CapsuleHeader
->HeaderSize
, CapsuleHeader
->CapsuleImageSize
));
225 return EFI_INVALID_PARAMETER
;
228 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
229 EndOfCapsule
= (UINT8
*) CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
;
230 FmpCapsuleSize
= (UINTN
)EndOfCapsule
- (UINTN
)FmpCapsuleHeader
;
232 if (FmpCapsuleSize
< sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
)) {
233 DEBUG((DEBUG_ERROR
, "FmpCapsuleSize(0x%x) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\n", FmpCapsuleSize
));
234 return EFI_INVALID_PARAMETER
;
237 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
238 if (FmpCapsuleHeader
->Version
!= EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
239 DEBUG((DEBUG_ERROR
, "FmpCapsuleHeader->Version(0x%x) != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION\n", FmpCapsuleHeader
->Version
));
240 return EFI_INVALID_PARAMETER
;
242 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
245 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
247 if ((FmpCapsuleSize
- sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
))/sizeof(UINT64
) < ItemNum
) {
248 DEBUG((DEBUG_ERROR
, "ItemNum(0x%x) too big\n", ItemNum
));
249 return EFI_INVALID_PARAMETER
;
251 FmpCapsuleHeaderSize
= sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
) + sizeof(UINT64
)*ItemNum
;
253 // Check ItemOffsetList
254 for (Index
= 0; Index
< ItemNum
; Index
++) {
255 if (ItemOffsetList
[Index
] >= FmpCapsuleSize
) {
256 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) >= FmpCapsuleSize(0x%x)\n", Index
, ItemOffsetList
[Index
], FmpCapsuleSize
));
257 return EFI_INVALID_PARAMETER
;
259 if (ItemOffsetList
[Index
] < FmpCapsuleHeaderSize
) {
260 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) < FmpCapsuleHeaderSize(0x%x)\n", Index
, ItemOffsetList
[Index
], FmpCapsuleHeaderSize
));
261 return EFI_INVALID_PARAMETER
;
264 // All the address in ItemOffsetList must be stored in ascending order
267 if (ItemOffsetList
[Index
] <= ItemOffsetList
[Index
- 1]) {
268 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) < ItemOffsetList[%d](0x%x)\n", Index
, ItemOffsetList
[Index
], Index
, ItemOffsetList
[Index
- 1]));
269 return EFI_INVALID_PARAMETER
;
274 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
275 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
276 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
277 if (Index
== ItemNum
- 1) {
278 EndOfPayload
= (UINT8
*)((UINTN
)EndOfCapsule
- (UINTN
)FmpCapsuleHeader
);
280 EndOfPayload
= (UINT8
*)(UINTN
)ItemOffsetList
[Index
+1];
282 FmpImageSize
= (UINTN
)EndOfPayload
- ItemOffsetList
[Index
];
284 if (FmpImageSize
< OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
)) {
285 DEBUG((DEBUG_ERROR
, "FmpImageSize(0x%lx) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER\n", FmpImageSize
));
286 return EFI_INVALID_PARAMETER
;
288 FmpImageHeaderSize
= sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
);
289 if ((ImageHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) ||
290 (ImageHeader
->Version
< 1)) {
291 DEBUG((DEBUG_ERROR
, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader
->Version
));
292 return EFI_INVALID_PARAMETER
;
294 if (ImageHeader
->Version
< EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
295 FmpImageHeaderSize
= OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
299 if (FmpImageSize
!= (UINT64
)FmpImageHeaderSize
+ (UINT64
)ImageHeader
->UpdateImageSize
+ (UINT64
)ImageHeader
->UpdateVendorCodeSize
) {
300 DEBUG((DEBUG_ERROR
, "FmpImageSize(0x%lx) mismatch, UpdateImageSize(0x%x) UpdateVendorCodeSize(0x%x)\n", FmpImageSize
, ImageHeader
->UpdateImageSize
, ImageHeader
->UpdateVendorCodeSize
));
301 return EFI_INVALID_PARAMETER
;
307 // No driver & payload element in FMP
309 EndOfPayload
= (UINT8
*)(FmpCapsuleHeader
+ 1);
310 if (EndOfPayload
!= EndOfCapsule
) {
311 DEBUG((DEBUG_ERROR
, "EndOfPayload(0x%x) mismatch, EndOfCapsule(0x%x)\n", EndOfPayload
, EndOfCapsule
));
312 return EFI_INVALID_PARAMETER
;
314 return EFI_UNSUPPORTED
;
317 if (EmbeddedDriverCount
!= NULL
) {
318 *EmbeddedDriverCount
= FmpCapsuleHeader
->EmbeddedDriverCount
;
325 Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
326 is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
327 buffer is passed in it will be used if it is big enough.
329 Caution: This function may receive untrusted input.
331 @param[in] BmpImage Pointer to BMP file
332 @param[in] BmpImageSize Number of bytes in BmpImage
333 @param[in, out] GopBlt Buffer containing GOP version of BmpImage.
334 @param[in, out] GopBltSize Size of GopBlt in bytes.
335 @param[out] PixelHeight Height of GopBlt/BmpImage in pixels
336 @param[out] PixelWidth Width of GopBlt/BmpImage in pixels
338 @retval EFI_SUCCESS GopBlt and GopBltSize are returned.
339 @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image
340 @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.
341 GopBltSize will contain the required size.
342 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.
349 IN UINTN BmpImageSize
,
350 IN OUT VOID
**GopBlt
,
351 IN OUT UINTN
*GopBltSize
,
352 OUT UINTN
*PixelHeight
,
353 OUT UINTN
*PixelWidth
358 BMP_IMAGE_HEADER
*BmpHeader
;
359 BMP_COLOR_MAP
*BmpColorMap
;
360 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
;
361 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
362 UINT64 BltBufferSize
;
367 UINT32 DataSizePerLine
;
371 if (sizeof (BMP_IMAGE_HEADER
) > BmpImageSize
) {
372 return EFI_INVALID_PARAMETER
;
375 BmpHeader
= (BMP_IMAGE_HEADER
*) BmpImage
;
377 if (BmpHeader
->CharB
!= 'B' || BmpHeader
->CharM
!= 'M') {
378 return EFI_UNSUPPORTED
;
382 // Doesn't support compress.
384 if (BmpHeader
->CompressionType
!= 0) {
385 return EFI_UNSUPPORTED
;
389 // Only support BITMAPINFOHEADER format.
390 // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER
392 if (BmpHeader
->HeaderSize
!= sizeof (BMP_IMAGE_HEADER
) - OFFSET_OF(BMP_IMAGE_HEADER
, HeaderSize
)) {
393 return EFI_UNSUPPORTED
;
397 // The data size in each line must be 4 byte alignment.
399 DataSizePerLine
= ((BmpHeader
->PixelWidth
* BmpHeader
->BitPerPixel
+ 31) >> 3) & (~0x3);
400 BltBufferSize
= MultU64x32 (DataSizePerLine
, BmpHeader
->PixelHeight
);
401 if (BltBufferSize
> (UINT32
) ~0) {
402 return EFI_INVALID_PARAMETER
;
405 if ((BmpHeader
->Size
!= BmpImageSize
) ||
406 (BmpHeader
->Size
< BmpHeader
->ImageOffset
) ||
407 (BmpHeader
->Size
- BmpHeader
->ImageOffset
!= BmpHeader
->PixelHeight
* DataSizePerLine
)) {
408 return EFI_INVALID_PARAMETER
;
412 // Calculate Color Map offset in the image.
415 BmpColorMap
= (BMP_COLOR_MAP
*) (Image
+ sizeof (BMP_IMAGE_HEADER
));
416 if (BmpHeader
->ImageOffset
< sizeof (BMP_IMAGE_HEADER
)) {
417 return EFI_INVALID_PARAMETER
;
420 if (BmpHeader
->ImageOffset
> sizeof (BMP_IMAGE_HEADER
)) {
421 switch (BmpHeader
->BitPerPixel
) {
436 // BMP file may has padding data between the bmp header section and the bmp data section.
438 if (BmpHeader
->ImageOffset
- sizeof (BMP_IMAGE_HEADER
) < sizeof (BMP_COLOR_MAP
) * ColorMapNum
) {
439 return EFI_INVALID_PARAMETER
;
444 // Calculate graphics image data address in the image
446 Image
= ((UINT8
*) BmpImage
) + BmpHeader
->ImageOffset
;
450 // Calculate the BltBuffer needed size.
452 BltBufferSize
= MultU64x32 ((UINT64
) BmpHeader
->PixelWidth
, BmpHeader
->PixelHeight
);
454 // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
456 if (BltBufferSize
> DivU64x32 ((UINTN
) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
))) {
457 return EFI_UNSUPPORTED
;
459 BltBufferSize
= MultU64x32 (BltBufferSize
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
462 if (*GopBlt
== NULL
) {
464 // GopBlt is not allocated by caller.
466 *GopBltSize
= (UINTN
) BltBufferSize
;
467 *GopBlt
= AllocatePool (*GopBltSize
);
469 if (*GopBlt
== NULL
) {
470 return EFI_OUT_OF_RESOURCES
;
474 // GopBlt has been allocated by caller.
476 if (*GopBltSize
< (UINTN
) BltBufferSize
) {
477 *GopBltSize
= (UINTN
) BltBufferSize
;
478 return EFI_BUFFER_TOO_SMALL
;
482 *PixelWidth
= BmpHeader
->PixelWidth
;
483 *PixelHeight
= BmpHeader
->PixelHeight
;
486 // Convert image from BMP to Blt buffer format
489 for (Height
= 0; Height
< BmpHeader
->PixelHeight
; Height
++) {
490 Blt
= &BltBuffer
[(BmpHeader
->PixelHeight
- Height
- 1) * BmpHeader
->PixelWidth
];
491 for (Width
= 0; Width
< BmpHeader
->PixelWidth
; Width
++, Image
++, Blt
++) {
492 switch (BmpHeader
->BitPerPixel
) {
495 // Convert 1-bit (2 colors) BMP to 24-bit color
497 for (Index
= 0; Index
< 8 && Width
< BmpHeader
->PixelWidth
; Index
++) {
498 Blt
->Red
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Red
;
499 Blt
->Green
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Green
;
500 Blt
->Blue
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Blue
;
511 // Convert 4-bit (16 colors) BMP Palette to 24-bit color
513 Index
= (*Image
) >> 4;
514 Blt
->Red
= BmpColorMap
[Index
].Red
;
515 Blt
->Green
= BmpColorMap
[Index
].Green
;
516 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
517 if (Width
< (BmpHeader
->PixelWidth
- 1)) {
520 Index
= (*Image
) & 0x0f;
521 Blt
->Red
= BmpColorMap
[Index
].Red
;
522 Blt
->Green
= BmpColorMap
[Index
].Green
;
523 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
529 // Convert 8-bit (256 colors) BMP Palette to 24-bit color
531 Blt
->Red
= BmpColorMap
[*Image
].Red
;
532 Blt
->Green
= BmpColorMap
[*Image
].Green
;
533 Blt
->Blue
= BmpColorMap
[*Image
].Blue
;
540 Blt
->Blue
= *Image
++;
541 Blt
->Green
= *Image
++;
547 // it is 32-bit BMP. Skip pixel's highest byte
549 Blt
->Blue
= *Image
++;
550 Blt
->Green
= *Image
++;
556 // Other bit format BMP is not supported.
562 return EFI_UNSUPPORTED
;
567 ImageIndex
= (UINTN
) (Image
- ImageHeader
);
568 if ((ImageIndex
% 4) != 0) {
570 // Bmp Image starts each row on a 32-bit boundary!
572 Image
= Image
+ (4 - (ImageIndex
% 4));
581 Those capsules supported by the firmwares.
583 Caution: This function may receive untrusted input.
585 @param[in] CapsuleHeader Points to a capsule header.
587 @retval EFI_SUCESS Input capsule is supported by firmware.
588 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
591 DisplayCapsuleImage (
592 IN EFI_CAPSULE_HEADER
*CapsuleHeader
595 DISPLAY_DISPLAY_PAYLOAD
*ImagePayload
;
598 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
602 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
604 ImagePayload
= (DISPLAY_DISPLAY_PAYLOAD
*)(CapsuleHeader
+ 1);
605 PayloadSize
= (UINTN
)(CapsuleHeader
->CapsuleImageSize
- sizeof(EFI_CAPSULE_HEADER
));
607 if (ImagePayload
->Version
!= 1) {
608 return EFI_UNSUPPORTED
;
610 if (CalculateCheckSum8((UINT8
*)CapsuleHeader
, CapsuleHeader
->CapsuleImageSize
) != 0) {
611 return EFI_UNSUPPORTED
;
614 // Only Support Bitmap by now
616 if (ImagePayload
->ImageType
!= 0) {
617 return EFI_UNSUPPORTED
;
623 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**)&GraphicsOutput
);
624 if (EFI_ERROR (Status
)) {
625 Status
= gBS
->LocateProtocol(&gEfiGraphicsOutputProtocolGuid
, NULL
, (VOID
**)&GraphicsOutput
);
626 if (EFI_ERROR(Status
)) {
627 return EFI_UNSUPPORTED
;
631 if (GraphicsOutput
->Mode
->Mode
!= ImagePayload
->Mode
) {
632 return EFI_UNSUPPORTED
;
638 Status
= ConvertBmpToGopBlt (
640 PayloadSize
- sizeof(DISPLAY_DISPLAY_PAYLOAD
),
647 if (EFI_ERROR (Status
)) {
651 Status
= GraphicsOutput
->Blt (
657 (UINTN
) ImagePayload
->OffsetX
,
658 (UINTN
) ImagePayload
->OffsetY
,
661 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
670 Dump FMP information.
672 @param[in] ImageInfoSize The size of ImageInfo, in bytes.
673 @param[in] ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
674 @param[in] DescriptorVersion The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
675 @param[in] DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
676 @param[in] DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
677 @param[in] PackageVersion The version of package.
678 @param[in] PackageVersionName The version name of package.
682 IN UINTN ImageInfoSize
,
683 IN EFI_FIRMWARE_IMAGE_DESCRIPTOR
*ImageInfo
,
684 IN UINT32 DescriptorVersion
,
685 IN UINT8 DescriptorCount
,
686 IN UINTN DescriptorSize
,
687 IN UINT32 PackageVersion
,
688 IN CHAR16
*PackageVersionName
691 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*CurrentImageInfo
;
694 DEBUG((DEBUG_VERBOSE
, " DescriptorVersion - 0x%x\n", DescriptorVersion
));
695 DEBUG((DEBUG_VERBOSE
, " DescriptorCount - 0x%x\n", DescriptorCount
));
696 DEBUG((DEBUG_VERBOSE
, " DescriptorSize - 0x%x\n", DescriptorSize
));
697 DEBUG((DEBUG_VERBOSE
, " PackageVersion - 0x%x\n", PackageVersion
));
698 DEBUG((DEBUG_VERBOSE
, " PackageVersionName - %s\n\n", PackageVersionName
));
699 CurrentImageInfo
= ImageInfo
;
700 for (Index
= 0; Index
< DescriptorCount
; Index
++) {
701 DEBUG((DEBUG_VERBOSE
, " ImageDescriptor (%d)\n", Index
));
702 DEBUG((DEBUG_VERBOSE
, " ImageIndex - 0x%x\n", CurrentImageInfo
->ImageIndex
));
703 DEBUG((DEBUG_VERBOSE
, " ImageTypeId - %g\n", &CurrentImageInfo
->ImageTypeId
));
704 DEBUG((DEBUG_VERBOSE
, " ImageId - 0x%lx\n", CurrentImageInfo
->ImageId
));
705 DEBUG((DEBUG_VERBOSE
, " ImageIdName - %s\n", CurrentImageInfo
->ImageIdName
));
706 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", CurrentImageInfo
->Version
));
707 DEBUG((DEBUG_VERBOSE
, " VersionName - %s\n", CurrentImageInfo
->VersionName
));
708 DEBUG((DEBUG_VERBOSE
, " Size - 0x%x\n", CurrentImageInfo
->Size
));
709 DEBUG((DEBUG_VERBOSE
, " AttributesSupported - 0x%lx\n", CurrentImageInfo
->AttributesSupported
));
710 DEBUG((DEBUG_VERBOSE
, " AttributesSetting - 0x%lx\n", CurrentImageInfo
->AttributesSetting
));
711 DEBUG((DEBUG_VERBOSE
, " Compatibilities - 0x%lx\n", CurrentImageInfo
->Compatibilities
));
712 if (DescriptorVersion
> 1) {
713 DEBUG((DEBUG_VERBOSE
, " LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo
->LowestSupportedImageVersion
));
714 if (DescriptorVersion
> 2) {
715 DEBUG((DEBUG_VERBOSE
, " LastAttemptVersion - 0x%x\n", CurrentImageInfo
->LastAttemptVersion
));
716 DEBUG((DEBUG_VERBOSE
, " LastAttemptStatus - 0x%x\n", CurrentImageInfo
->LastAttemptStatus
));
717 DEBUG((DEBUG_VERBOSE
, " HardwareInstance - 0x%lx\n", CurrentImageInfo
->HardwareInstance
));
721 // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
723 CurrentImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)CurrentImageInfo
+ DescriptorSize
);
728 Dump a non-nested FMP capsule.
730 @param[in] CapsuleHeader A pointer to CapsuleHeader
734 IN EFI_CAPSULE_HEADER
*CapsuleHeader
737 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
738 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
740 UINT64
*ItemOffsetList
;
742 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
744 DEBUG((DEBUG_VERBOSE
, "FmpCapsule:\n"));
745 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", FmpCapsuleHeader
->Version
));
746 DEBUG((DEBUG_VERBOSE
, " EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader
->EmbeddedDriverCount
));
747 DEBUG((DEBUG_VERBOSE
, " PayloadItemCount - 0x%x\n", FmpCapsuleHeader
->PayloadItemCount
));
749 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
750 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
751 DEBUG((DEBUG_VERBOSE
, " ItemOffsetList[%d] - 0x%lx\n", Index
, ItemOffsetList
[Index
]));
753 for (; Index
< (UINTN
)(FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
); Index
++) {
754 DEBUG((DEBUG_VERBOSE
, " ItemOffsetList[%d] - 0x%lx\n", Index
, ItemOffsetList
[Index
]));
755 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
757 DEBUG((DEBUG_VERBOSE
, " ImageHeader:\n"));
758 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", ImageHeader
->Version
));
759 DEBUG((DEBUG_VERBOSE
, " UpdateImageTypeId - %g\n", &ImageHeader
->UpdateImageTypeId
));
760 DEBUG((DEBUG_VERBOSE
, " UpdateImageIndex - 0x%x\n", ImageHeader
->UpdateImageIndex
));
761 DEBUG((DEBUG_VERBOSE
, " UpdateImageSize - 0x%x\n", ImageHeader
->UpdateImageSize
));
762 DEBUG((DEBUG_VERBOSE
, " UpdateVendorCodeSize - 0x%x\n", ImageHeader
->UpdateVendorCodeSize
));
763 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
764 DEBUG((DEBUG_VERBOSE
, " UpdateHardwareInstance - 0x%lx\n", ImageHeader
->UpdateHardwareInstance
));
770 Process Firmware management protocol data capsule.
772 This function assumes the caller validated the capsule by using
773 ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
774 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
775 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
777 This function need support nested FMP capsule.
779 @param[in] CapsuleHeader Points to a capsule header.
780 @param[in] AreAllImagesProcessed If all the FMP images in the capsule are processed.
782 @retval EFI_SUCESS Process Capsule Image successfully.
783 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
784 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
785 @retval EFI_OUT_OF_RESOURCES Not enough memory.
788 ProcessFmpCapsuleImage (
789 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
790 OUT BOOLEAN
*AreAllImagesProcessed
794 EFI_STATUS StatusEsrt
;
795 EFI_STATUS StatusRet
;
796 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
797 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
799 EFI_HANDLE ImageHandle
;
800 UINT64
*ItemOffsetList
;
804 EFI_HANDLE
*HandleBuffer
;
805 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
806 UINTN NumberOfHandles
;
807 UINTN DescriptorSize
;
808 UINT8 FmpImageInfoCount
;
809 UINT32 FmpImageInfoDescriptorVer
;
811 UINT32 PackageVersion
;
812 CHAR16
*PackageVersionName
;
814 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
815 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*TempFmpImageInfo
;
819 MEMMAP_DEVICE_PATH MemMapNode
;
820 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
821 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
822 EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry
;
825 if (!IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
826 return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
), AreAllImagesProcessed
);
829 ASSERT(AreAllImagesProcessed
!= NULL
);
831 Status
= EFI_SUCCESS
;
832 StatusRet
= EFI_NOT_FOUND
;
835 DriverDevicePath
= NULL
;
837 *AreAllImagesProcessed
= FALSE
;
839 DumpFmpCapsule(CapsuleHeader
);
841 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
843 if (FmpCapsuleHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
844 return EFI_INVALID_PARAMETER
;
846 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
848 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
851 // capsule in which driver count and payload count are both zero is not processed.
854 *AreAllImagesProcessed
= TRUE
;
859 // Update corresponding ESRT entry LastAttemp Status
861 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
862 if (EFI_ERROR (Status
)) {
867 // 1. Try to load & start all the drivers within capsule
869 SetDevicePathNodeLength (&MemMapNode
.Header
, sizeof (MemMapNode
));
870 MemMapNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
871 MemMapNode
.Header
.SubType
= HW_MEMMAP_DP
;
872 MemMapNode
.MemoryType
= EfiBootServicesCode
;
873 MemMapNode
.StartingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)CapsuleHeader
;
874 MemMapNode
.EndingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
- 1);
876 DriverDevicePath
= AppendDevicePathNode (NULL
, &MemMapNode
.Header
);
877 if (DriverDevicePath
== NULL
) {
878 return EFI_OUT_OF_RESOURCES
;
881 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
882 if (FmpCapsuleHeader
->PayloadItemCount
== 0 && Index
== (UINTN
)FmpCapsuleHeader
->EmbeddedDriverCount
- 1) {
884 // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
886 DriverLen
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
- (UINTN
)ItemOffsetList
[Index
];
888 DriverLen
= (UINTN
)ItemOffsetList
[Index
+ 1] - (UINTN
)ItemOffsetList
[Index
];
891 DEBUG((DEBUG_INFO
, "FmpCapsule: LoadImage ...\n"));
892 Status
= gBS
->LoadImage(
896 (UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
],
900 DEBUG((DEBUG_INFO
, "FmpCapsule: LoadImage - %r\n", Status
));
901 if (EFI_ERROR(Status
)) {
906 DEBUG((DEBUG_INFO
, "FmpCapsule: StartImage ...\n"));
907 Status
= gBS
->StartImage(
912 DEBUG((DEBUG_INFO
, "FmpCapsule: StartImage - %r\n", Status
));
913 if (EFI_ERROR(Status
)) {
914 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
921 // 2. Route payload to right FMP instance
923 DEBUG((DEBUG_INFO
, "FmpCapsule: route payload to right FMP instance ...\n"));
925 Status
= gBS
->LocateHandleBuffer (
927 &gEfiFirmwareManagementProtocolGuid
,
933 if (!EFI_ERROR(Status
)) {
934 for(Index1
= 0; Index1
< NumberOfHandles
; Index1
++) {
935 Status
= gBS
->HandleProtocol(
936 HandleBuffer
[Index1
],
937 &gEfiFirmwareManagementProtocolGuid
,
940 if (EFI_ERROR(Status
)) {
945 Status
= Fmp
->GetImageInfo (
955 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
959 FmpImageInfoBuf
= NULL
;
960 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
961 if (FmpImageInfoBuf
== NULL
) {
962 StatusRet
= EFI_OUT_OF_RESOURCES
;
966 PackageVersionName
= NULL
;
967 Status
= Fmp
->GetImageInfo (
969 &ImageInfoSize
, // ImageInfoSize
970 FmpImageInfoBuf
, // ImageInfo
971 &FmpImageInfoDescriptorVer
, // DescriptorVersion
972 &FmpImageInfoCount
, // DescriptorCount
973 &DescriptorSize
, // DescriptorSize
974 &PackageVersion
, // PackageVersion
975 &PackageVersionName
// PackageVersionName
979 // If FMP GetInformation interface failed, skip this resource
981 if (EFI_ERROR(Status
)) {
982 FreePool(FmpImageInfoBuf
);
986 DEBUG((DEBUG_INFO
, "FMP (%d) ImageInfo:\n", Index
));
988 ImageInfoSize
, // ImageInfoSize
989 FmpImageInfoBuf
, // ImageInfo
990 FmpImageInfoDescriptorVer
, // DescriptorVersion
991 FmpImageInfoCount
, // DescriptorCount
992 DescriptorSize
, // DescriptorSize
993 PackageVersion
, // PackageVersion
994 PackageVersionName
// PackageVersionName
997 if (PackageVersionName
!= NULL
) {
998 FreePool(PackageVersionName
);
1001 TempFmpImageInfo
= FmpImageInfoBuf
;
1002 for (Index2
= 0; Index2
< FmpImageInfoCount
; Index2
++) {
1004 // Check all the payload entry in capsule payload list
1006 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
1007 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
1009 if (IsFmpCapsuleProcessed(CapsuleHeader
, Index
- FmpCapsuleHeader
->EmbeddedDriverCount
, ImageHeader
)) {
1010 DEBUG((DEBUG_INFO
, "FMP Capsule already processed (%g):", CapsuleHeader
));
1011 DEBUG((DEBUG_INFO
, "ImageTypeId - %g, ", ImageHeader
->UpdateImageTypeId
));
1012 DEBUG((DEBUG_INFO
, "PayloadIndex - 0x%x, ImageIndex - 0x%x\n", Index
- FmpCapsuleHeader
->EmbeddedDriverCount
, ImageHeader
->UpdateImageIndex
));
1016 if (CompareGuid(&ImageHeader
->UpdateImageTypeId
, &TempFmpImageInfo
->ImageTypeId
) &&
1017 ImageHeader
->UpdateImageIndex
== TempFmpImageInfo
->ImageIndex
) {
1019 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
1020 if(ImageHeader
->UpdateHardwareInstance
!= 0){
1022 // FMP Version is >=2 & UpdateHardwareInstance Skip 2 case
1023 // 1. FMP Image info Version < 3
1024 // 2. HardwareInstance doesn't match
1026 if (FmpImageInfoDescriptorVer
< EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
||
1027 ImageHeader
->UpdateHardwareInstance
!= TempFmpImageInfo
->HardwareInstance
) {
1031 Image
= (UINT8
*)(ImageHeader
+ 1);
1034 // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1, only match ImageTypeId.
1035 // Header should exclude UpdateHardwareInstance field
1037 Image
= (UINT8
*)ImageHeader
+ OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
1040 if (ImageHeader
->UpdateVendorCodeSize
== 0) {
1043 VendorCode
= Image
+ ImageHeader
->UpdateImageSize
;
1045 DEBUG((DEBUG_INFO
, "Fmp->SetImage ...\n"));
1046 Status
= Fmp
->SetImage(
1048 ImageHeader
->UpdateImageIndex
, // ImageIndex
1050 ImageHeader
->UpdateImageSize
, // ImageSize
1051 VendorCode
, // VendorCode
1052 Update_Image_Progress
, // Progress
1053 &AbortReason
// AbortReason
1055 DEBUG((DEBUG_INFO
, "Fmp->SetImage - %r\n", Status
));
1056 if (AbortReason
!= NULL
) {
1057 DEBUG ((DEBUG_ERROR
, "%s\n", AbortReason
));
1058 FreePool(AbortReason
);
1060 RecordFmpCapsuleStatusVariable(
1061 CapsuleHeader
, // CapsuleGuid
1062 Status
, // CapsuleStatus
1063 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
, // PayloadIndex
1064 ImageHeader
// ImageHeader
1066 if (StatusRet
!= EFI_SUCCESS
) {
1070 // Update EsrtEntry For V1, V2 FMP instance. V3 FMP ESRT cache will be synced up through EsrtSyncFmp interface
1072 if (FmpImageInfoDescriptorVer
< EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
&& EsrtProtocol
!= NULL
) {
1073 StatusEsrt
= EsrtProtocol
->GetEsrtEntry(&TempFmpImageInfo
->ImageTypeId
, &EsrtEntry
);
1074 if (!EFI_ERROR(StatusEsrt
)){
1075 if (!EFI_ERROR(Status
)) {
1076 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_SUCCESS
;
1078 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL
;
1080 EsrtEntry
.LastAttemptVersion
= 0;
1081 EsrtProtocol
->UpdateEsrtEntry(&EsrtEntry
);
1087 // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
1089 TempFmpImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)TempFmpImageInfo
+ DescriptorSize
);
1091 FreePool(FmpImageInfoBuf
);
1096 // final check for AreAllImagesProcessed
1098 *AreAllImagesProcessed
= TRUE
;
1099 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
1100 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
1102 if (!IsFmpCapsuleProcessed(CapsuleHeader
, Index
- FmpCapsuleHeader
->EmbeddedDriverCount
, ImageHeader
)) {
1103 *AreAllImagesProcessed
= FALSE
;
1110 if (HandleBuffer
!= NULL
) {
1111 FreePool(HandleBuffer
);
1114 if (DriverDevicePath
!= NULL
) {
1115 FreePool(DriverDevicePath
);
1122 Return if there is a FMP header below capsule header.
1124 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1126 @retval TRUE There is a FMP header below capsule header.
1127 @retval FALSE There is not a FMP header below capsule header
1130 IsNestedFmpCapsule (
1131 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1135 EFI_SYSTEM_RESOURCE_TABLE
*Esrt
;
1136 EFI_SYSTEM_RESOURCE_ENTRY
*EsrtEntry
;
1138 BOOLEAN EsrtGuidFound
;
1139 EFI_CAPSULE_HEADER
*NestedCapsuleHeader
;
1140 UINTN NestedCapsuleSize
;
1141 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
1142 EFI_SYSTEM_RESOURCE_ENTRY Entry
;
1144 EsrtGuidFound
= FALSE
;
1147 // Check ESRT protocol
1149 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
1150 if (!EFI_ERROR(Status
)) {
1151 Status
= EsrtProtocol
->GetEsrtEntry(&CapsuleHeader
->CapsuleGuid
, &Entry
);
1152 if (!EFI_ERROR(Status
)) {
1153 EsrtGuidFound
= TRUE
;
1158 // Check ESRT configuration table
1160 if (!EsrtGuidFound
) {
1161 Status
= EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid
, (VOID
**)&Esrt
);
1162 if (!EFI_ERROR(Status
)) {
1163 ASSERT (Esrt
!= NULL
);
1164 EsrtEntry
= (VOID
*)(Esrt
+ 1);
1165 for (Index
= 0; Index
< Esrt
->FwResourceCount
; Index
++, EsrtEntry
++) {
1166 if (CompareGuid(&EsrtEntry
->FwClass
, &CapsuleHeader
->CapsuleGuid
)) {
1167 EsrtGuidFound
= TRUE
;
1173 if (!EsrtGuidFound
) {
1178 // Check nested capsule header
1179 // FMP GUID after ESRT one
1181 NestedCapsuleHeader
= (EFI_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
1182 NestedCapsuleSize
= (UINTN
)CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
- (UINTN
)NestedCapsuleHeader
;
1183 if (NestedCapsuleSize
< sizeof(EFI_CAPSULE_HEADER
)) {
1186 if (!IsValidCapsuleHeader(NestedCapsuleHeader
, NestedCapsuleSize
)) {
1189 if (!IsFmpCapsuleGuid(&NestedCapsuleHeader
->CapsuleGuid
)) {
1192 DEBUG ((DEBUG_INFO
, "IsNestedFmpCapsule\n"));
1197 Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
1199 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1201 @retval TRUE It is a system FMP.
1202 @retval FALSE It is a device FMP.
1206 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1209 if (IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
1212 if (IsNestedFmpCapsule(CapsuleHeader
)) {
1219 Those capsules supported by the firmwares.
1221 Caution: This function may receive untrusted input.
1223 @param[in] CapsuleHeader Points to a capsule header.
1225 @retval EFI_SUCESS Input capsule is supported by firmware.
1226 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
1227 @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
1231 SupportCapsuleImage (
1232 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1236 // check Display Capsule Guid
1238 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1242 if (IsFmpCapsule(CapsuleHeader
)) {
1244 // Check layout of FMP capsule
1246 return ValidateFmpCapsule(CapsuleHeader
, NULL
);
1248 DEBUG((DEBUG_ERROR
, "Unknown Capsule Guid - %g\n", &CapsuleHeader
->CapsuleGuid
));
1249 return EFI_UNSUPPORTED
;
1253 The firmware implements to process the capsule image.
1255 Caution: This function may receive untrusted input.
1257 @param[in] CapsuleHeader Points to a capsule header.
1259 @retval EFI_SUCESS Process Capsule Image successfully.
1260 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1261 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1262 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1266 ProcessCapsuleImage (
1267 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1271 BOOLEAN AreAllImagesProcessed
;
1273 if (SupportCapsuleImage (CapsuleHeader
) != EFI_SUCCESS
) {
1274 return EFI_UNSUPPORTED
;
1278 // Display image in firmware update display capsule
1280 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1281 DEBUG((DEBUG_INFO
, "ProcessCapsuleImage for WindowsUxCapsule ...\n"));
1282 Status
= DisplayCapsuleImage(CapsuleHeader
);
1283 RecordCapsuleStatusVariable(CapsuleHeader
, Status
);
1288 // Check FMP capsule layout
1290 if (IsFmpCapsule (CapsuleHeader
)) {
1291 DEBUG((DEBUG_INFO
, "ProcessCapsuleImage for FmpCapsule ...\n"));
1292 DEBUG((DEBUG_INFO
, "ValidateFmpCapsule ...\n"));
1293 Status
= ValidateFmpCapsule(CapsuleHeader
, NULL
);
1294 DEBUG((DEBUG_INFO
, "ValidateFmpCapsule - %r\n", Status
));
1295 if (EFI_ERROR(Status
)) {
1300 // Press EFI FMP Capsule
1302 DEBUG((DEBUG_INFO
, "ProcessFmpCapsuleImage ...\n"));
1303 Status
= ProcessFmpCapsuleImage(CapsuleHeader
, &AreAllImagesProcessed
);
1304 DEBUG((DEBUG_INFO
, "ProcessFmpCapsuleImage - %r\n", Status
));
1306 if (!AreAllImagesProcessed
) {
1307 mAreAllImagesProcessed
= FALSE
;
1313 return EFI_UNSUPPORTED
;
1317 Callback function executed when the EndOfDxe event group is signaled.
1319 @param[in] Event Event whose notification function is being invoked.
1320 @param[in] Context The pointer to the notification function's context, which
1321 is implementation-dependent.
1325 DxeCapsuleLibEndOfDxe (
1330 mDxeCapsuleLibEndOfDxe
= TRUE
;
1334 The constructor function.
1336 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1337 @param[in] SystemTable A pointer to the EFI System Table.
1339 @retval EFI_SUCCESS The constructor successfully .
1343 DxeCapsuleLibConstructor (
1344 IN EFI_HANDLE ImageHandle
,
1345 IN EFI_SYSTEM_TABLE
*SystemTable
1348 EFI_EVENT EndOfDxeEvent
;
1351 Status
= gBS
->CreateEventEx (
1354 DxeCapsuleLibEndOfDxe
,
1356 &gEfiEndOfDxeEventGroupGuid
,
1359 ASSERT_EFI_ERROR (Status
);
1361 InitCapsuleVariable();