1cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten/** @file 2566771b0a70a4ec637420c4b96a1415348bf2f12czhang Capsule Library instance to process capsule images. 3cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten 4566771b0a70a4ec637420c4b96a1415348bf2f12czhang Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR> 5cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten 6cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten This program and the accompanying materials 7cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten are licensed and made available under the terms and conditions of the BSD License 8cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten which accompanies this distribution. The full text of the license may be found at 9cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten http://opensource.org/licenses/bsd-license.php 10cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten 11cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten 14cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten**/ 15cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten#include <PiDxe.h> 16566771b0a70a4ec637420c4b96a1415348bf2f12czhang 17cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten#include <Guid/Capsule.h> 18566771b0a70a4ec637420c4b96a1415348bf2f12czhang#include <Guid/FmpCapsule.h> 19566771b0a70a4ec637420c4b96a1415348bf2f12czhang 20cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten#include <Library/DebugLib.h> 21cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten#include <Library/BaseMemoryLib.h> 22cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten#include <Library/DxeServicesTableLib.h> 23cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten#include <Library/MemoryAllocationLib.h> 24cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten#include <Library/CapsuleLib.h> 25566771b0a70a4ec637420c4b96a1415348bf2f12czhang#include <Library/GenericBdsLib.h> 26566771b0a70a4ec637420c4b96a1415348bf2f12czhang#include <Library/UefiBootServicesTableLib.h> 27566771b0a70a4ec637420c4b96a1415348bf2f12czhang#include <Library/BaseLib.h> 28566771b0a70a4ec637420c4b96a1415348bf2f12czhang#include <Library/DevicePathLib.h> 29566771b0a70a4ec637420c4b96a1415348bf2f12czhang 30566771b0a70a4ec637420c4b96a1415348bf2f12czhang#include <Protocol/FirmwareManagement.h> 31566771b0a70a4ec637420c4b96a1415348bf2f12czhang#include <Protocol/DevicePath.h> 32566771b0a70a4ec637420c4b96a1415348bf2f12czhang 33566771b0a70a4ec637420c4b96a1415348bf2f12czhang 34566771b0a70a4ec637420c4b96a1415348bf2f12czhang/** 35566771b0a70a4ec637420c4b96a1415348bf2f12czhang Function indicate the current completion progress of the firmware 36566771b0a70a4ec637420c4b96a1415348bf2f12czhang update. Platform may override with own specific progress function. 37566771b0a70a4ec637420c4b96a1415348bf2f12czhang 38566771b0a70a4ec637420c4b96a1415348bf2f12czhang @param Completion A value between 1 and 100 indicating the current completion progress of the firmware update 39566771b0a70a4ec637420c4b96a1415348bf2f12czhang 40566771b0a70a4ec637420c4b96a1415348bf2f12czhang @retval EFI_SUCESS Input capsule is a correct FMP capsule. 41566771b0a70a4ec637420c4b96a1415348bf2f12czhang**/ 42566771b0a70a4ec637420c4b96a1415348bf2f12czhangEFI_STATUS 43566771b0a70a4ec637420c4b96a1415348bf2f12czhangEFIAPI 44566771b0a70a4ec637420c4b96a1415348bf2f12czhangUpdate_Image_Progress ( 45566771b0a70a4ec637420c4b96a1415348bf2f12czhang IN UINTN Completion 46566771b0a70a4ec637420c4b96a1415348bf2f12czhang) 47566771b0a70a4ec637420c4b96a1415348bf2f12czhang{ 48566771b0a70a4ec637420c4b96a1415348bf2f12czhang return EFI_SUCCESS; 49566771b0a70a4ec637420c4b96a1415348bf2f12czhang} 50566771b0a70a4ec637420c4b96a1415348bf2f12czhang 51566771b0a70a4ec637420c4b96a1415348bf2f12czhang 52566771b0a70a4ec637420c4b96a1415348bf2f12czhang/** 53566771b0a70a4ec637420c4b96a1415348bf2f12czhang Validate Fmp capsules layout. 54566771b0a70a4ec637420c4b96a1415348bf2f12czhang 55566771b0a70a4ec637420c4b96a1415348bf2f12czhang @param CapsuleHeader Points to a capsule header. 56566771b0a70a4ec637420c4b96a1415348bf2f12czhang 57566771b0a70a4ec637420c4b96a1415348bf2f12czhang @retval EFI_SUCESS Input capsule is a correct FMP capsule. 58566771b0a70a4ec637420c4b96a1415348bf2f12czhang @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule. 59566771b0a70a4ec637420c4b96a1415348bf2f12czhang**/ 60566771b0a70a4ec637420c4b96a1415348bf2f12czhangEFI_STATUS 61566771b0a70a4ec637420c4b96a1415348bf2f12czhangValidateFmpCapsule ( 62566771b0a70a4ec637420c4b96a1415348bf2f12czhang IN EFI_CAPSULE_HEADER *CapsuleHeader 63566771b0a70a4ec637420c4b96a1415348bf2f12czhang ) 64566771b0a70a4ec637420c4b96a1415348bf2f12czhang{ 65566771b0a70a4ec637420c4b96a1415348bf2f12czhang EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader; 66566771b0a70a4ec637420c4b96a1415348bf2f12czhang UINT8 *EndOfCapsule; 67566771b0a70a4ec637420c4b96a1415348bf2f12czhang EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader; 68566771b0a70a4ec637420c4b96a1415348bf2f12czhang UINT8 *EndOfPayload; 69566771b0a70a4ec637420c4b96a1415348bf2f12czhang UINT64 *ItemOffsetList; 70566771b0a70a4ec637420c4b96a1415348bf2f12czhang UINT32 ItemNum; 71566771b0a70a4ec637420c4b96a1415348bf2f12czhang UINTN Index; 72566771b0a70a4ec637420c4b96a1415348bf2f12czhang 73566771b0a70a4ec637420c4b96a1415348bf2f12czhang FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize); 74566771b0a70a4ec637420c4b96a1415348bf2f12czhang EndOfCapsule = (UINT8 *) CapsuleHeader + CapsuleHeader->CapsuleImageSize; 75566771b0a70a4ec637420c4b96a1415348bf2f12czhang 76566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) { 77566771b0a70a4ec637420c4b96a1415348bf2f12czhang return EFI_INVALID_PARAMETER; 78566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 79566771b0a70a4ec637420c4b96a1415348bf2f12czhang ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1); 80566771b0a70a4ec637420c4b96a1415348bf2f12czhang 81566771b0a70a4ec637420c4b96a1415348bf2f12czhang ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount; 82566771b0a70a4ec637420c4b96a1415348bf2f12czhang 83566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (ItemNum == FmpCapsuleHeader->EmbeddedDriverCount) { 84566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 85566771b0a70a4ec637420c4b96a1415348bf2f12czhang // No payload element 86566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 87566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (((UINT8 *)FmpCapsuleHeader + ItemOffsetList[ItemNum - 1]) < EndOfCapsule) { 88566771b0a70a4ec637420c4b96a1415348bf2f12czhang return EFI_SUCCESS; 89566771b0a70a4ec637420c4b96a1415348bf2f12czhang } else { 90566771b0a70a4ec637420c4b96a1415348bf2f12czhang return EFI_INVALID_PARAMETER; 91566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 92566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 93566771b0a70a4ec637420c4b96a1415348bf2f12czhang 94566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (FmpCapsuleHeader->PayloadItemCount != 0) { 95566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 96566771b0a70a4ec637420c4b96a1415348bf2f12czhang // Check if the last payload is within capsule image range 97566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 98566771b0a70a4ec637420c4b96a1415348bf2f12czhang ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[ItemNum - 1]); 99566771b0a70a4ec637420c4b96a1415348bf2f12czhang EndOfPayload = (UINT8 *)(ImageHeader + 1) + ImageHeader->UpdateImageSize + ImageHeader->UpdateVendorCodeSize; 100566771b0a70a4ec637420c4b96a1415348bf2f12czhang } else { 101566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 102566771b0a70a4ec637420c4b96a1415348bf2f12czhang // No driver & payload element in FMP 103566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 104566771b0a70a4ec637420c4b96a1415348bf2f12czhang EndOfPayload = (UINT8 *)(FmpCapsuleHeader + 1); 105566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 106566771b0a70a4ec637420c4b96a1415348bf2f12czhang 107566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (EndOfPayload != EndOfCapsule) { 108566771b0a70a4ec637420c4b96a1415348bf2f12czhang return EFI_INVALID_PARAMETER; 109566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 110566771b0a70a4ec637420c4b96a1415348bf2f12czhang 111566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 112566771b0a70a4ec637420c4b96a1415348bf2f12czhang // All the address in ItemOffsetList must be stored in ascending order 113566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 114566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (ItemNum >= 2) { 115566771b0a70a4ec637420c4b96a1415348bf2f12czhang for (Index = 0; Index < ItemNum - 1; Index++) { 116566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (ItemOffsetList[Index] >= ItemOffsetList[Index + 1]) { 117566771b0a70a4ec637420c4b96a1415348bf2f12czhang return EFI_INVALID_PARAMETER; 118566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 119566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 120566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 121566771b0a70a4ec637420c4b96a1415348bf2f12czhang 122566771b0a70a4ec637420c4b96a1415348bf2f12czhang return EFI_SUCCESS; 123566771b0a70a4ec637420c4b96a1415348bf2f12czhang} 124566771b0a70a4ec637420c4b96a1415348bf2f12czhang 125566771b0a70a4ec637420c4b96a1415348bf2f12czhang/** 126566771b0a70a4ec637420c4b96a1415348bf2f12czhang Process Firmware management protocol data capsule. 127566771b0a70a4ec637420c4b96a1415348bf2f12czhang 128566771b0a70a4ec637420c4b96a1415348bf2f12czhang @param CapsuleHeader Points to a capsule header. 129566771b0a70a4ec637420c4b96a1415348bf2f12czhang 130566771b0a70a4ec637420c4b96a1415348bf2f12czhang @retval EFI_SUCESS Process Capsule Image successfully. 131566771b0a70a4ec637420c4b96a1415348bf2f12czhang @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware. 132566771b0a70a4ec637420c4b96a1415348bf2f12czhang @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted. 133566771b0a70a4ec637420c4b96a1415348bf2f12czhang @retval EFI_OUT_OF_RESOURCES Not enough memory. 134566771b0a70a4ec637420c4b96a1415348bf2f12czhang**/ 135566771b0a70a4ec637420c4b96a1415348bf2f12czhangEFI_STATUS 136566771b0a70a4ec637420c4b96a1415348bf2f12czhangProcessFmpCapsuleImage ( 137566771b0a70a4ec637420c4b96a1415348bf2f12czhang IN EFI_CAPSULE_HEADER *CapsuleHeader 138566771b0a70a4ec637420c4b96a1415348bf2f12czhang ) 139566771b0a70a4ec637420c4b96a1415348bf2f12czhang{ 140566771b0a70a4ec637420c4b96a1415348bf2f12czhang EFI_STATUS Status; 141566771b0a70a4ec637420c4b96a1415348bf2f12czhang EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader; 142566771b0a70a4ec637420c4b96a1415348bf2f12czhang UINT8 *EndOfCapsule; 143566771b0a70a4ec637420c4b96a1415348bf2f12czhang EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader; 144566771b0a70a4ec637420c4b96a1415348bf2f12czhang EFI_HANDLE ImageHandle; 145566771b0a70a4ec637420c4b96a1415348bf2f12czhang UINT64 *ItemOffsetList; 146566771b0a70a4ec637420c4b96a1415348bf2f12czhang UINT32 ItemNum; 147566771b0a70a4ec637420c4b96a1415348bf2f12czhang UINTN Index; 148566771b0a70a4ec637420c4b96a1415348bf2f12czhang UINTN ExitDataSize; 149566771b0a70a4ec637420c4b96a1415348bf2f12czhang EFI_HANDLE *HandleBuffer; 150566771b0a70a4ec637420c4b96a1415348bf2f12czhang EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp; 151566771b0a70a4ec637420c4b96a1415348bf2f12czhang UINTN NumberOfHandles; 152566771b0a70a4ec637420c4b96a1415348bf2f12czhang UINTN DescriptorSize; 153566771b0a70a4ec637420c4b96a1415348bf2f12czhang UINT8 FmpImageInfoCount; 154566771b0a70a4ec637420c4b96a1415348bf2f12czhang UINT32 FmpImageInfoDescriptorVer; 155566771b0a70a4ec637420c4b96a1415348bf2f12czhang UINTN ImageInfoSize; 156566771b0a70a4ec637420c4b96a1415348bf2f12czhang UINT32 PackageVersion; 157566771b0a70a4ec637420c4b96a1415348bf2f12czhang CHAR16 *PackageVersionName; 158566771b0a70a4ec637420c4b96a1415348bf2f12czhang CHAR16 *AbortReason; 159566771b0a70a4ec637420c4b96a1415348bf2f12czhang EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf; 160566771b0a70a4ec637420c4b96a1415348bf2f12czhang EFI_FIRMWARE_IMAGE_DESCRIPTOR *TempFmpImageInfo; 161566771b0a70a4ec637420c4b96a1415348bf2f12czhang UINTN DriverLen; 162566771b0a70a4ec637420c4b96a1415348bf2f12czhang UINTN Index1; 163566771b0a70a4ec637420c4b96a1415348bf2f12czhang UINTN Index2; 164566771b0a70a4ec637420c4b96a1415348bf2f12czhang MEMMAP_DEVICE_PATH MemMapNode; 165566771b0a70a4ec637420c4b96a1415348bf2f12czhang EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath; 166566771b0a70a4ec637420c4b96a1415348bf2f12czhang 167566771b0a70a4ec637420c4b96a1415348bf2f12czhang Status = EFI_SUCCESS; 168566771b0a70a4ec637420c4b96a1415348bf2f12czhang HandleBuffer = NULL; 169566771b0a70a4ec637420c4b96a1415348bf2f12czhang ExitDataSize = 0; 170566771b0a70a4ec637420c4b96a1415348bf2f12czhang DriverDevicePath = NULL; 171566771b0a70a4ec637420c4b96a1415348bf2f12czhang 172566771b0a70a4ec637420c4b96a1415348bf2f12czhang FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize); 173566771b0a70a4ec637420c4b96a1415348bf2f12czhang EndOfCapsule = (UINT8 *) CapsuleHeader + CapsuleHeader->CapsuleImageSize; 174566771b0a70a4ec637420c4b96a1415348bf2f12czhang 175566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) { 176566771b0a70a4ec637420c4b96a1415348bf2f12czhang return EFI_INVALID_PARAMETER; 177566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 178566771b0a70a4ec637420c4b96a1415348bf2f12czhang ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1); 179566771b0a70a4ec637420c4b96a1415348bf2f12czhang 180566771b0a70a4ec637420c4b96a1415348bf2f12czhang ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount; 181566771b0a70a4ec637420c4b96a1415348bf2f12czhang 182566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 183566771b0a70a4ec637420c4b96a1415348bf2f12czhang // capsule in which driver count and payload count are both zero is not processed. 184566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 185566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (ItemNum == 0) { 186566771b0a70a4ec637420c4b96a1415348bf2f12czhang return EFI_SUCCESS; 187566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 188566771b0a70a4ec637420c4b96a1415348bf2f12czhang 189566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 190566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 1. ConnectAll to ensure 191566771b0a70a4ec637420c4b96a1415348bf2f12czhang // All the communication protocol required by driver in capsule installed 192566771b0a70a4ec637420c4b96a1415348bf2f12czhang // All FMP protocols are installed 193566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 194566771b0a70a4ec637420c4b96a1415348bf2f12czhang BdsLibConnectAll(); 195566771b0a70a4ec637420c4b96a1415348bf2f12czhang 196566771b0a70a4ec637420c4b96a1415348bf2f12czhang 197566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 198566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 2. Try to load & start all the drivers within capsule 199566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 200566771b0a70a4ec637420c4b96a1415348bf2f12czhang SetDevicePathNodeLength (&MemMapNode.Header, sizeof (MemMapNode)); 201566771b0a70a4ec637420c4b96a1415348bf2f12czhang MemMapNode.Header.Type = HARDWARE_DEVICE_PATH; 202566771b0a70a4ec637420c4b96a1415348bf2f12czhang MemMapNode.Header.SubType = HW_MEMMAP_DP; 203566771b0a70a4ec637420c4b96a1415348bf2f12czhang MemMapNode.MemoryType = EfiBootServicesCode; 2045f7273293dd3fabc7903647532d65d143f3994afczhang MemMapNode.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CapsuleHeader; 2055f7273293dd3fabc7903647532d65d143f3994afczhang MemMapNode.EndingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)((UINT8 *)CapsuleHeader + CapsuleHeader->CapsuleImageSize - 1); 206566771b0a70a4ec637420c4b96a1415348bf2f12czhang 207566771b0a70a4ec637420c4b96a1415348bf2f12czhang DriverDevicePath = AppendDevicePathNode (NULL, &MemMapNode.Header); 208566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (DriverDevicePath == NULL) { 209566771b0a70a4ec637420c4b96a1415348bf2f12czhang return EFI_OUT_OF_RESOURCES; 210566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 211566771b0a70a4ec637420c4b96a1415348bf2f12czhang 212566771b0a70a4ec637420c4b96a1415348bf2f12czhang for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) { 2135f7273293dd3fabc7903647532d65d143f3994afczhang if (FmpCapsuleHeader->PayloadItemCount == 0 && Index == (UINTN)FmpCapsuleHeader->EmbeddedDriverCount - 1) { 214566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 215566771b0a70a4ec637420c4b96a1415348bf2f12czhang // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER 216566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 2175f7273293dd3fabc7903647532d65d143f3994afczhang DriverLen = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize - (UINTN)ItemOffsetList[Index]; 218566771b0a70a4ec637420c4b96a1415348bf2f12czhang } else { 2195f7273293dd3fabc7903647532d65d143f3994afczhang DriverLen = (UINTN)ItemOffsetList[Index + 1] - (UINTN)ItemOffsetList[Index]; 220566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 221566771b0a70a4ec637420c4b96a1415348bf2f12czhang 222566771b0a70a4ec637420c4b96a1415348bf2f12czhang Status = gBS->LoadImage( 223566771b0a70a4ec637420c4b96a1415348bf2f12czhang FALSE, 224566771b0a70a4ec637420c4b96a1415348bf2f12czhang gImageHandle, 225566771b0a70a4ec637420c4b96a1415348bf2f12czhang DriverDevicePath, 226566771b0a70a4ec637420c4b96a1415348bf2f12czhang (UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index], 227566771b0a70a4ec637420c4b96a1415348bf2f12czhang DriverLen, 228566771b0a70a4ec637420c4b96a1415348bf2f12czhang &ImageHandle 229566771b0a70a4ec637420c4b96a1415348bf2f12czhang ); 230566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (EFI_ERROR(Status)) { 231566771b0a70a4ec637420c4b96a1415348bf2f12czhang goto EXIT; 232566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 233566771b0a70a4ec637420c4b96a1415348bf2f12czhang 234566771b0a70a4ec637420c4b96a1415348bf2f12czhang Status = gBS->StartImage( 235566771b0a70a4ec637420c4b96a1415348bf2f12czhang ImageHandle, 236566771b0a70a4ec637420c4b96a1415348bf2f12czhang &ExitDataSize, 237566771b0a70a4ec637420c4b96a1415348bf2f12czhang NULL 238566771b0a70a4ec637420c4b96a1415348bf2f12czhang ); 239566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (EFI_ERROR(Status)) { 240566771b0a70a4ec637420c4b96a1415348bf2f12czhang DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status)); 241566771b0a70a4ec637420c4b96a1415348bf2f12czhang goto EXIT; 242566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 243566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 244566771b0a70a4ec637420c4b96a1415348bf2f12czhang 245566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 246566771b0a70a4ec637420c4b96a1415348bf2f12czhang // Connnect all again to connect drivers within capsule 247566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 248566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (FmpCapsuleHeader->EmbeddedDriverCount > 0) { 249566771b0a70a4ec637420c4b96a1415348bf2f12czhang BdsLibConnectAll(); 250566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 251566771b0a70a4ec637420c4b96a1415348bf2f12czhang 252566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 253566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 3. Route payload to right FMP instance 254566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 255566771b0a70a4ec637420c4b96a1415348bf2f12czhang Status = gBS->LocateHandleBuffer ( 256566771b0a70a4ec637420c4b96a1415348bf2f12czhang ByProtocol, 257566771b0a70a4ec637420c4b96a1415348bf2f12czhang &gEfiFirmwareManagementProtocolGuid, 258566771b0a70a4ec637420c4b96a1415348bf2f12czhang NULL, 259566771b0a70a4ec637420c4b96a1415348bf2f12czhang &NumberOfHandles, 260566771b0a70a4ec637420c4b96a1415348bf2f12czhang &HandleBuffer 261566771b0a70a4ec637420c4b96a1415348bf2f12czhang ); 262566771b0a70a4ec637420c4b96a1415348bf2f12czhang 263566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (!EFI_ERROR(Status)) { 264566771b0a70a4ec637420c4b96a1415348bf2f12czhang for(Index1 = 0; Index1 < NumberOfHandles; Index1++) { 265566771b0a70a4ec637420c4b96a1415348bf2f12czhang Status = gBS->HandleProtocol( 266566771b0a70a4ec637420c4b96a1415348bf2f12czhang HandleBuffer[Index1], 267566771b0a70a4ec637420c4b96a1415348bf2f12czhang &gEfiFirmwareManagementProtocolGuid, 2685f7273293dd3fabc7903647532d65d143f3994afczhang (VOID **)&Fmp 269566771b0a70a4ec637420c4b96a1415348bf2f12czhang ); 270566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (EFI_ERROR(Status)) { 271566771b0a70a4ec637420c4b96a1415348bf2f12czhang continue; 272566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 273566771b0a70a4ec637420c4b96a1415348bf2f12czhang 274566771b0a70a4ec637420c4b96a1415348bf2f12czhang ImageInfoSize = 0; 275566771b0a70a4ec637420c4b96a1415348bf2f12czhang Status = Fmp->GetImageInfo ( 276566771b0a70a4ec637420c4b96a1415348bf2f12czhang Fmp, 277566771b0a70a4ec637420c4b96a1415348bf2f12czhang &ImageInfoSize, 278566771b0a70a4ec637420c4b96a1415348bf2f12czhang NULL, 279566771b0a70a4ec637420c4b96a1415348bf2f12czhang NULL, 280566771b0a70a4ec637420c4b96a1415348bf2f12czhang NULL, 281566771b0a70a4ec637420c4b96a1415348bf2f12czhang NULL, 282566771b0a70a4ec637420c4b96a1415348bf2f12czhang NULL, 283566771b0a70a4ec637420c4b96a1415348bf2f12czhang NULL 284566771b0a70a4ec637420c4b96a1415348bf2f12czhang ); 285566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (Status != EFI_BUFFER_TOO_SMALL) { 286566771b0a70a4ec637420c4b96a1415348bf2f12czhang continue; 287566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 288566771b0a70a4ec637420c4b96a1415348bf2f12czhang 289566771b0a70a4ec637420c4b96a1415348bf2f12czhang FmpImageInfoBuf = NULL; 290566771b0a70a4ec637420c4b96a1415348bf2f12czhang FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize); 291566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (FmpImageInfoBuf == NULL) { 292566771b0a70a4ec637420c4b96a1415348bf2f12czhang Status = EFI_OUT_OF_RESOURCES; 293566771b0a70a4ec637420c4b96a1415348bf2f12czhang goto EXIT; 294566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 295566771b0a70a4ec637420c4b96a1415348bf2f12czhang 296566771b0a70a4ec637420c4b96a1415348bf2f12czhang PackageVersionName = NULL; 297566771b0a70a4ec637420c4b96a1415348bf2f12czhang Status = Fmp->GetImageInfo ( 298566771b0a70a4ec637420c4b96a1415348bf2f12czhang Fmp, 299566771b0a70a4ec637420c4b96a1415348bf2f12czhang &ImageInfoSize, // ImageInfoSize 300566771b0a70a4ec637420c4b96a1415348bf2f12czhang FmpImageInfoBuf, // ImageInfo 301566771b0a70a4ec637420c4b96a1415348bf2f12czhang &FmpImageInfoDescriptorVer, // DescriptorVersion 302566771b0a70a4ec637420c4b96a1415348bf2f12czhang &FmpImageInfoCount, // DescriptorCount 303566771b0a70a4ec637420c4b96a1415348bf2f12czhang &DescriptorSize, // DescriptorSize 304566771b0a70a4ec637420c4b96a1415348bf2f12czhang &PackageVersion, // PackageVersion 305566771b0a70a4ec637420c4b96a1415348bf2f12czhang &PackageVersionName // PackageVersionName 306566771b0a70a4ec637420c4b96a1415348bf2f12czhang ); 307566771b0a70a4ec637420c4b96a1415348bf2f12czhang 308566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 309566771b0a70a4ec637420c4b96a1415348bf2f12czhang // If FMP GetInformation interface failed, skip this resource 310566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 311566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (EFI_ERROR(Status)) { 312566771b0a70a4ec637420c4b96a1415348bf2f12czhang FreePool(FmpImageInfoBuf); 313566771b0a70a4ec637420c4b96a1415348bf2f12czhang continue; 314566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 315566771b0a70a4ec637420c4b96a1415348bf2f12czhang 316566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (PackageVersionName != NULL) { 317566771b0a70a4ec637420c4b96a1415348bf2f12czhang FreePool(PackageVersionName); 318566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 319566771b0a70a4ec637420c4b96a1415348bf2f12czhang 320566771b0a70a4ec637420c4b96a1415348bf2f12czhang TempFmpImageInfo = FmpImageInfoBuf; 321566771b0a70a4ec637420c4b96a1415348bf2f12czhang for (Index2 = 0; Index2 < FmpImageInfoCount; Index2++) { 322566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 323566771b0a70a4ec637420c4b96a1415348bf2f12czhang // Check all the payload entry in capsule payload list 324566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 325566771b0a70a4ec637420c4b96a1415348bf2f12czhang for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) { 326566771b0a70a4ec637420c4b96a1415348bf2f12czhang ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]); 327566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (CompareGuid(&ImageHeader->UpdateImageTypeId, &TempFmpImageInfo->ImageTypeId) && 328566771b0a70a4ec637420c4b96a1415348bf2f12czhang ImageHeader->UpdateImageIndex == TempFmpImageInfo->ImageIndex) { 329566771b0a70a4ec637420c4b96a1415348bf2f12czhang AbortReason = NULL; 330566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (ImageHeader->UpdateVendorCodeSize == 0) { 331566771b0a70a4ec637420c4b96a1415348bf2f12czhang Status = Fmp->SetImage( 332566771b0a70a4ec637420c4b96a1415348bf2f12czhang Fmp, 333566771b0a70a4ec637420c4b96a1415348bf2f12czhang TempFmpImageInfo->ImageIndex, // ImageIndex 334566771b0a70a4ec637420c4b96a1415348bf2f12czhang (UINT8 *)(ImageHeader + 1), // Image 335566771b0a70a4ec637420c4b96a1415348bf2f12czhang ImageHeader->UpdateImageSize, // ImageSize 336566771b0a70a4ec637420c4b96a1415348bf2f12czhang NULL, // VendorCode 337566771b0a70a4ec637420c4b96a1415348bf2f12czhang Update_Image_Progress, // Progress 338566771b0a70a4ec637420c4b96a1415348bf2f12czhang &AbortReason // AbortReason 339566771b0a70a4ec637420c4b96a1415348bf2f12czhang ); 340566771b0a70a4ec637420c4b96a1415348bf2f12czhang } else { 341566771b0a70a4ec637420c4b96a1415348bf2f12czhang Status = Fmp->SetImage( 342566771b0a70a4ec637420c4b96a1415348bf2f12czhang Fmp, 343566771b0a70a4ec637420c4b96a1415348bf2f12czhang TempFmpImageInfo->ImageIndex, // ImageIndex 344566771b0a70a4ec637420c4b96a1415348bf2f12czhang (UINT8 *)(ImageHeader + 1), // Image 345566771b0a70a4ec637420c4b96a1415348bf2f12czhang ImageHeader->UpdateImageSize, // ImageSize 346566771b0a70a4ec637420c4b96a1415348bf2f12czhang (UINT8 *)((UINT8 *) (ImageHeader + 1) + ImageHeader->UpdateImageSize), // VendorCode 347566771b0a70a4ec637420c4b96a1415348bf2f12czhang Update_Image_Progress, // Progress 348566771b0a70a4ec637420c4b96a1415348bf2f12czhang &AbortReason // AbortReason 349566771b0a70a4ec637420c4b96a1415348bf2f12czhang ); 350566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 351566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (AbortReason != NULL) { 352566771b0a70a4ec637420c4b96a1415348bf2f12czhang DEBUG ((EFI_D_ERROR, "%s\n", AbortReason)); 353566771b0a70a4ec637420c4b96a1415348bf2f12czhang FreePool(AbortReason); 354566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 355566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 356566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 357566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 358566771b0a70a4ec637420c4b96a1415348bf2f12czhang // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version 359566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 360566771b0a70a4ec637420c4b96a1415348bf2f12czhang TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)TempFmpImageInfo + DescriptorSize); 361566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 362566771b0a70a4ec637420c4b96a1415348bf2f12czhang FreePool(FmpImageInfoBuf); 363566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 364566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 365566771b0a70a4ec637420c4b96a1415348bf2f12czhang 366566771b0a70a4ec637420c4b96a1415348bf2f12czhangEXIT: 367566771b0a70a4ec637420c4b96a1415348bf2f12czhang 368566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (HandleBuffer != NULL) { 369566771b0a70a4ec637420c4b96a1415348bf2f12czhang FreePool(HandleBuffer); 370566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 371566771b0a70a4ec637420c4b96a1415348bf2f12czhang 372566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (DriverDevicePath != NULL) { 373566771b0a70a4ec637420c4b96a1415348bf2f12czhang FreePool(DriverDevicePath); 374566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 375566771b0a70a4ec637420c4b96a1415348bf2f12czhang 376566771b0a70a4ec637420c4b96a1415348bf2f12czhang return Status; 377566771b0a70a4ec637420c4b96a1415348bf2f12czhang} 378cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten 379cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten/** 380cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten Those capsules supported by the firmwares. 381cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten 382cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten @param CapsuleHeader Points to a capsule header. 383cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten 384cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten @retval EFI_SUCESS Input capsule is supported by firmware. 385cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware. 386566771b0a70a4ec637420c4b96a1415348bf2f12czhang @retval EFI_INVALID_PARAMETER Input capsule layout is not correct 387cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten**/ 388cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljustenEFI_STATUS 389cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljustenEFIAPI 390cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljustenSupportCapsuleImage ( 391cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten IN EFI_CAPSULE_HEADER *CapsuleHeader 392cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten ) 393cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten{ 394cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten if (CompareGuid (&gEfiCapsuleGuid, &CapsuleHeader->CapsuleGuid)) { 395cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten return EFI_SUCCESS; 396cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten } 397cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten 398566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (CompareGuid (&gEfiFmpCapsuleGuid, &CapsuleHeader->CapsuleGuid)) { 399566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 400566771b0a70a4ec637420c4b96a1415348bf2f12czhang // Check layout of FMP capsule 401566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 402566771b0a70a4ec637420c4b96a1415348bf2f12czhang return ValidateFmpCapsule(CapsuleHeader); 403566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 404566771b0a70a4ec637420c4b96a1415348bf2f12czhang 405cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten return EFI_UNSUPPORTED; 406cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten} 407cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten 408cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten/** 409cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten The firmware implements to process the capsule image. 410cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten 411cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten @param CapsuleHeader Points to a capsule header. 412cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten 413cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten @retval EFI_SUCESS Process Capsule Image successfully. 414cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware. 415cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted. 416cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten @retval EFI_OUT_OF_RESOURCES Not enough memory. 417cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten**/ 418cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljustenEFI_STATUS 419cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljustenEFIAPI 420cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljustenProcessCapsuleImage ( 421cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten IN EFI_CAPSULE_HEADER *CapsuleHeader 422cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten ) 423cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten{ 424cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten UINT32 Length; 425cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten EFI_FIRMWARE_VOLUME_HEADER *FvImage; 426cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten EFI_FIRMWARE_VOLUME_HEADER *ProcessedFvImage; 427cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten EFI_STATUS Status; 428cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten EFI_HANDLE FvProtocolHandle; 429cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten UINT32 FvAlignment; 430cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten 431cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten FvImage = NULL; 432cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten ProcessedFvImage = NULL; 433cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten Status = EFI_SUCCESS; 434cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten 435cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten if (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS) { 436cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten return EFI_UNSUPPORTED; 437cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten } 438cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten 439cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // 440566771b0a70a4ec637420c4b96a1415348bf2f12czhang // Check FMP capsule layout 441566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 442566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (CompareGuid (&gEfiFmpCapsuleGuid, &CapsuleHeader->CapsuleGuid)){ 443566771b0a70a4ec637420c4b96a1415348bf2f12czhang Status = ValidateFmpCapsule(CapsuleHeader); 444566771b0a70a4ec637420c4b96a1415348bf2f12czhang if (EFI_ERROR(Status)) { 445566771b0a70a4ec637420c4b96a1415348bf2f12czhang return Status; 446566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 447566771b0a70a4ec637420c4b96a1415348bf2f12czhang 448566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 449566771b0a70a4ec637420c4b96a1415348bf2f12czhang // Press EFI FMP Capsule 450566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 451566771b0a70a4ec637420c4b96a1415348bf2f12czhang return ProcessFmpCapsuleImage(CapsuleHeader); 452566771b0a70a4ec637420c4b96a1415348bf2f12czhang } 453566771b0a70a4ec637420c4b96a1415348bf2f12czhang 454566771b0a70a4ec637420c4b96a1415348bf2f12czhang // 455cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // Skip the capsule header, move to the Firware Volume 456cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // 457cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten FvImage = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize); 458cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten Length = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize; 459cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten 460cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten while (Length != 0) { 461cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // 462cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // Point to the next firmware volume header, and then 463cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // call the DXE service to process it. 464cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // 465cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten if (FvImage->FvLength > (UINTN) Length) { 466cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // 467cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // Notes: need to stuff this status somewhere so that the 468cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // error can be detected at OS runtime 469cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // 470cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten Status = EFI_VOLUME_CORRUPTED; 471cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten break; 472cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten } 473cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten 474cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten FvAlignment = 1 << ((FvImage->Attributes & EFI_FVB2_ALIGNMENT) >> 16); 475cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // 476cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // FvAlignment must be more than 8 bytes required by FvHeader structure. 477cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // 478cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten if (FvAlignment < 8) { 479cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten FvAlignment = 8; 480cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten } 481cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // 482cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // Check FvImage Align is required. 483cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // 484cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten if (((UINTN) FvImage % FvAlignment) == 0) { 485cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten ProcessedFvImage = FvImage; 486cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten } else { 487cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // 488cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // Allocate new aligned buffer to store FvImage. 489cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // 490a661e27f7aa3f8e197af3f4a61d5ac350c82aaa7lgao ProcessedFvImage = (EFI_FIRMWARE_VOLUME_HEADER *) AllocateAlignedPages ((UINTN) EFI_SIZE_TO_PAGES ((UINTN) FvImage->FvLength), (UINTN) FvAlignment); 491cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten if (ProcessedFvImage == NULL) { 492cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten Status = EFI_OUT_OF_RESOURCES; 493cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten break; 494cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten } 495cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten CopyMem (ProcessedFvImage, FvImage, (UINTN) FvImage->FvLength); 496cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten } 497cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten 498cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten Status = gDS->ProcessFirmwareVolume ( 499cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten (VOID *) ProcessedFvImage, 500cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten (UINTN) ProcessedFvImage->FvLength, 501cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten &FvProtocolHandle 502cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten ); 503cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten if (EFI_ERROR (Status)) { 504cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten break; 505cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten } 506cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // 507cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // Call the dispatcher to dispatch any drivers from the produced firmware volume 508cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // 509cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten gDS->Dispatch (); 510cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // 511cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // On to the next FV in the capsule 512cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten // 513cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten Length -= (UINT32) FvImage->FvLength; 514cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten FvImage = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) FvImage + FvImage->FvLength); 515cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten } 516cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten 517cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten return Status; 518cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten} 519cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten 520cf7958f7f9394c4a545b707b8409fc5b2ffaf84ajljusten 521