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