2 Capsule Library instance to process capsule images.
4 Copyright (c) 2007 - 2013, 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
;
143 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*ImageHeader
;
144 EFI_HANDLE ImageHandle
;
145 UINT64
*ItemOffsetList
;
149 EFI_HANDLE
*HandleBuffer
;
150 EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*Fmp
;
151 UINTN NumberOfHandles
;
152 UINTN DescriptorSize
;
153 UINT8 FmpImageInfoCount
;
154 UINT32 FmpImageInfoDescriptorVer
;
156 UINT32 PackageVersion
;
157 CHAR16
*PackageVersionName
;
159 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*FmpImageInfoBuf
;
160 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*TempFmpImageInfo
;
164 MEMMAP_DEVICE_PATH MemMapNode
;
165 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
167 Status
= EFI_SUCCESS
;
170 DriverDevicePath
= NULL
;
172 FmpCapsuleHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
173 EndOfCapsule
= (UINT8
*) CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
;
175 if (FmpCapsuleHeader
->Version
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
) {
176 return EFI_INVALID_PARAMETER
;
178 ItemOffsetList
= (UINT64
*)(FmpCapsuleHeader
+ 1);
180 ItemNum
= FmpCapsuleHeader
->EmbeddedDriverCount
+ FmpCapsuleHeader
->PayloadItemCount
;
183 // capsule in which driver count and payload count are both zero is not processed.
190 // 1. ConnectAll to ensure
191 // All the communication protocol required by driver in capsule installed
192 // All FMP protocols are installed
198 // 2. Try to load & start all the drivers within capsule
200 SetDevicePathNodeLength (&MemMapNode
.Header
, sizeof (MemMapNode
));
201 MemMapNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
202 MemMapNode
.Header
.SubType
= HW_MEMMAP_DP
;
203 MemMapNode
.MemoryType
= EfiBootServicesCode
;
204 MemMapNode
.StartingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)CapsuleHeader
;
205 MemMapNode
.EndingAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)((UINT8
*)CapsuleHeader
+ CapsuleHeader
->CapsuleImageSize
- 1);
207 DriverDevicePath
= AppendDevicePathNode (NULL
, &MemMapNode
.Header
);
208 if (DriverDevicePath
== NULL
) {
209 return EFI_OUT_OF_RESOURCES
;
212 for (Index
= 0; Index
< FmpCapsuleHeader
->EmbeddedDriverCount
; Index
++) {
213 if (FmpCapsuleHeader
->PayloadItemCount
== 0 && Index
== (UINTN
)FmpCapsuleHeader
->EmbeddedDriverCount
- 1) {
215 // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
217 DriverLen
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
- (UINTN
)ItemOffsetList
[Index
];
219 DriverLen
= (UINTN
)ItemOffsetList
[Index
+ 1] - (UINTN
)ItemOffsetList
[Index
];
222 Status
= gBS
->LoadImage(
226 (UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
],
230 if (EFI_ERROR(Status
)) {
234 Status
= gBS
->StartImage(
239 if (EFI_ERROR(Status
)) {
240 DEBUG ((DEBUG_ERROR
, "Driver Return Status = %r\n", Status
));
246 // Connnect all again to connect drivers within capsule
248 if (FmpCapsuleHeader
->EmbeddedDriverCount
> 0) {
253 // 3. Route payload to right FMP instance
255 Status
= gBS
->LocateHandleBuffer (
257 &gEfiFirmwareManagementProtocolGuid
,
263 if (!EFI_ERROR(Status
)) {
264 for(Index1
= 0; Index1
< NumberOfHandles
; Index1
++) {
265 Status
= gBS
->HandleProtocol(
266 HandleBuffer
[Index1
],
267 &gEfiFirmwareManagementProtocolGuid
,
270 if (EFI_ERROR(Status
)) {
275 Status
= Fmp
->GetImageInfo (
285 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
289 FmpImageInfoBuf
= NULL
;
290 FmpImageInfoBuf
= AllocateZeroPool (ImageInfoSize
);
291 if (FmpImageInfoBuf
== NULL
) {
292 Status
= EFI_OUT_OF_RESOURCES
;
296 PackageVersionName
= NULL
;
297 Status
= Fmp
->GetImageInfo (
299 &ImageInfoSize
, // ImageInfoSize
300 FmpImageInfoBuf
, // ImageInfo
301 &FmpImageInfoDescriptorVer
, // DescriptorVersion
302 &FmpImageInfoCount
, // DescriptorCount
303 &DescriptorSize
, // DescriptorSize
304 &PackageVersion
, // PackageVersion
305 &PackageVersionName
// PackageVersionName
309 // If FMP GetInformation interface failed, skip this resource
311 if (EFI_ERROR(Status
)) {
312 FreePool(FmpImageInfoBuf
);
316 if (PackageVersionName
!= NULL
) {
317 FreePool(PackageVersionName
);
320 TempFmpImageInfo
= FmpImageInfoBuf
;
321 for (Index2
= 0; Index2
< FmpImageInfoCount
; Index2
++) {
323 // Check all the payload entry in capsule payload list
325 for (Index
= FmpCapsuleHeader
->EmbeddedDriverCount
; Index
< ItemNum
; Index
++) {
326 ImageHeader
= (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
*)((UINT8
*)FmpCapsuleHeader
+ ItemOffsetList
[Index
]);
327 if (CompareGuid(&ImageHeader
->UpdateImageTypeId
, &TempFmpImageInfo
->ImageTypeId
) &&
328 ImageHeader
->UpdateImageIndex
== TempFmpImageInfo
->ImageIndex
) {
330 if (ImageHeader
->UpdateVendorCodeSize
== 0) {
331 Status
= Fmp
->SetImage(
333 TempFmpImageInfo
->ImageIndex
, // ImageIndex
334 (UINT8
*)(ImageHeader
+ 1), // Image
335 ImageHeader
->UpdateImageSize
, // ImageSize
337 Update_Image_Progress
, // Progress
338 &AbortReason
// AbortReason
341 Status
= Fmp
->SetImage(
343 TempFmpImageInfo
->ImageIndex
, // ImageIndex
344 (UINT8
*)(ImageHeader
+ 1), // Image
345 ImageHeader
->UpdateImageSize
, // ImageSize
346 (UINT8
*)((UINT8
*) (ImageHeader
+ 1) + ImageHeader
->UpdateImageSize
), // VendorCode
347 Update_Image_Progress
, // Progress
348 &AbortReason
// AbortReason
351 if (AbortReason
!= NULL
) {
352 DEBUG ((EFI_D_ERROR
, "%s\n", AbortReason
));
353 FreePool(AbortReason
);
358 // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
360 TempFmpImageInfo
= (EFI_FIRMWARE_IMAGE_DESCRIPTOR
*)((UINT8
*)TempFmpImageInfo
+ DescriptorSize
);
362 FreePool(FmpImageInfoBuf
);
368 if (HandleBuffer
!= NULL
) {
369 FreePool(HandleBuffer
);
372 if (DriverDevicePath
!= NULL
) {
373 FreePool(DriverDevicePath
);
380 Those capsules supported by the firmwares.
382 @param CapsuleHeader Points to a capsule header.
384 @retval EFI_SUCESS Input capsule is supported by firmware.
385 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
386 @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
390 SupportCapsuleImage (
391 IN EFI_CAPSULE_HEADER
*CapsuleHeader
394 if (CompareGuid (&gEfiCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
398 if (CompareGuid (&gEfiFmpCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)) {
400 // Check layout of FMP capsule
402 return ValidateFmpCapsule(CapsuleHeader
);
405 return EFI_UNSUPPORTED
;
409 The firmware implements to process the capsule image.
411 @param CapsuleHeader Points to a capsule header.
413 @retval EFI_SUCESS Process Capsule Image successfully.
414 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
415 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
416 @retval EFI_OUT_OF_RESOURCES Not enough memory.
420 ProcessCapsuleImage (
421 IN EFI_CAPSULE_HEADER
*CapsuleHeader
425 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
;
426 EFI_FIRMWARE_VOLUME_HEADER
*ProcessedFvImage
;
428 EFI_HANDLE FvProtocolHandle
;
432 ProcessedFvImage
= NULL
;
433 Status
= EFI_SUCCESS
;
435 if (SupportCapsuleImage (CapsuleHeader
) != EFI_SUCCESS
) {
436 return EFI_UNSUPPORTED
;
440 // Check FMP capsule layout
442 if (CompareGuid (&gEfiFmpCapsuleGuid
, &CapsuleHeader
->CapsuleGuid
)){
443 Status
= ValidateFmpCapsule(CapsuleHeader
);
444 if (EFI_ERROR(Status
)) {
449 // Press EFI FMP Capsule
451 return ProcessFmpCapsuleImage(CapsuleHeader
);
455 // Skip the capsule header, move to the Firware Volume
457 FvImage
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINT8
*) CapsuleHeader
+ CapsuleHeader
->HeaderSize
);
458 Length
= CapsuleHeader
->CapsuleImageSize
- CapsuleHeader
->HeaderSize
;
460 while (Length
!= 0) {
462 // Point to the next firmware volume header, and then
463 // call the DXE service to process it.
465 if (FvImage
->FvLength
> (UINTN
) Length
) {
467 // Notes: need to stuff this status somewhere so that the
468 // error can be detected at OS runtime
470 Status
= EFI_VOLUME_CORRUPTED
;
474 FvAlignment
= 1 << ((FvImage
->Attributes
& EFI_FVB2_ALIGNMENT
) >> 16);
476 // FvAlignment must be more than 8 bytes required by FvHeader structure.
478 if (FvAlignment
< 8) {
482 // Check FvImage Align is required.
484 if (((UINTN
) FvImage
% FvAlignment
) == 0) {
485 ProcessedFvImage
= FvImage
;
488 // Allocate new aligned buffer to store FvImage.
490 ProcessedFvImage
= (EFI_FIRMWARE_VOLUME_HEADER
*) AllocateAlignedPages ((UINTN
) EFI_SIZE_TO_PAGES ((UINTN
) FvImage
->FvLength
), (UINTN
) FvAlignment
);
491 if (ProcessedFvImage
== NULL
) {
492 Status
= EFI_OUT_OF_RESOURCES
;
495 CopyMem (ProcessedFvImage
, FvImage
, (UINTN
) FvImage
->FvLength
);
498 Status
= gDS
->ProcessFirmwareVolume (
499 (VOID
*) ProcessedFvImage
,
500 (UINTN
) ProcessedFvImage
->FvLength
,
503 if (EFI_ERROR (Status
)) {
507 // Call the dispatcher to dispatch any drivers from the produced firmware volume
511 // On to the next FV in the capsule
513 Length
-= (UINT32
) FvImage
->FvLength
;
514 FvImage
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINT8
*) FvImage
+ FvImage
->FvLength
);