2 Capsule Library instance to process capsule images.
4 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include <Guid/Capsule.h>
12 #include <Guid/FmpCapsule.h>
14 #include <Library/DebugLib.h>
15 #include <Library/BaseMemoryLib.h>
16 #include <Library/DxeServicesTableLib.h>
17 #include <Library/MemoryAllocationLib.h>
18 #include <Library/CapsuleLib.h>
19 #include <Library/GenericBdsLib.h>
20 #include <Library/UefiBootServicesTableLib.h>
21 #include <Library/BaseLib.h>
22 #include <Library/DevicePathLib.h>
24 #include <Protocol/FirmwareManagement.h>
25 #include <Protocol/DevicePath.h>
29 Function indicate the current completion progress of the firmware
30 update. Platform may override with own specific progress function.
32 @param Completion A value between 1 and 100 indicating the current completion progress of the firmware update
34 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
38 Update_Image_Progress (
47 Validate Fmp capsules layout.
49 @param CapsuleHeader Points to a capsule header.
51 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
52 @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.
56 IN EFI_CAPSULE_HEADER
*CapsuleHeader
59 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
61 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
63 UINT64
*ItemOffsetList
;
67 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
68 EndOfCapsule
= (UINT8
*) CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
;
70 if (FmpCapsuleHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
71 return EFI_INVALID_PARAMETER
;
73 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
75 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
77 if (ItemNum
== FmpCapsuleHeader
->EmbeddedDriverCount
) {
81 if (((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[ItemNum
- 1]) < EndOfCapsule
) {
84 return EFI_INVALID_PARAMETER
;
88 if (FmpCapsuleHeader
->PayloadItemCount
!= 0) {
90 // Check if the last payload is within capsule image range
92 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[ItemNum
- 1]);
93 EndOfPayload
= (UINT8
*)(ImageHeader
+ 1) + ImageHeader
->UpdateImageSize
+ ImageHeader
->UpdateVendorCodeSize
;
96 // No driver & payload element in FMP
98 EndOfPayload
= (UINT8
*)(FmpCapsuleHeader
+ 1);
101 if (EndOfPayload
!= EndOfCapsule
) {
102 return EFI_INVALID_PARAMETER
;
106 // All the address in ItemOffsetList must be stored in ascending order
109 for (Index
= 0; Index
< ItemNum
- 1; Index
++) {
110 if (ItemOffsetList
[Index
] >= ItemOffsetList
[Index
+ 1]) {
111 return EFI_INVALID_PARAMETER
;
120 Process Firmware management protocol data capsule.
122 @param CapsuleHeader Points to a capsule header.
124 @retval EFI_SUCESS Process Capsule Image successfully.
125 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
126 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
127 @retval EFI_OUT_OF_RESOURCES Not enough memory.
130 ProcessFmpCapsuleImage (
131 IN EFI_CAPSULE_HEADER
*CapsuleHeader
135 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
136 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
137 EFI_HANDLE ImageHandle
;
138 UINT64
*ItemOffsetList
;
142 EFI_HANDLE
*HandleBuffer
;
143 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
144 UINTN NumberOfHandles
;
145 UINTN DescriptorSize
;
146 UINT8 FmpImageInfoCount
;
147 UINT32 FmpImageInfoDescriptorVer
;
149 UINT32 PackageVersion
;
150 CHAR16
*PackageVersionName
;
152 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
153 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*TempFmpImageInfo
;
157 MEMMAP_DEVICE_PATH MemMapNode
;
158 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
160 Status
= EFI_SUCCESS
;
163 DriverDevicePath
= NULL
;
165 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
167 if (FmpCapsuleHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
168 return EFI_INVALID_PARAMETER
;
170 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
172 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
175 // capsule in which driver count and payload count are both zero is not processed.
182 // 1. ConnectAll to ensure
183 // All the communication protocol required by driver in capsule installed
184 // All FMP protocols are installed
190 // 2. Try to load & start all the drivers within capsule
192 SetDevicePathNodeLength (&MemMapNode
.Header
, sizeof (MemMapNode
));
193 MemMapNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
194 MemMapNode
.Header
.SubType
= HW_MEMMAP_DP
;
195 MemMapNode
.MemoryType
= EfiBootServicesCode
;
196 MemMapNode
.StartingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)CapsuleHeader
;
197 MemMapNode
.EndingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
- 1);
199 DriverDevicePath
= AppendDevicePathNode (NULL
, &MemMapNode
.Header
);
200 if (DriverDevicePath
== NULL
) {
201 return EFI_OUT_OF_RESOURCES
;
204 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
205 if (FmpCapsuleHeader
->PayloadItemCount
== 0 && Index
== (UINTN
)FmpCapsuleHeader
->EmbeddedDriverCount
- 1) {
207 // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
209 DriverLen
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
- (UINTN
)ItemOffsetList
[Index
];
211 DriverLen
= (UINTN
)ItemOffsetList
[Index
+ 1] - (UINTN
)ItemOffsetList
[Index
];
214 Status
= gBS
->LoadImage(
218 (UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
],
222 if (EFI_ERROR(Status
)) {
226 Status
= gBS
->StartImage(
231 if (EFI_ERROR(Status
)) {
232 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
238 // Connnect all again to connect drivers within capsule
240 if (FmpCapsuleHeader
->EmbeddedDriverCount
> 0) {
245 // 3. Route payload to right FMP instance
247 Status
= gBS
->LocateHandleBuffer (
249 &gEfiFirmwareManagementProtocolGuid
,
255 if (!EFI_ERROR(Status
)) {
256 for(Index1
= 0; Index1
< NumberOfHandles
; Index1
++) {
257 Status
= gBS
->HandleProtocol(
258 HandleBuffer
[Index1
],
259 &gEfiFirmwareManagementProtocolGuid
,
262 if (EFI_ERROR(Status
)) {
267 Status
= Fmp
->GetImageInfo (
277 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
281 FmpImageInfoBuf
= NULL
;
282 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
283 if (FmpImageInfoBuf
== NULL
) {
284 Status
= EFI_OUT_OF_RESOURCES
;
288 PackageVersionName
= NULL
;
289 Status
= Fmp
->GetImageInfo (
291 &ImageInfoSize
, // ImageInfoSize
292 FmpImageInfoBuf
, // ImageInfo
293 &FmpImageInfoDescriptorVer
, // DescriptorVersion
294 &FmpImageInfoCount
, // DescriptorCount
295 &DescriptorSize
, // DescriptorSize
296 &PackageVersion
, // PackageVersion
297 &PackageVersionName
// PackageVersionName
301 // If FMP GetInformation interface failed, skip this resource
303 if (EFI_ERROR(Status
)) {
304 FreePool(FmpImageInfoBuf
);
308 if (PackageVersionName
!= NULL
) {
309 FreePool(PackageVersionName
);
312 TempFmpImageInfo
= FmpImageInfoBuf
;
313 for (Index2
= 0; Index2
< FmpImageInfoCount
; Index2
++) {
315 // Check all the payload entry in capsule payload list
317 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
318 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
319 if (CompareGuid(&ImageHeader
->UpdateImageTypeId
, &TempFmpImageInfo
->ImageTypeId
) &&
320 ImageHeader
->UpdateImageIndex
== TempFmpImageInfo
->ImageIndex
) {
322 if (ImageHeader
->UpdateVendorCodeSize
== 0) {
323 Status
= Fmp
->SetImage(
325 TempFmpImageInfo
->ImageIndex
, // ImageIndex
326 (UINT8
*)(ImageHeader
+ 1), // Image
327 ImageHeader
->UpdateImageSize
, // ImageSize
329 Update_Image_Progress
, // Progress
330 &AbortReason
// AbortReason
333 Status
= Fmp
->SetImage(
335 TempFmpImageInfo
->ImageIndex
, // ImageIndex
336 (UINT8
*)(ImageHeader
+ 1), // Image
337 ImageHeader
->UpdateImageSize
, // ImageSize
338 (UINT8
*)((UINT8
*) (ImageHeader
+ 1) + ImageHeader
->UpdateImageSize
), // VendorCode
339 Update_Image_Progress
, // Progress
340 &AbortReason
// AbortReason
343 if (AbortReason
!= NULL
) {
344 DEBUG ((EFI_D_ERROR
, "%s\n", AbortReason
));
345 FreePool(AbortReason
);
350 // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
352 TempFmpImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)TempFmpImageInfo
+ DescriptorSize
);
354 FreePool(FmpImageInfoBuf
);
360 if (HandleBuffer
!= NULL
) {
361 FreePool(HandleBuffer
);
364 if (DriverDevicePath
!= NULL
) {
365 FreePool(DriverDevicePath
);
372 Those capsules supported by the firmwares.
374 @param CapsuleHeader Points to a capsule header.
376 @retval EFI_SUCESS Input capsule is supported by firmware.
377 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
378 @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
382 SupportCapsuleImage (
383 IN EFI_CAPSULE_HEADER
*CapsuleHeader
386 if (CompareGuid (&gEfiCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
390 if (CompareGuid (&gEfiFmpCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
392 // Check layout of FMP capsule
394 return ValidateFmpCapsule(CapsuleHeader
);
397 return EFI_UNSUPPORTED
;
401 The firmware implements to process the capsule image.
403 @param CapsuleHeader Points to a capsule header.
405 @retval EFI_SUCESS Process Capsule Image successfully.
406 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
407 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
408 @retval EFI_OUT_OF_RESOURCES Not enough memory.
412 ProcessCapsuleImage (
413 IN EFI_CAPSULE_HEADER
*CapsuleHeader
417 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
;
418 EFI_FIRMWARE_VOLUME_HEADER
*ProcessedFvImage
;
420 EFI_HANDLE FvProtocolHandle
;
424 ProcessedFvImage
= NULL
;
425 Status
= EFI_SUCCESS
;
427 if (SupportCapsuleImage (CapsuleHeader
) != EFI_SUCCESS
) {
428 return EFI_UNSUPPORTED
;
432 // Check FMP capsule layout
434 if (CompareGuid (&gEfiFmpCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)){
435 Status
= ValidateFmpCapsule(CapsuleHeader
);
436 if (EFI_ERROR(Status
)) {
441 // Press EFI FMP Capsule
443 return ProcessFmpCapsuleImage(CapsuleHeader
);
447 // Skip the capsule header, move to the Firware Volume
449 FvImage
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
450 Length
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
;
452 while (Length
!= 0) {
454 // Point to the next firmware volume header, and then
455 // call the DXE service to process it.
457 if (FvImage
->FvLength
> (UINTN
) Length
) {
459 // Notes: need to stuff this status somewhere so that the
460 // error can be detected at OS runtime
462 Status
= EFI_VOLUME_CORRUPTED
;
466 FvAlignment
= 1 << ((FvImage
->Attributes
& EFI_FVB2_ALIGNMENT
) >> 16);
468 // FvAlignment must be more than 8 bytes required by FvHeader structure.
470 if (FvAlignment
< 8) {
474 // Check FvImage Align is required.
476 if (((UINTN
) FvImage
% FvAlignment
) == 0) {
477 ProcessedFvImage
= FvImage
;
480 // Allocate new aligned buffer to store FvImage.
482 ProcessedFvImage
= (EFI_FIRMWARE_VOLUME_HEADER
*) AllocateAlignedPages ((UINTN
) EFI_SIZE_TO_PAGES ((UINTN
) FvImage
->FvLength
), (UINTN
) FvAlignment
);
483 if (ProcessedFvImage
== NULL
) {
484 Status
= EFI_OUT_OF_RESOURCES
;
487 CopyMem (ProcessedFvImage
, FvImage
, (UINTN
) FvImage
->FvLength
);
490 Status
= gDS
->ProcessFirmwareVolume (
491 (VOID
*) ProcessedFvImage
,
492 (UINTN
) ProcessedFvImage
->FvLength
,
495 if (EFI_ERROR (Status
)) {
499 // Call the dispatcher to dispatch any drivers from the produced firmware volume
503 // On to the next FV in the capsule
505 Length
-= (UINT32
) FvImage
->FvLength
;
506 FvImage
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINT8
*) FvImage
+ FvImage
->FvLength
);
514 This routine is called to process capsules.
516 Caution: This function may receive untrusted input.
518 The capsules reported in EFI_HOB_UEFI_CAPSULE are processed.
519 If there is no EFI_HOB_UEFI_CAPSULE, this routine does nothing.
521 This routine should be called twice in BDS.
522 1) The first call must be before EndOfDxe. The system capsules is processed.
523 If device capsule FMP protocols are exposted at this time and device FMP
524 capsule has zero EmbeddedDriverCount, the device capsules are processed.
525 Each individual capsule result is recorded in capsule record variable.
526 System may reset in this function, if reset is required by capsule and
527 all capsules are processed.
528 If not all capsules are processed, reset will be defered to second call.
530 2) The second call must be after EndOfDxe and after ConnectAll, so that all
531 device capsule FMP protocols are exposed.
532 The system capsules are skipped. If the device capsules are NOT processed
533 in first call, they are processed here.
534 Each individual capsule result is recorded in capsule record variable.
535 System may reset in this function, if reset is required by capsule
536 processed in first call and second call.
538 @retval EFI_SUCCESS There is no error when processing capsules.
539 @retval EFI_OUT_OF_RESOURCES No enough resource to process capsules.
548 return EFI_UNSUPPORTED
;