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(), and DisplayCapsuleImage() receives untrusted input and
11 performs basic validation.
13 Copyright (c) 2016 - 2018, 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/WindowsUxCapsule.h>
28 #include <Guid/FmpCapsule.h>
29 #include <Guid/SystemResourceTable.h>
30 #include <Guid/EventGroup.h>
32 #include <Library/BaseLib.h>
33 #include <Library/DebugLib.h>
34 #include <Library/BaseMemoryLib.h>
35 #include <Library/DxeServicesTableLib.h>
36 #include <Library/UefiBootServicesTableLib.h>
37 #include <Library/UefiRuntimeServicesTableLib.h>
38 #include <Library/MemoryAllocationLib.h>
39 #include <Library/CapsuleLib.h>
40 #include <Library/DevicePathLib.h>
41 #include <Library/UefiLib.h>
42 #include <Library/PcdLib.h>
43 #include <Library/BmpSupportLib.h>
45 #include <Protocol/GraphicsOutput.h>
46 #include <Protocol/EsrtManagement.h>
47 #include <Protocol/FirmwareManagement.h>
48 #include <Protocol/DevicePath.h>
50 EFI_SYSTEM_RESOURCE_TABLE
*mEsrtTable
= NULL
;
51 BOOLEAN mIsVirtualAddrConverted
= FALSE
;
53 BOOLEAN mDxeCapsuleLibEndOfDxe
= FALSE
;
54 EFI_EVENT mDxeCapsuleLibEndOfDxeEvent
= NULL
;
57 Initialize capsule related variables.
65 Record capsule status variable.
67 @param[in] CapsuleHeader The capsule image header
68 @param[in] CapsuleStatus The capsule process stauts
70 @retval EFI_SUCCESS The capsule status variable is recorded.
71 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
74 RecordCapsuleStatusVariable (
75 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
76 IN EFI_STATUS CapsuleStatus
80 Record FMP capsule status variable.
82 @param[in] CapsuleHeader The capsule image header
83 @param[in] CapsuleStatus The capsule process stauts
84 @param[in] PayloadIndex FMP payload index
85 @param[in] ImageHeader FMP image header
86 @param[in] FmpDevicePath DevicePath associated with the FMP producer
88 @retval EFI_SUCCESS The capsule status variable is recorded.
89 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
92 RecordFmpCapsuleStatusVariable (
93 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
94 IN EFI_STATUS CapsuleStatus
,
95 IN UINTN PayloadIndex
,
96 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
,
97 IN EFI_DEVICE_PATH_PROTOCOL
*FmpDevicePath OPTIONAL
101 Function indicate the current completion progress of the firmware
102 update. Platform may override with own specific progress function.
104 @param[in] Completion A value between 1 and 100 indicating the current completion progress of the firmware update
106 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
110 Update_Image_Progress (
118 Return if this CapsuleGuid is a FMP capsule GUID or not.
120 @param[in] CapsuleGuid A pointer to EFI_GUID
122 @retval TRUE It is a FMP capsule GUID.
123 @retval FALSE It is not a FMP capsule GUID.
127 IN EFI_GUID
*CapsuleGuid
130 if (CompareGuid(&gEfiFmpCapsuleGuid
, CapsuleGuid
)) {
138 Validate if it is valid capsule header
140 Caution: This function may receive untrusted input.
142 This function assumes the caller provided correct CapsuleHeader pointer
145 This function validates the fields in EFI_CAPSULE_HEADER.
147 @param[in] CapsuleHeader Points to a capsule header.
148 @param[in] CapsuleSize Size of the whole capsule image.
152 IsValidCapsuleHeader (
153 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
154 IN UINT64 CapsuleSize
157 if (CapsuleHeader
->CapsuleImageSize
!= CapsuleSize
) {
160 if (CapsuleHeader
->HeaderSize
>= CapsuleHeader
->CapsuleImageSize
) {
167 Validate Fmp capsules layout.
169 Caution: This function may receive untrusted input.
171 This function assumes the caller validated the capsule by using
172 IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.
173 The capsule buffer size is CapsuleHeader->CapsuleImageSize.
175 This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
176 and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
178 This function need support nested FMP capsule.
180 @param[in] CapsuleHeader Points to a capsule header.
181 @param[out] EmbeddedDriverCount The EmbeddedDriverCount in the FMP capsule.
183 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
184 @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.
188 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
189 OUT UINT16
*EmbeddedDriverCount OPTIONAL
192 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
194 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
196 UINT64
*ItemOffsetList
;
199 UINTN FmpCapsuleSize
;
200 UINTN FmpCapsuleHeaderSize
;
202 UINTN FmpImageHeaderSize
;
204 if (!IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
205 return ValidateFmpCapsule ((EFI_CAPSULE_HEADER
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
), EmbeddedDriverCount
);
208 if (CapsuleHeader
->HeaderSize
>= CapsuleHeader
->CapsuleImageSize
) {
209 DEBUG((DEBUG_ERROR
, "HeaderSize(0x%x) >= CapsuleImageSize(0x%x)\n", CapsuleHeader
->HeaderSize
, CapsuleHeader
->CapsuleImageSize
));
210 return EFI_INVALID_PARAMETER
;
213 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
214 EndOfCapsule
= (UINT8
*) CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
;
215 FmpCapsuleSize
= (UINTN
)EndOfCapsule
- (UINTN
)FmpCapsuleHeader
;
217 if (FmpCapsuleSize
< sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
)) {
218 DEBUG((DEBUG_ERROR
, "FmpCapsuleSize(0x%x) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\n", FmpCapsuleSize
));
219 return EFI_INVALID_PARAMETER
;
222 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
223 if (FmpCapsuleHeader
->Version
!= EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
224 DEBUG((DEBUG_ERROR
, "FmpCapsuleHeader->Version(0x%x) != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION\n", FmpCapsuleHeader
->Version
));
225 return EFI_INVALID_PARAMETER
;
227 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
230 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
232 if ((FmpCapsuleSize
- sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
))/sizeof(UINT64
) < ItemNum
) {
233 DEBUG((DEBUG_ERROR
, "ItemNum(0x%x) too big\n", ItemNum
));
234 return EFI_INVALID_PARAMETER
;
236 FmpCapsuleHeaderSize
= sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
) + sizeof(UINT64
)*ItemNum
;
238 // Check ItemOffsetList
239 for (Index
= 0; Index
< ItemNum
; Index
++) {
240 if (ItemOffsetList
[Index
] >= FmpCapsuleSize
) {
241 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) >= FmpCapsuleSize(0x%x)\n", Index
, ItemOffsetList
[Index
], FmpCapsuleSize
));
242 return EFI_INVALID_PARAMETER
;
244 if (ItemOffsetList
[Index
] < FmpCapsuleHeaderSize
) {
245 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) < FmpCapsuleHeaderSize(0x%x)\n", Index
, ItemOffsetList
[Index
], FmpCapsuleHeaderSize
));
246 return EFI_INVALID_PARAMETER
;
249 // All the address in ItemOffsetList must be stored in ascending order
252 if (ItemOffsetList
[Index
] <= ItemOffsetList
[Index
- 1]) {
253 DEBUG((DEBUG_ERROR
, "ItemOffsetList[%d](0x%lx) < ItemOffsetList[%d](0x%x)\n", Index
, ItemOffsetList
[Index
], Index
, ItemOffsetList
[Index
- 1]));
254 return EFI_INVALID_PARAMETER
;
259 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
260 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
261 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
262 if (Index
== ItemNum
- 1) {
263 EndOfPayload
= (UINT8
*)((UINTN
)EndOfCapsule
- (UINTN
)FmpCapsuleHeader
);
265 EndOfPayload
= (UINT8
*)(UINTN
)ItemOffsetList
[Index
+1];
267 FmpImageSize
= (UINTN
)EndOfPayload
- ItemOffsetList
[Index
];
269 if (FmpImageSize
< OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
)) {
270 DEBUG((DEBUG_ERROR
, "FmpImageSize(0x%lx) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER\n", FmpImageSize
));
271 return EFI_INVALID_PARAMETER
;
273 FmpImageHeaderSize
= sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
);
274 if ((ImageHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) ||
275 (ImageHeader
->Version
< 1)) {
276 DEBUG((DEBUG_ERROR
, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader
->Version
));
277 return EFI_INVALID_PARAMETER
;
279 if (ImageHeader
->Version
< EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
280 FmpImageHeaderSize
= OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
284 if (FmpImageSize
!= (UINT64
)FmpImageHeaderSize
+ (UINT64
)ImageHeader
->UpdateImageSize
+ (UINT64
)ImageHeader
->UpdateVendorCodeSize
) {
285 DEBUG((DEBUG_ERROR
, "FmpImageSize(0x%lx) mismatch, UpdateImageSize(0x%x) UpdateVendorCodeSize(0x%x)\n", FmpImageSize
, ImageHeader
->UpdateImageSize
, ImageHeader
->UpdateVendorCodeSize
));
286 return EFI_INVALID_PARAMETER
;
292 // No driver & payload element in FMP
294 EndOfPayload
= (UINT8
*)(FmpCapsuleHeader
+ 1);
295 if (EndOfPayload
!= EndOfCapsule
) {
296 DEBUG((DEBUG_ERROR
, "EndOfPayload(0x%x) mismatch, EndOfCapsule(0x%x)\n", EndOfPayload
, EndOfCapsule
));
297 return EFI_INVALID_PARAMETER
;
299 return EFI_UNSUPPORTED
;
302 if (EmbeddedDriverCount
!= NULL
) {
303 *EmbeddedDriverCount
= FmpCapsuleHeader
->EmbeddedDriverCount
;
310 Those capsules supported by the firmwares.
312 Caution: This function may receive untrusted input.
314 @param[in] CapsuleHeader Points to a capsule header.
316 @retval EFI_SUCESS Input capsule is supported by firmware.
317 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
320 DisplayCapsuleImage (
321 IN EFI_CAPSULE_HEADER
*CapsuleHeader
324 DISPLAY_DISPLAY_PAYLOAD
*ImagePayload
;
327 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
331 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
333 ImagePayload
= (DISPLAY_DISPLAY_PAYLOAD
*)(CapsuleHeader
+ 1);
334 PayloadSize
= CapsuleHeader
->CapsuleImageSize
- sizeof(EFI_CAPSULE_HEADER
);
336 if (ImagePayload
->Version
!= 1) {
337 return EFI_UNSUPPORTED
;
339 if (CalculateCheckSum8((UINT8
*)CapsuleHeader
, CapsuleHeader
->CapsuleImageSize
) != 0) {
340 return EFI_UNSUPPORTED
;
343 // Only Support Bitmap by now
345 if (ImagePayload
->ImageType
!= 0) {
346 return EFI_UNSUPPORTED
;
352 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**)&GraphicsOutput
);
353 if (EFI_ERROR (Status
)) {
354 Status
= gBS
->LocateProtocol(&gEfiGraphicsOutputProtocolGuid
, NULL
, (VOID
**)&GraphicsOutput
);
355 if (EFI_ERROR(Status
)) {
356 return EFI_UNSUPPORTED
;
360 if (GraphicsOutput
->Mode
->Mode
!= ImagePayload
->Mode
) {
361 return EFI_UNSUPPORTED
;
367 Status
= TranslateBmpToGopBlt (
369 PayloadSize
- sizeof(DISPLAY_DISPLAY_PAYLOAD
),
376 if (EFI_ERROR (Status
)) {
380 Status
= GraphicsOutput
->Blt (
386 (UINTN
) ImagePayload
->OffsetX
,
387 (UINTN
) ImagePayload
->OffsetY
,
390 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
399 Dump FMP information.
401 @param[in] ImageInfoSize The size of ImageInfo, in bytes.
402 @param[in] ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
403 @param[in] DescriptorVersion The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
404 @param[in] DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
405 @param[in] DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
406 @param[in] PackageVersion The version of package.
407 @param[in] PackageVersionName The version name of package.
411 IN UINTN ImageInfoSize
,
412 IN EFI_FIRMWARE_IMAGE_DESCRIPTOR
*ImageInfo
,
413 IN UINT32 DescriptorVersion
,
414 IN UINT8 DescriptorCount
,
415 IN UINTN DescriptorSize
,
416 IN UINT32 PackageVersion
,
417 IN CHAR16
*PackageVersionName
420 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*CurrentImageInfo
;
423 DEBUG((DEBUG_VERBOSE
, " DescriptorVersion - 0x%x\n", DescriptorVersion
));
424 DEBUG((DEBUG_VERBOSE
, " DescriptorCount - 0x%x\n", DescriptorCount
));
425 DEBUG((DEBUG_VERBOSE
, " DescriptorSize - 0x%x\n", DescriptorSize
));
426 DEBUG((DEBUG_VERBOSE
, " PackageVersion - 0x%x\n", PackageVersion
));
427 DEBUG((DEBUG_VERBOSE
, " PackageVersionName - %s\n\n", PackageVersionName
));
428 CurrentImageInfo
= ImageInfo
;
429 for (Index
= 0; Index
< DescriptorCount
; Index
++) {
430 DEBUG((DEBUG_VERBOSE
, " ImageDescriptor (%d)\n", Index
));
431 DEBUG((DEBUG_VERBOSE
, " ImageIndex - 0x%x\n", CurrentImageInfo
->ImageIndex
));
432 DEBUG((DEBUG_VERBOSE
, " ImageTypeId - %g\n", &CurrentImageInfo
->ImageTypeId
));
433 DEBUG((DEBUG_VERBOSE
, " ImageId - 0x%lx\n", CurrentImageInfo
->ImageId
));
434 DEBUG((DEBUG_VERBOSE
, " ImageIdName - %s\n", CurrentImageInfo
->ImageIdName
));
435 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", CurrentImageInfo
->Version
));
436 DEBUG((DEBUG_VERBOSE
, " VersionName - %s\n", CurrentImageInfo
->VersionName
));
437 DEBUG((DEBUG_VERBOSE
, " Size - 0x%x\n", CurrentImageInfo
->Size
));
438 DEBUG((DEBUG_VERBOSE
, " AttributesSupported - 0x%lx\n", CurrentImageInfo
->AttributesSupported
));
439 DEBUG((DEBUG_VERBOSE
, " AttributesSetting - 0x%lx\n", CurrentImageInfo
->AttributesSetting
));
440 DEBUG((DEBUG_VERBOSE
, " Compatibilities - 0x%lx\n", CurrentImageInfo
->Compatibilities
));
441 if (DescriptorVersion
> 1) {
442 DEBUG((DEBUG_VERBOSE
, " LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo
->LowestSupportedImageVersion
));
443 if (DescriptorVersion
> 2) {
444 DEBUG((DEBUG_VERBOSE
, " LastAttemptVersion - 0x%x\n", CurrentImageInfo
->LastAttemptVersion
));
445 DEBUG((DEBUG_VERBOSE
, " LastAttemptStatus - 0x%x\n", CurrentImageInfo
->LastAttemptStatus
));
446 DEBUG((DEBUG_VERBOSE
, " HardwareInstance - 0x%lx\n", CurrentImageInfo
->HardwareInstance
));
450 // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
452 CurrentImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)CurrentImageInfo
+ DescriptorSize
);
457 Dump a non-nested FMP capsule.
459 @param[in] CapsuleHeader A pointer to CapsuleHeader
463 IN EFI_CAPSULE_HEADER
*CapsuleHeader
466 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
467 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
469 UINT64
*ItemOffsetList
;
471 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
473 DEBUG((DEBUG_VERBOSE
, "FmpCapsule:\n"));
474 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", FmpCapsuleHeader
->Version
));
475 DEBUG((DEBUG_VERBOSE
, " EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader
->EmbeddedDriverCount
));
476 DEBUG((DEBUG_VERBOSE
, " PayloadItemCount - 0x%x\n", FmpCapsuleHeader
->PayloadItemCount
));
478 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
479 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
480 DEBUG((DEBUG_VERBOSE
, " ItemOffsetList[%d] - 0x%lx\n", Index
, ItemOffsetList
[Index
]));
482 for (; Index
< (UINT32
)FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
; Index
++) {
483 DEBUG((DEBUG_VERBOSE
, " ItemOffsetList[%d] - 0x%lx\n", Index
, ItemOffsetList
[Index
]));
484 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
486 DEBUG((DEBUG_VERBOSE
, " ImageHeader:\n"));
487 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", ImageHeader
->Version
));
488 DEBUG((DEBUG_VERBOSE
, " UpdateImageTypeId - %g\n", &ImageHeader
->UpdateImageTypeId
));
489 DEBUG((DEBUG_VERBOSE
, " UpdateImageIndex - 0x%x\n", ImageHeader
->UpdateImageIndex
));
490 DEBUG((DEBUG_VERBOSE
, " UpdateImageSize - 0x%x\n", ImageHeader
->UpdateImageSize
));
491 DEBUG((DEBUG_VERBOSE
, " UpdateVendorCodeSize - 0x%x\n", ImageHeader
->UpdateVendorCodeSize
));
492 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
493 DEBUG((DEBUG_VERBOSE
, " UpdateHardwareInstance - 0x%lx\n", ImageHeader
->UpdateHardwareInstance
));
499 Dump all FMP information.
507 EFI_HANDLE
*HandleBuffer
;
508 UINTN NumberOfHandles
;
509 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
512 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
513 UINT32 FmpImageInfoDescriptorVer
;
514 UINT8 FmpImageInfoCount
;
515 UINTN DescriptorSize
;
516 UINT32 PackageVersion
;
517 CHAR16
*PackageVersionName
;
519 Status
= gBS
->LocateHandleBuffer (
521 &gEfiFirmwareManagementProtocolGuid
,
526 if (EFI_ERROR(Status
)) {
530 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
531 Status
= gBS
->HandleProtocol(
533 &gEfiFirmwareManagementProtocolGuid
,
536 if (EFI_ERROR(Status
)) {
541 Status
= Fmp
->GetImageInfo (
551 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
555 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
556 if (FmpImageInfoBuf
== NULL
) {
560 PackageVersionName
= NULL
;
561 Status
= Fmp
->GetImageInfo (
563 &ImageInfoSize
, // ImageInfoSize
564 FmpImageInfoBuf
, // ImageInfo
565 &FmpImageInfoDescriptorVer
, // DescriptorVersion
566 &FmpImageInfoCount
, // DescriptorCount
567 &DescriptorSize
, // DescriptorSize
568 &PackageVersion
, // PackageVersion
569 &PackageVersionName
// PackageVersionName
571 if (EFI_ERROR(Status
)) {
572 FreePool(FmpImageInfoBuf
);
576 DEBUG((DEBUG_INFO
, "FMP (%d) ImageInfo:\n", Index
));
578 ImageInfoSize
, // ImageInfoSize
579 FmpImageInfoBuf
, // ImageInfo
580 FmpImageInfoDescriptorVer
, // DescriptorVersion
581 FmpImageInfoCount
, // DescriptorCount
582 DescriptorSize
, // DescriptorSize
583 PackageVersion
, // PackageVersion
584 PackageVersionName
// PackageVersionName
587 if (PackageVersionName
!= NULL
) {
588 FreePool(PackageVersionName
);
591 FreePool(FmpImageInfoBuf
);
598 Get FMP handle by ImageTypeId and HardwareInstance.
600 @param[in] UpdateImageTypeId Used to identify device firmware targeted by this update.
601 @param[in] UpdateHardwareInstance The HardwareInstance to target with this update.
602 @param[in,out] NoHandles The number of handles returned in Buffer.
603 @param[out] Buffer[out] A pointer to the buffer to return the requested array of handles.
605 @retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of
606 handles in Buffer was returned in NoHandles.
607 @retval EFI_NOT_FOUND No handles match the search.
608 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
611 GetFmpHandleBufferByType (
612 IN EFI_GUID
*UpdateImageTypeId
,
613 IN UINT64 UpdateHardwareInstance
,
614 IN OUT UINTN
*NoHandles
,
615 OUT EFI_HANDLE
**Buffer
619 EFI_HANDLE
*HandleBuffer
;
620 UINTN NumberOfHandles
;
621 EFI_HANDLE
*MatchedHandleBuffer
;
622 UINTN MatchedNumberOfHandles
;
623 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
626 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
627 UINT32 FmpImageInfoDescriptorVer
;
628 UINT8 FmpImageInfoCount
;
629 UINTN DescriptorSize
;
630 UINT32 PackageVersion
;
631 CHAR16
*PackageVersionName
;
633 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*TempFmpImageInfo
;
638 Status
= gBS
->LocateHandleBuffer (
640 &gEfiFirmwareManagementProtocolGuid
,
645 if (EFI_ERROR(Status
)) {
649 MatchedNumberOfHandles
= 0;
650 MatchedHandleBuffer
= AllocateZeroPool (sizeof(EFI_HANDLE
) * NumberOfHandles
);
651 if (MatchedHandleBuffer
== NULL
) {
652 FreePool (HandleBuffer
);
653 return EFI_OUT_OF_RESOURCES
;
656 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
657 Status
= gBS
->HandleProtocol(
659 &gEfiFirmwareManagementProtocolGuid
,
662 if (EFI_ERROR(Status
)) {
667 Status
= Fmp
->GetImageInfo (
677 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
681 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
682 if (FmpImageInfoBuf
== NULL
) {
686 PackageVersionName
= NULL
;
687 Status
= Fmp
->GetImageInfo (
689 &ImageInfoSize
, // ImageInfoSize
690 FmpImageInfoBuf
, // ImageInfo
691 &FmpImageInfoDescriptorVer
, // DescriptorVersion
692 &FmpImageInfoCount
, // DescriptorCount
693 &DescriptorSize
, // DescriptorSize
694 &PackageVersion
, // PackageVersion
695 &PackageVersionName
// PackageVersionName
697 if (EFI_ERROR(Status
)) {
698 FreePool(FmpImageInfoBuf
);
702 if (PackageVersionName
!= NULL
) {
703 FreePool(PackageVersionName
);
706 TempFmpImageInfo
= FmpImageInfoBuf
;
707 for (Index2
= 0; Index2
< FmpImageInfoCount
; Index2
++) {
709 // Check if this FMP instance matches
711 if (CompareGuid(UpdateImageTypeId
, &TempFmpImageInfo
->ImageTypeId
)) {
712 if ((UpdateHardwareInstance
== 0) ||
713 ((FmpImageInfoDescriptorVer
>= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
) &&
714 (UpdateHardwareInstance
== TempFmpImageInfo
->HardwareInstance
))) {
715 MatchedHandleBuffer
[MatchedNumberOfHandles
] = HandleBuffer
[Index
];
716 MatchedNumberOfHandles
++;
720 TempFmpImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)TempFmpImageInfo
+ DescriptorSize
);
722 FreePool(FmpImageInfoBuf
);
725 if (MatchedNumberOfHandles
== 0) {
726 return EFI_NOT_FOUND
;
729 *NoHandles
= MatchedNumberOfHandles
;
730 *Buffer
= MatchedHandleBuffer
;
736 Return FmpImageInfoDescriptorVer by an FMP handle.
738 @param[in] Handle A FMP handle.
740 @return FmpImageInfoDescriptorVer associated with the FMP.
743 GetFmpImageInfoDescriptorVer (
748 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
750 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
751 UINT32 FmpImageInfoDescriptorVer
;
752 UINT8 FmpImageInfoCount
;
753 UINTN DescriptorSize
;
754 UINT32 PackageVersion
;
755 CHAR16
*PackageVersionName
;
757 Status
= gBS
->HandleProtocol(
759 &gEfiFirmwareManagementProtocolGuid
,
762 if (EFI_ERROR(Status
)) {
767 Status
= Fmp
->GetImageInfo (
777 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
781 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
782 if (FmpImageInfoBuf
== NULL
) {
786 PackageVersionName
= NULL
;
787 Status
= Fmp
->GetImageInfo (
789 &ImageInfoSize
, // ImageInfoSize
790 FmpImageInfoBuf
, // ImageInfo
791 &FmpImageInfoDescriptorVer
, // DescriptorVersion
792 &FmpImageInfoCount
, // DescriptorCount
793 &DescriptorSize
, // DescriptorSize
794 &PackageVersion
, // PackageVersion
795 &PackageVersionName
// PackageVersionName
797 if (EFI_ERROR(Status
)) {
798 FreePool(FmpImageInfoBuf
);
801 return FmpImageInfoDescriptorVer
;
807 @param[in] Handle A FMP handle.
808 @param[in] ImageHeader The payload image header.
809 @param[in] PayloadIndex The index of the payload.
811 @return The status of FMP->SetImage.
815 IN EFI_HANDLE Handle
,
816 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
,
817 IN UINTN PayloadIndex
821 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
826 Status
= gBS
->HandleProtocol(
828 &gEfiFirmwareManagementProtocolGuid
,
831 if (EFI_ERROR(Status
)) {
835 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
836 Image
= (UINT8
*)(ImageHeader
+ 1);
839 // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1,
840 // Header should exclude UpdateHardwareInstance field
842 Image
= (UINT8
*)ImageHeader
+ OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
, UpdateHardwareInstance
);
845 if (ImageHeader
->UpdateVendorCodeSize
== 0) {
848 VendorCode
= Image
+ ImageHeader
->UpdateImageSize
;
851 DEBUG((DEBUG_INFO
, "Fmp->SetImage ...\n"));
852 DEBUG((DEBUG_INFO
, "ImageTypeId - %g, ", &ImageHeader
->UpdateImageTypeId
));
853 DEBUG((DEBUG_INFO
, "PayloadIndex - 0x%x, ", PayloadIndex
));
854 DEBUG((DEBUG_INFO
, "ImageIndex - 0x%x ", ImageHeader
->UpdateImageIndex
));
855 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
856 DEBUG((DEBUG_INFO
, "(UpdateHardwareInstance - 0x%x)", ImageHeader
->UpdateHardwareInstance
));
858 DEBUG((DEBUG_INFO
, "\n"));
859 Status
= Fmp
->SetImage(
861 ImageHeader
->UpdateImageIndex
, // ImageIndex
863 ImageHeader
->UpdateImageSize
, // ImageSize
864 VendorCode
, // VendorCode
865 Update_Image_Progress
, // Progress
866 &AbortReason
// AbortReason
868 DEBUG((DEBUG_INFO
, "Fmp->SetImage - %r\n", Status
));
869 if (AbortReason
!= NULL
) {
870 DEBUG ((DEBUG_ERROR
, "%s\n", AbortReason
));
871 FreePool(AbortReason
);
878 Start a UEFI image in the FMP payload.
880 @param[in] ImageBuffer A pointer to the memory location containing a copy of the image to be loaded..
881 @param[in] ImageSize The size in bytes of ImageBuffer.
883 @return The status of gBS->LoadImage and gBS->StartImage.
887 IN VOID
*ImageBuffer
,
891 MEMMAP_DEVICE_PATH MemMapNode
;
893 EFI_HANDLE ImageHandle
;
894 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
897 SetDevicePathNodeLength (&MemMapNode
.Header
, sizeof (MemMapNode
));
898 MemMapNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
899 MemMapNode
.Header
.SubType
= HW_MEMMAP_DP
;
900 MemMapNode
.MemoryType
= EfiBootServicesCode
;
901 MemMapNode
.StartingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)ImageBuffer
;
902 MemMapNode
.EndingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)((UINT8
*)ImageBuffer
+ ImageSize
- 1);
904 DriverDevicePath
= AppendDevicePathNode (NULL
, &MemMapNode
.Header
);
905 if (DriverDevicePath
== NULL
) {
906 return EFI_OUT_OF_RESOURCES
;
909 DEBUG((DEBUG_INFO
, "FmpCapsule: LoadImage ...\n"));
910 Status
= gBS
->LoadImage(
918 DEBUG((DEBUG_INFO
, "FmpCapsule: LoadImage - %r\n", Status
));
919 if (EFI_ERROR(Status
)) {
920 FreePool(DriverDevicePath
);
924 DEBUG((DEBUG_INFO
, "FmpCapsule: StartImage ...\n"));
925 Status
= gBS
->StartImage(
930 DEBUG((DEBUG_INFO
, "FmpCapsule: StartImage - %r\n", Status
));
931 if (EFI_ERROR(Status
)) {
932 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
935 FreePool(DriverDevicePath
);
940 Record FMP capsule status.
942 @param[in] Handle A FMP handle.
943 @param[in] CapsuleHeader The capsule image header
944 @param[in] CapsuleStatus The capsule process stauts
945 @param[in] PayloadIndex FMP payload index
946 @param[in] ImageHeader FMP image header
949 RecordFmpCapsuleStatus (
950 IN EFI_HANDLE Handle
, OPTIONAL
951 IN EFI_CAPSULE_HEADER
*CapsuleHeader
,
952 IN EFI_STATUS CapsuleStatus
,
953 IN UINTN PayloadIndex
,
954 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
958 EFI_DEVICE_PATH_PROTOCOL
*FmpDevicePath
;
959 UINT32 FmpImageInfoDescriptorVer
;
960 EFI_STATUS StatusEsrt
;
961 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
962 EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry
;
964 FmpDevicePath
= NULL
;
965 if (Handle
!= NULL
) {
968 &gEfiDevicePathProtocolGuid
,
969 (VOID
**)&FmpDevicePath
973 RecordFmpCapsuleStatusVariable (
982 // Update corresponding ESRT entry LastAttemp Status
984 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
985 if (EFI_ERROR (Status
)) {
989 if (Handle
== NULL
) {
994 // Update EsrtEntry For V1, V2 FMP instance.
995 // V3 FMP ESRT cache will be synced up through EsrtSyncFmp interface
997 FmpImageInfoDescriptorVer
= GetFmpImageInfoDescriptorVer (Handle
);
998 if (FmpImageInfoDescriptorVer
< EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
) {
999 StatusEsrt
= EsrtProtocol
->GetEsrtEntry(&ImageHeader
->UpdateImageTypeId
, &EsrtEntry
);
1000 if (!EFI_ERROR(StatusEsrt
)){
1001 if (!EFI_ERROR(CapsuleStatus
)) {
1002 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_SUCCESS
;
1004 EsrtEntry
.LastAttemptStatus
= LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL
;
1006 EsrtEntry
.LastAttemptVersion
= 0;
1007 EsrtProtocol
->UpdateEsrtEntry(&EsrtEntry
);
1013 Process Firmware management protocol data capsule.
1015 This function assumes the caller validated the capsule by using
1016 ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
1017 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
1018 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
1020 This function need support nested FMP capsule.
1022 @param[in] CapsuleHeader Points to a capsule header.
1024 @retval EFI_SUCESS Process Capsule Image successfully.
1025 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1026 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1027 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1028 @retval EFI_NOT_READY No FMP protocol to handle this FMP capsule.
1031 ProcessFmpCapsuleImage (
1032 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1036 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
1037 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
1038 UINT64
*ItemOffsetList
;
1041 EFI_HANDLE
*HandleBuffer
;
1042 UINTN NumberOfHandles
;
1044 UINT64 UpdateHardwareInstance
;
1049 if (!IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
1050 return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER
*)((UINTN
)CapsuleHeader
+ CapsuleHeader
->HeaderSize
));
1056 DumpFmpCapsule(CapsuleHeader
);
1058 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
1060 if (FmpCapsuleHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
1061 return EFI_INVALID_PARAMETER
;
1063 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
1065 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
1068 // capsule in which driver count and payload count are both zero is not processed.
1075 // 1. Try to load & start all the drivers within capsule
1077 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
1078 if ((FmpCapsuleHeader
->PayloadItemCount
== 0) &&
1079 (Index
== (UINTN
)FmpCapsuleHeader
->EmbeddedDriverCount
- 1)) {
1081 // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
1083 DriverLen
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
- (UINTN
)ItemOffsetList
[Index
];
1085 DriverLen
= (UINTN
)ItemOffsetList
[Index
+ 1] - (UINTN
)ItemOffsetList
[Index
];
1088 Status
= StartFmpImage (
1089 (UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
],
1092 if (EFI_ERROR(Status
)) {
1093 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
1099 // 2. Route payload to right FMP instance
1101 DEBUG((DEBUG_INFO
, "FmpCapsule: route payload to right FMP instance ...\n"));
1106 // Check all the payload entry in capsule payload list
1108 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
1109 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
1111 UpdateHardwareInstance
= 0;
1112 if (ImageHeader
->Version
>= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
) {
1113 UpdateHardwareInstance
= ImageHeader
->UpdateHardwareInstance
;
1116 Status
= GetFmpHandleBufferByType (
1117 &ImageHeader
->UpdateImageTypeId
,
1118 UpdateHardwareInstance
,
1122 if (EFI_ERROR(Status
)) {
1124 RecordFmpCapsuleStatus (
1128 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1134 for (Index2
= 0; Index2
< NumberOfHandles
; Index2
++) {
1136 RecordFmpCapsuleStatus (
1137 HandleBuffer
[Index2
],
1140 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1146 Status
= SetFmpImageData (
1147 HandleBuffer
[Index2
],
1149 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
1151 if (Status
!= EFI_SUCCESS
) {
1155 RecordFmpCapsuleStatus (
1156 HandleBuffer
[Index2
],
1159 Index
- FmpCapsuleHeader
->EmbeddedDriverCount
,
1163 if (HandleBuffer
!= NULL
) {
1164 FreePool(HandleBuffer
);
1169 return EFI_NOT_READY
;
1173 // always return SUCCESS to indicate this capsule is processed.
1174 // The status of SetImage is recorded in capsule result variable.
1180 Return if there is a FMP header below capsule header.
1182 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1184 @retval TRUE There is a FMP header below capsule header.
1185 @retval FALSE There is not a FMP header below capsule header
1188 IsNestedFmpCapsule (
1189 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1193 EFI_SYSTEM_RESOURCE_ENTRY
*EsrtEntry
;
1195 BOOLEAN EsrtGuidFound
;
1196 EFI_CAPSULE_HEADER
*NestedCapsuleHeader
;
1197 UINTN NestedCapsuleSize
;
1198 ESRT_MANAGEMENT_PROTOCOL
*EsrtProtocol
;
1199 EFI_SYSTEM_RESOURCE_ENTRY Entry
;
1200 EFI_HANDLE
*HandleBuffer
;
1201 UINTN NumberOfHandles
;
1203 EsrtGuidFound
= FALSE
;
1204 if (mIsVirtualAddrConverted
) {
1205 if(mEsrtTable
!= NULL
) {
1206 EsrtEntry
= (EFI_SYSTEM_RESOURCE_ENTRY
*)(mEsrtTable
+ 1);
1207 for (Index
= 0; Index
< mEsrtTable
->FwResourceCount
; Index
++, EsrtEntry
++) {
1208 if (CompareGuid(&EsrtEntry
->FwClass
, &CapsuleHeader
->CapsuleGuid
)) {
1209 EsrtGuidFound
= TRUE
;
1216 // Check ESRT protocol
1218 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtProtocol
);
1219 if (!EFI_ERROR(Status
)) {
1220 Status
= EsrtProtocol
->GetEsrtEntry(&CapsuleHeader
->CapsuleGuid
, &Entry
);
1221 if (!EFI_ERROR(Status
)) {
1222 EsrtGuidFound
= TRUE
;
1227 // Check Firmware Management Protocols
1229 if (!EsrtGuidFound
) {
1230 HandleBuffer
= NULL
;
1231 Status
= GetFmpHandleBufferByType (
1232 &CapsuleHeader
->CapsuleGuid
,
1237 if (!EFI_ERROR(Status
)) {
1238 EsrtGuidFound
= TRUE
;
1240 if (HandleBuffer
!= NULL
) {
1241 FreePool (HandleBuffer
);
1245 if (!EsrtGuidFound
) {
1250 // Check nested capsule header
1251 // FMP GUID after ESRT one
1253 NestedCapsuleHeader
= (EFI_CAPSULE_HEADER
*)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
1254 NestedCapsuleSize
= (UINTN
)CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
- (UINTN
)NestedCapsuleHeader
;
1255 if (NestedCapsuleSize
< sizeof(EFI_CAPSULE_HEADER
)) {
1258 if (!IsValidCapsuleHeader(NestedCapsuleHeader
, NestedCapsuleSize
)) {
1261 if (!IsFmpCapsuleGuid(&NestedCapsuleHeader
->CapsuleGuid
)) {
1264 DEBUG ((DEBUG_INFO
, "IsNestedFmpCapsule\n"));
1269 Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
1271 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1273 @retval TRUE It is a system FMP.
1274 @retval FALSE It is a device FMP.
1278 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1281 if (IsFmpCapsuleGuid(&CapsuleHeader
->CapsuleGuid
)) {
1284 if (IsNestedFmpCapsule(CapsuleHeader
)) {
1291 Those capsules supported by the firmwares.
1293 Caution: This function may receive untrusted input.
1295 @param[in] CapsuleHeader Points to a capsule header.
1297 @retval EFI_SUCESS Input capsule is supported by firmware.
1298 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
1299 @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
1303 SupportCapsuleImage (
1304 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1308 // check Display Capsule Guid
1310 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1314 if (IsFmpCapsule(CapsuleHeader
)) {
1316 // Check layout of FMP capsule
1318 return ValidateFmpCapsule(CapsuleHeader
, NULL
);
1320 DEBUG((DEBUG_ERROR
, "Unknown Capsule Guid - %g\n", &CapsuleHeader
->CapsuleGuid
));
1321 return EFI_UNSUPPORTED
;
1325 The firmware implements to process the capsule image.
1327 Caution: This function may receive untrusted input.
1329 @param[in] CapsuleHeader Points to a capsule header.
1331 @retval EFI_SUCESS Process Capsule Image successfully.
1332 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1333 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1334 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1338 ProcessCapsuleImage (
1339 IN EFI_CAPSULE_HEADER
*CapsuleHeader
1344 if (SupportCapsuleImage (CapsuleHeader
) != EFI_SUCCESS
) {
1345 RecordCapsuleStatusVariable(CapsuleHeader
, EFI_UNSUPPORTED
);
1346 return EFI_UNSUPPORTED
;
1350 // Display image in firmware update display capsule
1352 if (CompareGuid (&gWindowsUxCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
1353 DEBUG((DEBUG_INFO
, "ProcessCapsuleImage for WindowsUxCapsule ...\n"));
1354 Status
= DisplayCapsuleImage(CapsuleHeader
);
1355 RecordCapsuleStatusVariable(CapsuleHeader
, Status
);
1360 // Check FMP capsule layout
1362 if (IsFmpCapsule (CapsuleHeader
)) {
1363 DEBUG((DEBUG_INFO
, "ProcessCapsuleImage for FmpCapsule ...\n"));
1364 DEBUG((DEBUG_INFO
, "ValidateFmpCapsule ...\n"));
1365 Status
= ValidateFmpCapsule(CapsuleHeader
, NULL
);
1366 DEBUG((DEBUG_INFO
, "ValidateFmpCapsule - %r\n", Status
));
1367 if (EFI_ERROR(Status
)) {
1368 RecordCapsuleStatusVariable(CapsuleHeader
, Status
);
1373 // Press EFI FMP Capsule
1375 DEBUG((DEBUG_INFO
, "ProcessFmpCapsuleImage ...\n"));
1376 Status
= ProcessFmpCapsuleImage(CapsuleHeader
);
1377 DEBUG((DEBUG_INFO
, "ProcessFmpCapsuleImage - %r\n", Status
));
1382 return EFI_UNSUPPORTED
;
1386 Callback function executed when the EndOfDxe event group is signaled.
1388 @param[in] Event Event whose notification function is being invoked.
1389 @param[in] Context The pointer to the notification function's context, which
1390 is implementation-dependent.
1394 DxeCapsuleLibEndOfDxe (
1399 mDxeCapsuleLibEndOfDxe
= TRUE
;
1403 The constructor function.
1405 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1406 @param[in] SystemTable A pointer to the EFI System Table.
1408 @retval EFI_SUCCESS The constructor successfully .
1412 DxeCapsuleLibConstructor (
1413 IN EFI_HANDLE ImageHandle
,
1414 IN EFI_SYSTEM_TABLE
*SystemTable
1419 Status
= gBS
->CreateEventEx (
1422 DxeCapsuleLibEndOfDxe
,
1424 &gEfiEndOfDxeEventGroupGuid
,
1425 &mDxeCapsuleLibEndOfDxeEvent
1427 ASSERT_EFI_ERROR (Status
);
1429 InitCapsuleVariable();
1435 The destructor function closes the End of DXE event.
1437 @param ImageHandle The firmware allocated handle for the EFI image.
1438 @param SystemTable A pointer to the EFI System Table.
1440 @retval EFI_SUCCESS The destructor completed successfully.
1444 DxeCapsuleLibDestructor (
1445 IN EFI_HANDLE ImageHandle
,
1446 IN EFI_SYSTEM_TABLE
*SystemTable
1452 // Close the End of DXE event.
1454 Status
= gBS
->CloseEvent (mDxeCapsuleLibEndOfDxeEvent
);
1455 ASSERT_EFI_ERROR (Status
);