2 Capsule Library instance to process capsule images.
4 Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Guid/Capsule.h>
18 #include <Guid/FmpCapsule.h>
20 #include <Library/DebugLib.h>
21 #include <Library/BaseMemoryLib.h>
22 #include <Library/DxeServicesTableLib.h>
23 #include <Library/MemoryAllocationLib.h>
24 #include <Library/CapsuleLib.h>
25 #include <Library/GenericBdsLib.h>
26 #include <Library/UefiBootServicesTableLib.h>
27 #include <Library/BaseLib.h>
28 #include <Library/DevicePathLib.h>
30 #include <Protocol/FirmwareManagement.h>
31 #include <Protocol/DevicePath.h>
35 Function indicate the current completion progress of the firmware
36 update. Platform may override with own specific progress function.
38 @param Completion A value between 1 and 100 indicating the current completion progress of the firmware update
40 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
44 Update_Image_Progress (
53 Validate Fmp capsules layout.
55 @param CapsuleHeader Points to a capsule header.
57 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
58 @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.
62 IN EFI_CAPSULE_HEADER
*CapsuleHeader
65 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
67 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
69 UINT64
*ItemOffsetList
;
73 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
74 EndOfCapsule
= (UINT8
*) CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
;
76 if (FmpCapsuleHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
77 return EFI_INVALID_PARAMETER
;
79 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
81 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
83 if (ItemNum
== FmpCapsuleHeader
->EmbeddedDriverCount
) {
87 if (((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[ItemNum
- 1]) < EndOfCapsule
) {
90 return EFI_INVALID_PARAMETER
;
94 if (FmpCapsuleHeader
->PayloadItemCount
!= 0) {
96 // Check if the last payload is within capsule image range
98 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[ItemNum
- 1]);
99 EndOfPayload
= (UINT8
*)(ImageHeader
+ 1) + ImageHeader
->UpdateImageSize
+ ImageHeader
->UpdateVendorCodeSize
;
102 // No driver & payload element in FMP
104 EndOfPayload
= (UINT8
*)(FmpCapsuleHeader
+ 1);
107 if (EndOfPayload
!= EndOfCapsule
) {
108 return EFI_INVALID_PARAMETER
;
112 // All the address in ItemOffsetList must be stored in ascending order
115 for (Index
= 0; Index
< ItemNum
- 1; Index
++) {
116 if (ItemOffsetList
[Index
] >= ItemOffsetList
[Index
+ 1]) {
117 return EFI_INVALID_PARAMETER
;
126 Process Firmware management protocol data capsule.
128 @param CapsuleHeader Points to a capsule header.
130 @retval EFI_SUCESS Process Capsule Image successfully.
131 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
132 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
133 @retval EFI_OUT_OF_RESOURCES Not enough memory.
136 ProcessFmpCapsuleImage (
137 IN EFI_CAPSULE_HEADER
*CapsuleHeader
141 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*FmpCapsuleHeader
;
142 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
143 EFI_HANDLE ImageHandle
;
144 UINT64
*ItemOffsetList
;
148 EFI_HANDLE
*HandleBuffer
;
149 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
150 UINTN NumberOfHandles
;
151 UINTN DescriptorSize
;
152 UINT8 FmpImageInfoCount
;
153 UINT32 FmpImageInfoDescriptorVer
;
155 UINT32 PackageVersion
;
156 CHAR16
*PackageVersionName
;
158 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
159 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*TempFmpImageInfo
;
163 MEMMAP_DEVICE_PATH MemMapNode
;
164 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
166 Status
= EFI_SUCCESS
;
169 DriverDevicePath
= NULL
;
171 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
173 if (FmpCapsuleHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
174 return EFI_INVALID_PARAMETER
;
176 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
178 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
181 // capsule in which driver count and payload count are both zero is not processed.
188 // 1. ConnectAll to ensure
189 // All the communication protocol required by driver in capsule installed
190 // All FMP protocols are installed
196 // 2. Try to load & start all the drivers within capsule
198 SetDevicePathNodeLength (&MemMapNode
.Header
, sizeof (MemMapNode
));
199 MemMapNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
200 MemMapNode
.Header
.SubType
= HW_MEMMAP_DP
;
201 MemMapNode
.MemoryType
= EfiBootServicesCode
;
202 MemMapNode
.StartingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)CapsuleHeader
;
203 MemMapNode
.EndingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
- 1);
205 DriverDevicePath
= AppendDevicePathNode (NULL
, &MemMapNode
.Header
);
206 if (DriverDevicePath
== NULL
) {
207 return EFI_OUT_OF_RESOURCES
;
210 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
211 if (FmpCapsuleHeader
->PayloadItemCount
== 0 && Index
== (UINTN
)FmpCapsuleHeader
->EmbeddedDriverCount
- 1) {
213 // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
215 DriverLen
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
- (UINTN
)ItemOffsetList
[Index
];
217 DriverLen
= (UINTN
)ItemOffsetList
[Index
+ 1] - (UINTN
)ItemOffsetList
[Index
];
220 Status
= gBS
->LoadImage(
224 (UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
],
228 if (EFI_ERROR(Status
)) {
232 Status
= gBS
->StartImage(
237 if (EFI_ERROR(Status
)) {
238 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
244 // Connnect all again to connect drivers within capsule
246 if (FmpCapsuleHeader
->EmbeddedDriverCount
> 0) {
251 // 3. Route payload to right FMP instance
253 Status
= gBS
->LocateHandleBuffer (
255 &gEfiFirmwareManagementProtocolGuid
,
261 if (!EFI_ERROR(Status
)) {
262 for(Index1
= 0; Index1
< NumberOfHandles
; Index1
++) {
263 Status
= gBS
->HandleProtocol(
264 HandleBuffer
[Index1
],
265 &gEfiFirmwareManagementProtocolGuid
,
268 if (EFI_ERROR(Status
)) {
273 Status
= Fmp
->GetImageInfo (
283 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
287 FmpImageInfoBuf
= NULL
;
288 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
289 if (FmpImageInfoBuf
== NULL
) {
290 Status
= EFI_OUT_OF_RESOURCES
;
294 PackageVersionName
= NULL
;
295 Status
= Fmp
->GetImageInfo (
297 &ImageInfoSize
, // ImageInfoSize
298 FmpImageInfoBuf
, // ImageInfo
299 &FmpImageInfoDescriptorVer
, // DescriptorVersion
300 &FmpImageInfoCount
, // DescriptorCount
301 &DescriptorSize
, // DescriptorSize
302 &PackageVersion
, // PackageVersion
303 &PackageVersionName
// PackageVersionName
307 // If FMP GetInformation interface failed, skip this resource
309 if (EFI_ERROR(Status
)) {
310 FreePool(FmpImageInfoBuf
);
314 if (PackageVersionName
!= NULL
) {
315 FreePool(PackageVersionName
);
318 TempFmpImageInfo
= FmpImageInfoBuf
;
319 for (Index2
= 0; Index2
< FmpImageInfoCount
; Index2
++) {
321 // Check all the payload entry in capsule payload list
323 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
324 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
325 if (CompareGuid(&ImageHeader
->UpdateImageTypeId
, &TempFmpImageInfo
->ImageTypeId
) &&
326 ImageHeader
->UpdateImageIndex
== TempFmpImageInfo
->ImageIndex
) {
328 if (ImageHeader
->UpdateVendorCodeSize
== 0) {
329 Status
= Fmp
->SetImage(
331 TempFmpImageInfo
->ImageIndex
, // ImageIndex
332 (UINT8
*)(ImageHeader
+ 1), // Image
333 ImageHeader
->UpdateImageSize
, // ImageSize
335 Update_Image_Progress
, // Progress
336 &AbortReason
// AbortReason
339 Status
= Fmp
->SetImage(
341 TempFmpImageInfo
->ImageIndex
, // ImageIndex
342 (UINT8
*)(ImageHeader
+ 1), // Image
343 ImageHeader
->UpdateImageSize
, // ImageSize
344 (UINT8
*)((UINT8
*) (ImageHeader
+ 1) + ImageHeader
->UpdateImageSize
), // VendorCode
345 Update_Image_Progress
, // Progress
346 &AbortReason
// AbortReason
349 if (AbortReason
!= NULL
) {
350 DEBUG ((EFI_D_ERROR
, "%s\n", AbortReason
));
351 FreePool(AbortReason
);
356 // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
358 TempFmpImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)TempFmpImageInfo
+ DescriptorSize
);
360 FreePool(FmpImageInfoBuf
);
366 if (HandleBuffer
!= NULL
) {
367 FreePool(HandleBuffer
);
370 if (DriverDevicePath
!= NULL
) {
371 FreePool(DriverDevicePath
);
378 Those capsules supported by the firmwares.
380 @param CapsuleHeader Points to a capsule header.
382 @retval EFI_SUCESS Input capsule is supported by firmware.
383 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
384 @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
388 SupportCapsuleImage (
389 IN EFI_CAPSULE_HEADER
*CapsuleHeader
392 if (CompareGuid (&gEfiCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
396 if (CompareGuid (&gEfiFmpCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
398 // Check layout of FMP capsule
400 return ValidateFmpCapsule(CapsuleHeader
);
403 return EFI_UNSUPPORTED
;
407 The firmware implements to process the capsule image.
409 @param CapsuleHeader Points to a capsule header.
411 @retval EFI_SUCESS Process Capsule Image successfully.
412 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
413 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
414 @retval EFI_OUT_OF_RESOURCES Not enough memory.
418 ProcessCapsuleImage (
419 IN EFI_CAPSULE_HEADER
*CapsuleHeader
423 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
;
424 EFI_FIRMWARE_VOLUME_HEADER
*ProcessedFvImage
;
426 EFI_HANDLE FvProtocolHandle
;
430 ProcessedFvImage
= NULL
;
431 Status
= EFI_SUCCESS
;
433 if (SupportCapsuleImage (CapsuleHeader
) != EFI_SUCCESS
) {
434 return EFI_UNSUPPORTED
;
438 // Check FMP capsule layout
440 if (CompareGuid (&gEfiFmpCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)){
441 Status
= ValidateFmpCapsule(CapsuleHeader
);
442 if (EFI_ERROR(Status
)) {
447 // Press EFI FMP Capsule
449 return ProcessFmpCapsuleImage(CapsuleHeader
);
453 // Skip the capsule header, move to the Firware Volume
455 FvImage
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
456 Length
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
;
458 while (Length
!= 0) {
460 // Point to the next firmware volume header, and then
461 // call the DXE service to process it.
463 if (FvImage
->FvLength
> (UINTN
) Length
) {
465 // Notes: need to stuff this status somewhere so that the
466 // error can be detected at OS runtime
468 Status
= EFI_VOLUME_CORRUPTED
;
472 FvAlignment
= 1 << ((FvImage
->Attributes
& EFI_FVB2_ALIGNMENT
) >> 16);
474 // FvAlignment must be more than 8 bytes required by FvHeader structure.
476 if (FvAlignment
< 8) {
480 // Check FvImage Align is required.
482 if (((UINTN
) FvImage
% FvAlignment
) == 0) {
483 ProcessedFvImage
= FvImage
;
486 // Allocate new aligned buffer to store FvImage.
488 ProcessedFvImage
= (EFI_FIRMWARE_VOLUME_HEADER
*) AllocateAlignedPages ((UINTN
) EFI_SIZE_TO_PAGES ((UINTN
) FvImage
->FvLength
), (UINTN
) FvAlignment
);
489 if (ProcessedFvImage
== NULL
) {
490 Status
= EFI_OUT_OF_RESOURCES
;
493 CopyMem (ProcessedFvImage
, FvImage
, (UINTN
) FvImage
->FvLength
);
496 Status
= gDS
->ProcessFirmwareVolume (
497 (VOID
*) ProcessedFvImage
,
498 (UINTN
) ProcessedFvImage
->FvLength
,
501 if (EFI_ERROR (Status
)) {
505 // Call the dispatcher to dispatch any drivers from the produced firmware volume
509 // On to the next FV in the capsule
511 Length
-= (UINT32
) FvImage
->FvLength
;
512 FvImage
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINT8
*) FvImage
+ FvImage
->FvLength
);
520 This routine is called to process capsules.
522 Caution: This function may receive untrusted input.
524 The capsules reported in EFI_HOB_UEFI_CAPSULE are processed.
525 If there is no EFI_HOB_UEFI_CAPSULE, this routine does nothing.
527 This routine should be called twice in BDS.
528 1) The first call must be before EndOfDxe. The system capsules is processed.
529 If device capsule FMP protocols are exposted at this time and device FMP
530 capsule has zero EmbeddedDriverCount, the device capsules are processed.
531 Each individual capsule result is recorded in capsule record variable.
532 System may reset in this function, if reset is required by capsule and
533 all capsules are processed.
534 If not all capsules are processed, reset will be defered to second call.
536 2) The second call must be after EndOfDxe and after ConnectAll, so that all
537 device capsule FMP protocols are exposed.
538 The system capsules are skipped. If the device capsules are NOT processed
539 in first call, they are processed here.
540 Each individual capsule result is recorded in capsule record variable.
541 System may reset in this function, if reset is required by capsule
542 processed in first call and second call.
544 @retval EFI_SUCCESS There is no error when processing capsules.
545 @retval EFI_OUT_OF_RESOURCES No enough resource to process capsules.
554 return EFI_UNSUPPORTED
;