1ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin/** @file
2ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  The logic to process capsule.
3ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
4dc204d5a0fd64d1ccbc90ebea827e7ad73b71f4djyao  Caution: This module requires additional review when modified.
5dc204d5a0fd64d1ccbc90ebea827e7ad73b71f4djyao  This driver will have external input - capsule image.
6dc204d5a0fd64d1ccbc90ebea827e7ad73b71f4djyao  This external input must be validated carefully to avoid security issue like
7dc204d5a0fd64d1ccbc90ebea827e7ad73b71f4djyao  buffer overflow, integer overflow.
8dc204d5a0fd64d1ccbc90ebea827e7ad73b71f4djyao
9dc204d5a0fd64d1ccbc90ebea827e7ad73b71f4djyao  CapsuleDataCoalesce() will do basic validation before coalesce capsule data
10dc204d5a0fd64d1ccbc90ebea827e7ad73b71f4djyao  into memory.
11dc204d5a0fd64d1ccbc90ebea827e7ad73b71f4djyao
1235f910f08b58e978bc9251872635075d6f422e48Randy Pawell(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
13ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyaoCopyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
14ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinThis program and the accompanying materials
15ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinare licensed and made available under the terms and conditions of the BSD License
16ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinwhich accompanies this distribution.  The full text of the license may be found at
17ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinhttp://opensource.org/licenses/bsd-license.php
18ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
19ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
20ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
22ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin**/
23ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
24ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin#include <Uefi.h>
25ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin#include <PiPei.h>
26ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
27ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin#include <Guid/CapsuleVendor.h>
28ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
29ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin#include <Library/BaseMemoryLib.h>
30ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin#include <Library/DebugLib.h>
31ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin#include <Library/PrintLib.h>
32ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin#include <Library/BaseLib.h>
33ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
34ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao#include "CommonHeader.h"
35ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
36ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao#define MIN_COALESCE_ADDR                     (1024 * 1024)
37ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
38ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin/**
39ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  Given a pointer to the capsule block list, info on the available system
40ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  memory, and the size of a buffer, find a free block of memory where a
41ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  buffer of the given size can be copied to safely.
42ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
43ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param BlockList   Pointer to head of capsule block descriptors
44ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param MemBase     Pointer to the base of memory in which we want to find free space
45ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param MemSize     The size of the block of memory pointed to by MemBase
46ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param DataSize    How big a free block we want to find
47ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
48ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @return A pointer to a memory block of at least DataSize that lies somewhere
49ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin          between MemBase and (MemBase + MemSize). The memory pointed to does not
50ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin          contain any of the capsule block descriptors or capsule blocks pointed to
51ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin          by the BlockList.
52ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
53ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin**/
54ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinUINT8 *
55ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinFindFreeMem (
56ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  EFI_CAPSULE_BLOCK_DESCRIPTOR     *BlockList,
57ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINT8                            *MemBase,
58ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINTN                             MemSize,
59ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINTN                             DataSize
60ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  );
61ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
62ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin/**
63ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  Check the integrity of the capsule descriptors.
64ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
65ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param BlockList    Pointer to the capsule descriptors
66ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
67ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval NULL           BlockList is not valid.
68ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval LastBlockDesc  Last one Block in BlockList
69ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
70ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin**/
71ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinEFI_CAPSULE_BLOCK_DESCRIPTOR *
72ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinValidateCapsuleIntegrity (
73ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN EFI_CAPSULE_BLOCK_DESCRIPTOR    *BlockList
74ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  );
75ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
76ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin/**
77ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  The capsule block descriptors may be fragmented and spread all over memory.
78ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  To simplify the coalescing of capsule blocks, first coalesce all the
79ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  capsule block descriptors low in memory.
80ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
81ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  The descriptors passed in can be fragmented throughout memory. Here
82ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  they are relocated into memory to turn them into a contiguous (null
83ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  terminated) array.
84ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
85ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  @param PeiServices    pointer to PEI services table
86ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  @param BlockList      pointer to the capsule block descriptors
87ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  @param NumDescriptors number of capsule data block descriptors, whose Length is non-zero.
88ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  @param MemBase        base of system memory in which we can work
89ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  @param MemSize        size of the system memory pointed to by MemBase
90ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
91ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval NULL    could not relocate the descriptors
92ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval Pointer to the base of the successfully-relocated block descriptors.
93ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
94ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin**/
95ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinEFI_CAPSULE_BLOCK_DESCRIPTOR *
96ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinRelocateBlockDescriptors (
97ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN EFI_PEI_SERVICES                  **PeiServices,
98ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN EFI_CAPSULE_BLOCK_DESCRIPTOR      *BlockList,
99ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  IN UINTN                              NumDescriptors,
100ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN UINT8                             *MemBase,
101ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN UINTN                             MemSize
102ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  );
103ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
104ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin/**
105ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  Check every capsule header.
106ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
107ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param CapsuleHeader   The pointer to EFI_CAPSULE_HEADER
108ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
109ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval FALSE  Capsule is OK
110ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval TRUE   Capsule is corrupted
111ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
112ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin**/
113ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinBOOLEAN
114ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinIsCapsuleCorrupted (
115ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN EFI_CAPSULE_HEADER       *CapsuleHeader
116ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  );
117ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
118ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin/**
119ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  Determine if two buffers overlap in memory.
120ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
121ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param Buff1   pointer to first buffer
122ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param Size1   size of Buff1
123ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param Buff2   pointer to second buffer
124ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param Size2   size of Buff2
125ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
126ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval TRUE    Buffers overlap in memory.
127ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval FALSE   Buffer doesn't overlap.
128ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
129ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin**/
130ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinBOOLEAN
131ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinIsOverlapped (
132ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINT8     *Buff1,
133ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINTN     Size1,
134ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINT8     *Buff2,
135ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINTN     Size2
136ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  );
137ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
138ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin/**
139ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  Given a pointer to a capsule block descriptor, traverse the list to figure
140ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  out how many legitimate descriptors there are, and how big the capsule it
141ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  refers to is.
142ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
143ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param Desc            Pointer to the capsule block descriptors
144ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  @param NumDescriptors  Optional pointer to where to return the number of capsule data descriptors, whose Length is non-zero.
145ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  @param CapsuleSize     Optional pointer to where to return the capsule image size
146ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  @param CapsuleNumber   Optional pointer to where to return the number of capsule
147ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
148ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval EFI_NOT_FOUND   No descriptors containing data in the list
149ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval EFI_SUCCESS     Return data is valid
150ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
151ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin**/
152ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinEFI_STATUS
153ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinGetCapsuleInfo (
154ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN EFI_CAPSULE_BLOCK_DESCRIPTOR   *Desc,
155ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN OUT UINTN                      *NumDescriptors OPTIONAL,
156ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  IN OUT UINTN                      *CapsuleSize OPTIONAL,
157ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  IN OUT UINTN                      *CapsuleNumber OPTIONAL
158ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  );
159ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
160ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin/**
161ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  Given a pointer to the capsule block list, info on the available system
162ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  memory, and the size of a buffer, find a free block of memory where a
163ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  buffer of the given size can be copied to safely.
164ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
165ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param BlockList   Pointer to head of capsule block descriptors
166ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param MemBase     Pointer to the base of memory in which we want to find free space
167ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param MemSize     The size of the block of memory pointed to by MemBase
168ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param DataSize    How big a free block we want to find
169ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
170ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @return A pointer to a memory block of at least DataSize that lies somewhere
171ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin          between MemBase and (MemBase + MemSize). The memory pointed to does not
172ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin          contain any of the capsule block descriptors or capsule blocks pointed to
173ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin          by the BlockList.
174ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
175ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin**/
176ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinUINT8 *
177ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinFindFreeMem (
178ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  EFI_CAPSULE_BLOCK_DESCRIPTOR      *BlockList,
179ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINT8                             *MemBase,
180ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINTN                             MemSize,
181ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINTN                             DataSize
182ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  )
183ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin{
184ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINTN                           Size;
185ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  EFI_CAPSULE_BLOCK_DESCRIPTOR    *CurrDesc;
186ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  EFI_CAPSULE_BLOCK_DESCRIPTOR    *TempDesc;
187ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINT8                           *MemEnd;
188ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  BOOLEAN                         Failed;
189ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
190ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
191ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // Need at least enough to copy the data to at the end of the buffer, so
192ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // say the end is less the data size for easy comparisons here.
193ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
194ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  MemEnd    = MemBase + MemSize - DataSize;
195ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  CurrDesc  = BlockList;
196ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
197ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // Go through all the descriptor blocks and see if any obstruct the range
198ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
199ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  while (CurrDesc != NULL) {
200ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
201ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    // Get the size of this block list and see if it's in the way
202ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
203ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    Failed    = FALSE;
204ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    TempDesc  = CurrDesc;
205ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    Size      = sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
206ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    while (TempDesc->Length != 0) {
207ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      Size += sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
208ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      TempDesc++;
209ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    }
210ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
211ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    if (IsOverlapped (MemBase, DataSize, (UINT8 *) CurrDesc, Size)) {
212ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
213ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      // Set our new base to the end of this block list and start all over
214ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
215ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      MemBase   = (UINT8 *) CurrDesc + Size;
216ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      CurrDesc  = BlockList;
217ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      if (MemBase > MemEnd) {
218ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        return NULL;
219ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      }
220ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
221ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      Failed = TRUE;
222ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    }
223ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
224ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    // Now go through all the blocks and make sure none are in the way
225ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
226ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    while ((CurrDesc->Length != 0) && (!Failed)) {
227ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      if (IsOverlapped (MemBase, DataSize, (UINT8 *) (UINTN) CurrDesc->Union.DataBlock, (UINTN) CurrDesc->Length)) {
228ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        //
229ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        // Set our new base to the end of this block and start all over
230ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        //
231ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        Failed    = TRUE;
232ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        MemBase   = (UINT8 *) ((UINTN) CurrDesc->Union.DataBlock) + CurrDesc->Length;
233ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        CurrDesc  = BlockList;
234ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        if (MemBase > MemEnd) {
235ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin          return NULL;
236ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        }
237ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      }
238ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      CurrDesc++;
239ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    }
240ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
241ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    // Normal continuation -- jump to next block descriptor list
242ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
243ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    if (!Failed) {
244ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      CurrDesc = (EFI_CAPSULE_BLOCK_DESCRIPTOR  *) (UINTN) CurrDesc->Union.ContinuationPointer;
245ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    }
246ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
247ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  return MemBase;
248ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin}
249ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
250ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin/**
251ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  Check the integrity of the capsule descriptors.
252ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
253ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param BlockList    Pointer to the capsule descriptors
254ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
255ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval NULL           BlockList is not valid.
256ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval LastBlockDesc  Last one Block in BlockList
257ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
258ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin**/
259ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinEFI_CAPSULE_BLOCK_DESCRIPTOR *
260ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinValidateCapsuleIntegrity (
261ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN EFI_CAPSULE_BLOCK_DESCRIPTOR    *BlockList
262ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  )
263ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin{
264ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  EFI_CAPSULE_HEADER             *CapsuleHeader;
265ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINT64                         CapsuleSize;
266ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  UINTN                          CapsuleCount;
267ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  EFI_CAPSULE_BLOCK_DESCRIPTOR   *Ptr;
268ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
269ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  DEBUG ((EFI_D_INFO, "ValidateCapsuleIntegrity\n"));
270ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao
271ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
272ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // Go through the list to look for inconsistencies. Check for:
273ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //   * misaligned block descriptors.
274ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //   * The first capsule header guid
275ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //   * The first capsule header flag
276ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  //   * The first capsule header HeaderSize
277ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  //   * Length > MAX_ADDRESS
278ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  //   * ContinuationPointer > MAX_ADDRESS
279ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  //   * DataBlock + Length > MAX_ADDRESS
280ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  //
281ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  CapsuleSize  = 0;
282ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  CapsuleCount = 0;
283ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  Ptr = BlockList;
284ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao
285ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  DEBUG ((EFI_D_INFO, "Ptr - 0x%x\n", Ptr));
286ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  DEBUG ((EFI_D_INFO, "Ptr->Length - 0x%x\n", Ptr->Length));
287ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  DEBUG ((EFI_D_INFO, "Ptr->Union - 0x%x\n", Ptr->Union.ContinuationPointer));
288ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  while ((Ptr->Length != 0) || (Ptr->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
289ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
290ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    // Make sure the descriptor is aligned at UINT64 in memory
291ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
292ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    if ((UINTN) Ptr & (sizeof(UINT64) - 1)) {
293ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      DEBUG ((EFI_D_ERROR, "ERROR: BlockList address failed alignment check\n"));
294ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      return NULL;
295ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    }
296ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    //
297ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    // Sanity Check
298ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    //
299ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    if (Ptr->Length > MAX_ADDRESS) {
300ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      DEBUG ((EFI_D_ERROR, "ERROR: Ptr->Length(0x%lx) > MAX_ADDRESS\n", Ptr->Length));
301ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      return NULL;
302ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    }
303ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
304ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    if (Ptr->Length == 0) {
305ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
306ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      // Sanity Check
307ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      //
308ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      if (Ptr->Union.ContinuationPointer > MAX_ADDRESS) {
309ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        DEBUG ((EFI_D_ERROR, "ERROR: Ptr->Union.ContinuationPointer(0x%lx) > MAX_ADDRESS\n", Ptr->Union.ContinuationPointer));
310ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        return NULL;
311ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      }
312ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      //
313ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      // Descriptor points to another list of block descriptors somewhere
314ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      // else.
315ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
316ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      Ptr = (EFI_CAPSULE_BLOCK_DESCRIPTOR  *) (UINTN) Ptr->Union.ContinuationPointer;
317ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      DEBUG ((EFI_D_INFO, "Ptr(C) - 0x%x\n", Ptr));
318ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      DEBUG ((EFI_D_INFO, "Ptr->Length - 0x%x\n", Ptr->Length));
319ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      DEBUG ((EFI_D_INFO, "Ptr->Union - 0x%x\n", Ptr->Union.ContinuationPointer));
320ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    } else {
321ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
322ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      // Sanity Check
323ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      //
324ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      if (Ptr->Union.DataBlock > (MAX_ADDRESS - (UINTN)Ptr->Length)) {
325ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        DEBUG ((EFI_D_ERROR, "ERROR: Ptr->Union.DataBlock(0x%lx) > (MAX_ADDRESS - (UINTN)Ptr->Length(0x%lx))\n", Ptr->Union.DataBlock, Ptr->Length));
326ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        return NULL;
327ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      }
328ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao
329ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      //
330ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //To enhance the reliability of check-up, the first capsule's header is checked here.
331ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //More reliabilities check-up will do later.
332ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
333ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      if (CapsuleSize == 0) {
334ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        //
335ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        //Move to the first capsule to check its header.
336ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        //
337ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        CapsuleHeader = (EFI_CAPSULE_HEADER*)((UINTN)Ptr->Union.DataBlock);
338ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        //
339ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        // Sanity check
340ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        //
341ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        if (Ptr->Length < sizeof(EFI_CAPSULE_HEADER)) {
342ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao          DEBUG ((EFI_D_ERROR, "ERROR: Ptr->Length(0x%lx) < sizeof(EFI_CAPSULE_HEADER)\n", Ptr->Length));
343ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao          return NULL;
344ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        }
345ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        //
346ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        // Make sure HeaderSize field is valid
347ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        //
348ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        if (CapsuleHeader->HeaderSize > CapsuleHeader->CapsuleImageSize) {
349ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao          DEBUG ((EFI_D_ERROR, "ERROR: CapsuleHeader->HeaderSize(0x%x) > CapsuleHeader->CapsuleImageSize(0x%x)\n", CapsuleHeader->HeaderSize, CapsuleHeader->CapsuleImageSize));
350ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao          return NULL;
351ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        }
352ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        if (IsCapsuleCorrupted (CapsuleHeader)) {
353ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin          return NULL;
354ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        }
355ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        CapsuleCount ++;
356ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        CapsuleSize = CapsuleHeader->CapsuleImageSize;
357240bc4ee8fdd73054b6dd58547ef416b9d9e2a7flzeng      }
358240bc4ee8fdd73054b6dd58547ef416b9d9e2a7flzeng
359240bc4ee8fdd73054b6dd58547ef416b9d9e2a7flzeng      if (CapsuleSize >= Ptr->Length) {
360240bc4ee8fdd73054b6dd58547ef416b9d9e2a7flzeng        CapsuleSize = CapsuleSize - Ptr->Length;
361ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      } else {
362ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        DEBUG ((EFI_D_ERROR, "ERROR: CapsuleSize(0x%lx) < Ptr->Length(0x%lx)\n", CapsuleSize, Ptr->Length));
363ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        //
364ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        // Sanity check
365ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        //
366ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        return NULL;
367ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      }
368240bc4ee8fdd73054b6dd58547ef416b9d9e2a7flzeng
369ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
370ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      // Move to next BLOCK descriptor
371ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
372ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      Ptr++;
373ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      DEBUG ((EFI_D_INFO, "Ptr(B) - 0x%x\n", Ptr));
374ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      DEBUG ((EFI_D_INFO, "Ptr->Length - 0x%x\n", Ptr->Length));
375ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      DEBUG ((EFI_D_INFO, "Ptr->Union - 0x%x\n", Ptr->Union.ContinuationPointer));
376ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    }
377ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
378ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
379ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  if (CapsuleCount == 0) {
380ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
381ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    // No any capsule is found in BlockList
382ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
383ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    DEBUG ((EFI_D_ERROR, "ERROR: CapsuleCount(0x%x) == 0\n", CapsuleCount));
384ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    return NULL;
385ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  }
386ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao
387ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  if (CapsuleSize != 0) {
388ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    //
389ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    // Capsule data is incomplete.
390ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    //
391ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    DEBUG ((EFI_D_ERROR, "ERROR: CapsuleSize(0x%lx) != 0\n", CapsuleSize));
392ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    return NULL;
393ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
394ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
395ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  return Ptr;
396ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin}
397ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
398ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin/**
399ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  The capsule block descriptors may be fragmented and spread all over memory.
400ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  To simplify the coalescing of capsule blocks, first coalesce all the
401ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  capsule block descriptors low in memory.
402ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
403ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  The descriptors passed in can be fragmented throughout memory. Here
404ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  they are relocated into memory to turn them into a contiguous (null
405ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  terminated) array.
406ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
407ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  @param PeiServices    pointer to PEI services table
408ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  @param BlockList      pointer to the capsule block descriptors
409ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  @param NumDescriptors number of capsule data block descriptors, whose Length is non-zero.
410ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  @param MemBase        base of system memory in which we can work
411ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  @param MemSize        size of the system memory pointed to by MemBase
412ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
413ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval NULL    could not relocate the descriptors
414ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval Pointer to the base of the successfully-relocated block descriptors.
415ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
416ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin**/
417ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinEFI_CAPSULE_BLOCK_DESCRIPTOR  *
418ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinRelocateBlockDescriptors (
419ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN EFI_PEI_SERVICES                   **PeiServices,
420ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN EFI_CAPSULE_BLOCK_DESCRIPTOR       *BlockList,
421ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  IN UINTN                              NumDescriptors,
422ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN UINT8                              *MemBase,
423ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN UINTN                              MemSize
424ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  )
425ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin{
426ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  EFI_CAPSULE_BLOCK_DESCRIPTOR   *NewBlockList;
427ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  EFI_CAPSULE_BLOCK_DESCRIPTOR   *CurrBlockDescHead;
428ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockDesc;
429ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  EFI_CAPSULE_BLOCK_DESCRIPTOR   *PrevBlockDescTail;
430ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINTN                          BufferSize;
431ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINT8                          *RelocBuffer;
432ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINTN                          BlockListSize;
433ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao
434ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
435ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // Get the info on the blocks and descriptors. Since we're going to move
436ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // the descriptors low in memory, adjust the base/size values accordingly here.
437ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  // NumDescriptors is the number of legit data descriptors, so add one for
438ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  // a terminator. (Already done by caller, no check is needed.)
439ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
440ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
441ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  BufferSize    = NumDescriptors * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
442ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  NewBlockList  = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) MemBase;
443ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  if (MemSize < BufferSize) {
444ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    return NULL;
445ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
446ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
447ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  MemSize -= BufferSize;
448ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  MemBase += BufferSize;
449ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
450ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // Go through all the blocks and make sure none are in the way
451ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
452ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  TempBlockDesc = BlockList;
453ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  while (TempBlockDesc->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL) {
454ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    if (TempBlockDesc->Length == 0) {
455ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
456ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      // Next block of descriptors
457ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
458ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      TempBlockDesc = (EFI_CAPSULE_BLOCK_DESCRIPTOR  *) (UINTN) TempBlockDesc->Union.ContinuationPointer;
459ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    } else {
460ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
461ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      // If the capsule data pointed to by this descriptor is in the way,
462ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      // move it.
463ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
464ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      if (IsOverlapped (
465ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin            (UINT8 *) NewBlockList,
466ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin            BufferSize,
467ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin            (UINT8 *) (UINTN) TempBlockDesc->Union.DataBlock,
468ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin            (UINTN) TempBlockDesc->Length
469ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin            )) {
470ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        //
471ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        // Relocate the block
472ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        //
473ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        RelocBuffer = FindFreeMem (BlockList, MemBase, MemSize, (UINTN) TempBlockDesc->Length);
474ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        if (RelocBuffer == NULL) {
475ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin          return NULL;
476ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        }
477ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
478ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        CopyMem ((VOID *) RelocBuffer, (VOID *) (UINTN) TempBlockDesc->Union.DataBlock, (UINTN) TempBlockDesc->Length);
479ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        DEBUG ((EFI_D_INFO, "Capsule relocate descriptors from/to/size  0x%lX 0x%lX 0x%lX\n", TempBlockDesc->Union.DataBlock, (UINT64)(UINTN)RelocBuffer, TempBlockDesc->Length));
4805d4f8cf3c9aace8ad3a37670629a88bb7b21a3f7lzeng        TempBlockDesc->Union.DataBlock = (EFI_PHYSICAL_ADDRESS) (UINTN) RelocBuffer;
481ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      }
4825d4f8cf3c9aace8ad3a37670629a88bb7b21a3f7lzeng      TempBlockDesc++;
483ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    }
484ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
485ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
486ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // Now go through all the block descriptors to make sure that they're not
487ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // in the memory region we want to copy them to.
488ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
489ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  CurrBlockDescHead = BlockList;
490ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  PrevBlockDescTail = NULL;
491ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  while ((CurrBlockDescHead != NULL) && (CurrBlockDescHead->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
492ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
493ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    // Get the size of this list then see if it overlaps our low region
494ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
495ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    TempBlockDesc = CurrBlockDescHead;
496ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    BlockListSize = sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
497ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    while (TempBlockDesc->Length != 0) {
498ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      BlockListSize += sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
499ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      TempBlockDesc++;
500ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    }
501ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
502ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    if (IsOverlapped (
503ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin          (UINT8 *) NewBlockList,
504ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin          BufferSize,
505ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin          (UINT8 *) CurrBlockDescHead,
506ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin          BlockListSize
507ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin          )) {
508ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
509ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      // Overlaps, so move it out of the way
510ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
511ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      RelocBuffer = FindFreeMem (BlockList, MemBase, MemSize, BlockListSize);
512ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      if (RelocBuffer == NULL) {
513ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        return NULL;
514ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      }
515ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      CopyMem ((VOID *) RelocBuffer, (VOID *) CurrBlockDescHead, BlockListSize);
516ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      DEBUG ((EFI_D_INFO, "Capsule reloc descriptor block #2\n"));
517ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
518ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      // Point the previous block's next point to this copied version. If
519ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      // the tail pointer is null, then this is the first descriptor block.
520ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
521ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      if (PrevBlockDescTail == NULL) {
522ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        BlockList = (EFI_CAPSULE_BLOCK_DESCRIPTOR  *) RelocBuffer;
523ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      } else {
524ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        PrevBlockDescTail->Union.DataBlock = (EFI_PHYSICAL_ADDRESS) (UINTN) RelocBuffer;
525ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      }
526ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    }
527ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
528ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    // Save our new tail and jump to the next block list
529ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
530ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    PrevBlockDescTail = TempBlockDesc;
531ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    CurrBlockDescHead = (EFI_CAPSULE_BLOCK_DESCRIPTOR  *) (UINTN) TempBlockDesc->Union.ContinuationPointer;
532ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
533ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
534ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // Cleared out low memory. Now copy the descriptors down there.
535ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
536ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  TempBlockDesc     = BlockList;
537ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  CurrBlockDescHead = NewBlockList;
538ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  while ((TempBlockDesc != NULL) && (TempBlockDesc->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
539ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    if (TempBlockDesc->Length != 0) {
540ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      CurrBlockDescHead->Union.DataBlock = TempBlockDesc->Union.DataBlock;
541ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      CurrBlockDescHead->Length = TempBlockDesc->Length;
542ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      CurrBlockDescHead++;
543ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      TempBlockDesc++;
544ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    } else {
545ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      TempBlockDesc = (EFI_CAPSULE_BLOCK_DESCRIPTOR  *) (UINTN) TempBlockDesc->Union.ContinuationPointer;
546ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    }
547ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
548ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
549ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // Null terminate
550ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
551ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  CurrBlockDescHead->Union.ContinuationPointer   = (EFI_PHYSICAL_ADDRESS) (UINTN) NULL;
552ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  CurrBlockDescHead->Length = 0;
553ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  return NewBlockList;
554ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin}
555ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
556ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin/**
557ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  Determine if two buffers overlap in memory.
558ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
559ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param Buff1   pointer to first buffer
560ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param Size1   size of Buff1
561ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param Buff2   pointer to second buffer
562ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param Size2   size of Buff2
563ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
564ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval TRUE    Buffers overlap in memory.
565ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval FALSE   Buffer doesn't overlap.
566ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
567ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin**/
568ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinBOOLEAN
569ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinIsOverlapped (
570ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINT8     *Buff1,
571ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINTN     Size1,
572ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINT8     *Buff2,
573ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINTN     Size2
574ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  )
575ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin{
576ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
577ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // If buff1's end is less than the start of buff2, then it's ok.
578ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // Also, if buff1's start is beyond buff2's end, then it's ok.
579ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
580ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  if (((Buff1 + Size1) <= Buff2) || (Buff1 >= (Buff2 + Size2))) {
581ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    return FALSE;
582ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
583ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
584ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  return TRUE;
585ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin}
586ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
587ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin/**
588ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  Given a pointer to a capsule block descriptor, traverse the list to figure
589ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  out how many legitimate descriptors there are, and how big the capsule it
590ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  refers to is.
591ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
592ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param Desc            Pointer to the capsule block descriptors
593ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  @param NumDescriptors  Optional pointer to where to return the number of capsule data descriptors, whose Length is non-zero.
594ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  @param CapsuleSize     Optional pointer to where to return the capsule image size
595ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  @param CapsuleNumber   Optional pointer to where to return the number of capsule
596ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
597ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval EFI_NOT_FOUND   No descriptors containing data in the list
598ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval EFI_SUCCESS     Return data is valid
599ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
600ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin**/
601ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinEFI_STATUS
602ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinGetCapsuleInfo (
603ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN EFI_CAPSULE_BLOCK_DESCRIPTOR   *Desc,
604ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN OUT UINTN                      *NumDescriptors OPTIONAL,
605ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  IN OUT UINTN                      *CapsuleSize OPTIONAL,
606ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  IN OUT UINTN                      *CapsuleNumber OPTIONAL
607ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  )
608ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin{
609ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  UINTN                          Count;
610ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  UINTN                          Size;
611ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  UINTN                          Number;
612ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  UINTN                          ThisCapsuleImageSize;
613ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  EFI_CAPSULE_HEADER             *CapsuleHeader;
614ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao
615ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  DEBUG ((EFI_D_INFO, "GetCapsuleInfo enter\n"));
616ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
617f63085f50c1e8c086d6c4007a9ec68fa66267411li-elvin  ASSERT (Desc != NULL);
618f63085f50c1e8c086d6c4007a9ec68fa66267411li-elvin
619ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  Count = 0;
620ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  Size  = 0;
621ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  Number = 0;
622ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  ThisCapsuleImageSize = 0;
623ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
624ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  while (Desc->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL) {
625ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    if (Desc->Length == 0) {
626ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
627ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      // Descriptor points to another list of block descriptors somewhere
628ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
629ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      Desc = (EFI_CAPSULE_BLOCK_DESCRIPTOR  *) (UINTN) Desc->Union.ContinuationPointer;
630ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    } else {
631ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      //
632ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      // Sanity Check
633ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      // It is needed, because ValidateCapsuleIntegrity() only validate one individual capsule Size.
634ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      // While here we need check all capsules size.
635ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      //
636ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      if (Desc->Length >= (MAX_ADDRESS - Size)) {
637ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        DEBUG ((EFI_D_ERROR, "ERROR: Desc->Length(0x%lx) >= (MAX_ADDRESS - Size(0x%x))\n", Desc->Length, Size));
638ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        return EFI_OUT_OF_RESOURCES;
639ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      }
640ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      Size += (UINTN) Desc->Length;
641ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      Count++;
642ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao
643ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      //
644ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      // See if this is first capsule's header
645ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      //
646ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      if (ThisCapsuleImageSize == 0) {
647ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        CapsuleHeader = (EFI_CAPSULE_HEADER*)((UINTN)Desc->Union.DataBlock);
648ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        //
649ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        // This has been checked in ValidateCapsuleIntegrity()
650ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        //
651ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        Number ++;
652ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        ThisCapsuleImageSize = CapsuleHeader->CapsuleImageSize;
653ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      }
654ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao
655ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      //
656ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      // This has been checked in ValidateCapsuleIntegrity()
657ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      //
658ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      ASSERT (ThisCapsuleImageSize >= Desc->Length);
659ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      ThisCapsuleImageSize = (UINTN)(ThisCapsuleImageSize - Desc->Length);
660ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao
661ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      //
662ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      // Move to next
663ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      //
664ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      Desc++;
665ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    }
666ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
667ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
668ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // If no descriptors, then fail
669ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
670ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  if (Count == 0) {
671ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    DEBUG ((EFI_D_ERROR, "ERROR: Count == 0\n"));
672ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    return EFI_NOT_FOUND;
673ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
674ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
675ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  //
676ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  // checked in ValidateCapsuleIntegrity()
677ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  //
678ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  ASSERT (ThisCapsuleImageSize == 0);
679ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao
680ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  if (NumDescriptors != NULL) {
681ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    *NumDescriptors = Count;
682ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
683ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
684ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  if (CapsuleSize != NULL) {
685ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    *CapsuleSize = Size;
686ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
687ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
688ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  if (CapsuleNumber != NULL) {
689ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    *CapsuleNumber = Number;
690ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  }
691ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao
692ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  return EFI_SUCCESS;
693ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin}
694ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
695ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin/**
696ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  Check every capsule header.
697ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
698ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param CapsuleHeader   The pointer to EFI_CAPSULE_HEADER
699ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
700ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval FALSE  Capsule is OK
701ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval TRUE   Capsule is corrupted
702ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
703ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin**/
704ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinBOOLEAN
705ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinIsCapsuleCorrupted (
706ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN EFI_CAPSULE_HEADER       *CapsuleHeader
707ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  )
708ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin{
709ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
710ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //A capsule to be updated across a system reset should contain CAPSULE_FLAGS_PERSIST_ACROSS_RESET.
711ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
712ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) == 0) {
713ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    return TRUE;
714ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
715ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
716ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //Make sure the flags combination is supported by the platform.
717ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
718ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {
719ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    return TRUE;
720ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
721ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_INITIATE_RESET)) == CAPSULE_FLAGS_INITIATE_RESET) {
722ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    return TRUE;
723ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
724ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
725ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  return FALSE;
726ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin}
727ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
728ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin/**
729ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  Try to verify the integrity of a capsule test pattern before the
730ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  capsule gets coalesced. This can be useful in narrowing down
731ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  where capsule data corruption occurs.
732ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
733ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  The test pattern mode fills in memory with a counting UINT32 value.
734ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  If the capsule is not divided up in a multiple of 4-byte blocks, then
735ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  things get messy doing the check. Therefore there are some cases
736ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  here where we just give up and skip the pre-coalesce check.
737ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
738ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param PeiServices  PEI services table
739ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param Desc         Pointer to capsule descriptors
740ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin**/
741ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinVOID
742ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinCapsuleTestPatternPreCoalesce (
743ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN EFI_PEI_SERVICES              **PeiServices,
744ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN EFI_CAPSULE_BLOCK_DESCRIPTOR  *Desc
745ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  )
746ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin{
747ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINT32  *TestPtr;
748ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINT32  TestCounter;
749ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINT32  TestSize;
750ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao
751ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  DEBUG ((EFI_D_INFO, "CapsuleTestPatternPreCoalesce\n"));
752ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao
753ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
754ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // Find first data descriptor
755ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
756ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  while ((Desc->Length == 0) && (Desc->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
757ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    Desc = (EFI_CAPSULE_BLOCK_DESCRIPTOR  *) (UINTN) Desc->Union.ContinuationPointer;
758ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
759ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
760ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  if (Desc->Union.ContinuationPointer == 0) {
761ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    return ;
762ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
763ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
764ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // First one better be long enough to at least hold the test signature
765ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
766ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  if (Desc->Length < sizeof (UINT32)) {
767ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    DEBUG ((EFI_D_INFO, "Capsule test pattern pre-coalesce punted #1\n"));
768ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    return ;
769ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
770ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
771ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  TestPtr = (UINT32 *) (UINTN) Desc->Union.DataBlock;
772ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
773ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // 0x54534554 "TEST"
774ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
775ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  if (*TestPtr != 0x54534554) {
776ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    return ;
777ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
778ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
779ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  TestCounter = 0;
780ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  TestSize    = (UINT32) Desc->Length - 2 * sizeof (UINT32);
781ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
782ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // Skip over the signature and the size fields in the pattern data header
783ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
784ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  TestPtr += 2;
785ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  while (1) {
786ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    if ((TestSize & 0x03) != 0) {
787ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      DEBUG ((EFI_D_INFO, "Capsule test pattern pre-coalesce punted #2\n"));
788ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      return ;
789ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    }
790ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
791ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    while (TestSize > 0) {
792ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      if (*TestPtr != TestCounter) {
793ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        DEBUG ((EFI_D_INFO, "Capsule test pattern pre-coalesce failed data corruption check\n"));
794ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        return ;
795ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      }
796ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
797ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      TestSize -= sizeof (UINT32);
798ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      TestCounter++;
799ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      TestPtr++;
800ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    }
801ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    Desc++;
802ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    while ((Desc->Length == 0) && (Desc->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
803ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      Desc = (EFI_CAPSULE_BLOCK_DESCRIPTOR  *) (UINTN) Desc->Union.ContinuationPointer;
804ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    }
805ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
806ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    if (Desc->Union.ContinuationPointer == (EFI_PHYSICAL_ADDRESS) (UINTN) NULL) {
807ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      return ;
808ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    }
809ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    TestSize = (UINT32) Desc->Length;
810ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    TestPtr  = (UINT32 *) (UINTN) Desc->Union.DataBlock;
811ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
812ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin}
813ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
814ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin/**
815ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  Checks for the presence of capsule descriptors.
816ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  Get capsule descriptors from variable CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
817ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
818ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param BlockListBuffer            Pointer to the buffer of capsule descriptors variables
819ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param BlockDescriptorList        Pointer to the capsule descriptors list
820ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
821ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval EFI_SUCCESS               a valid capsule is present
822ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval EFI_NOT_FOUND             if a valid capsule is not present
823ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin**/
824ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinEFI_STATUS
825ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinBuildCapsuleDescriptors (
826ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN  EFI_PHYSICAL_ADDRESS            *BlockListBuffer,
827ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  OUT EFI_CAPSULE_BLOCK_DESCRIPTOR    **BlockDescriptorList
828ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  )
829ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin{
830ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINTN                            Index;
831ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  EFI_CAPSULE_BLOCK_DESCRIPTOR     *LastBlock;
832ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  EFI_CAPSULE_BLOCK_DESCRIPTOR     *TempBlock;
833ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  EFI_CAPSULE_BLOCK_DESCRIPTOR     *HeadBlock;
834ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
835ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  DEBUG ((EFI_D_INFO, "BuildCapsuleDescriptors enter\n"));
836ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao
837ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  LastBlock         = NULL;
838ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  HeadBlock         = NULL;
839ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  TempBlock         = NULL;
840ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  Index             = 0;
841ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
842ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  while (BlockListBuffer[Index] != 0) {
84331abeada42ff7f265e42cdea7c44ea44d16568b9lzeng    //
84431abeada42ff7f265e42cdea7c44ea44d16568b9lzeng    // Test integrity of descriptors.
84531abeada42ff7f265e42cdea7c44ea44d16568b9lzeng    //
846ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    if (BlockListBuffer[Index] < MAX_ADDRESS) {
847ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      TempBlock = ValidateCapsuleIntegrity ((EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)BlockListBuffer[Index]);
848ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      if (TempBlock != NULL) {
849ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        if (LastBlock == NULL) {
850ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao          LastBlock = TempBlock;
85131abeada42ff7f265e42cdea7c44ea44d16568b9lzeng
852ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao          //
853ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao          // Return the base of the block descriptors
854ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao          //
855ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao          HeadBlock = (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)BlockListBuffer[Index];
856ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        } else {
857ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao          //
858ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao          // Combine the different BlockList into single BlockList.
859ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao          //
860ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao          LastBlock->Union.DataBlock = (EFI_PHYSICAL_ADDRESS)(UINTN)BlockListBuffer[Index];
861ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao          LastBlock->Length          = 0;
862ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao          LastBlock                  = TempBlock;
863ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        }
864ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      }
865ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    } else {
866ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      DEBUG ((EFI_D_ERROR, "ERROR: BlockListBuffer[Index](0x%lx) < MAX_ADDRESS\n", BlockListBuffer[Index]));
867ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    }
868ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    Index ++;
869ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
870ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
871ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  if (HeadBlock != NULL) {
872ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    *BlockDescriptorList = HeadBlock;
873ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    return EFI_SUCCESS;
874ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
875ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  return EFI_NOT_FOUND;
876ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin}
877ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
878ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin/**
879ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  The function to coalesce a fragmented capsule in memory.
880ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
881ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  Memory Map for coalesced capsule:
882ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  MemBase +   ---->+---------------------------+<-----------+
883ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  MemSize          | ------------------------- |            |
884ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao                   | |  Capsule [Num-1]      | |            |
885ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao                   | ------------------------- |            |
886ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao                   | |  ................     | |            |
887ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao                   | ------------------------- |            |
888ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao                   | |  Capsule [1]          | |            |
889ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao                   | ------------------------- |            |
890ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao                   | |  Capsule [0]          | |            |
891ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao                   | ------------------------- |            |
892ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                   |    Capsule Image          |            |
893ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyaoCapsuleImageBase-->+---------------------------+
894ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao                   | ------------------------- |            |
895ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao                   | |  CapsuleOffset[Num-1] | |            |
896ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao                   | ------------------------- |            |
897ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao                   | |  ................     | |        CapsuleSize
898ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao                   | ------------------------- |            |
899ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao                   | |  CapsuleOffset[1]     | |            |
900ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao                   | ------------------------- |            |
901ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao                   | |  CapsuleOffset[0]     | |            |
902ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao                   |---------------------------|            |
903ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao                   | |  CapsuleNumber        | |            |
904ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao                   | ------------------------- |            |
905ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao                   | |  CapsuleAllImageSize  | |            |
906ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao                   | ------------------------- |            |
907ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                   |    PrivateData            |            |
908ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao     DestPtr  ---->+---------------------------+<-----------+
909ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                   |                           |            |
910ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                   |     FreeMem               |        FreeMemSize
911ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                   |                           |            |
912ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin   FreeMemBase --->+---------------------------+<-----------+
913ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                   |    Terminator             |
914ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                   +---------------------------+
915ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                   |    BlockDescriptor n      |
916ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                   +---------------------------+
917ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                   |    .................      |
918ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                   +---------------------------+
919ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                   |    BlockDescriptor 1      |
920ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                   +---------------------------+
921ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                   |    BlockDescriptor 0      |
922ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                   +---------------------------+
923ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                   |    PrivateDataDesc 0      |
924ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      MemBase ---->+---------------------------+<----- BlockList
925ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
926dc204d5a0fd64d1ccbc90ebea827e7ad73b71f4djyao  Caution: This function may receive untrusted input.
927dc204d5a0fd64d1ccbc90ebea827e7ad73b71f4djyao  The capsule data is external input, so this routine will do basic validation before
928dc204d5a0fd64d1ccbc90ebea827e7ad73b71f4djyao  coalesce capsule data into memory.
929dc204d5a0fd64d1ccbc90ebea827e7ad73b71f4djyao
930ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param PeiServices        General purpose services available to every PEIM.
931ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param BlockListBuffer    Point to the buffer of Capsule Descriptor Variables.
932ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param MemoryBase         Pointer to the base of a block of memory that we can walk
933ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                            all over while trying to coalesce our buffers.
934ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                            On output, this variable will hold the base address of
935ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                            a coalesced capsule.
936ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @param MemorySize         Size of the memory region pointed to by MemoryBase.
937ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                            On output, this variable will contain the size of the
938ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                            coalesced capsule.
939ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
940ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval EFI_NOT_FOUND     If we could not find the capsule descriptors.
941ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
942ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval EFI_BUFFER_TOO_SMALL
943ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                            If we could not coalesce the capsule in the memory
944ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                            region provided to us.
945ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
946ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  @retval EFI_SUCCESS       Processed the capsule successfully.
947ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin**/
948ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinEFI_STATUS
949ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinEFIAPI
950ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvinCapsuleDataCoalesce (
951ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN EFI_PEI_SERVICES                **PeiServices,
952ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN EFI_PHYSICAL_ADDRESS            *BlockListBuffer,
953ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN OUT VOID                        **MemoryBase,
954ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  IN OUT UINTN                       *MemorySize
955ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  )
956ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin{
957ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  VOID                           *NewCapsuleBase;
958ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  VOID                           *CapsuleImageBase;
959ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  UINTN                          CapsuleIndex;
960ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINT8                          *FreeMemBase;
961ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINT8                          *DestPtr;
962ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  UINTN                          DestLength;
963ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINT8                          *RelocPtr;
964ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  UINTN                          CapsuleTimes;
965ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINT64                         SizeLeft;
966ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINT64                         CapsuleImageSize;
967ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINTN                          CapsuleSize;
968ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  UINTN                          CapsuleNumber;
969ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINTN                          DescriptorsSize;
970ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINTN                          FreeMemSize;
971ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  UINTN                          NumDescriptors;
972ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  BOOLEAN                        CapsuleBeginFlag;
973ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  EFI_STATUS                     Status;
974ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  EFI_CAPSULE_HEADER             *CapsuleHeader;
975ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  EFI_CAPSULE_PEIM_PRIVATE_DATA  PrivateData;
976ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  EFI_CAPSULE_PEIM_PRIVATE_DATA  *PrivateDataPtr;
977ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  EFI_CAPSULE_BLOCK_DESCRIPTOR   *BlockList;
978ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  EFI_CAPSULE_BLOCK_DESCRIPTOR   *CurrentBlockDesc;
979ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  EFI_CAPSULE_BLOCK_DESCRIPTOR   *TempBlockDesc;
980ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  EFI_CAPSULE_BLOCK_DESCRIPTOR   PrivateDataDesc[2];
981ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
982ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  DEBUG ((EFI_D_INFO, "CapsuleDataCoalesce enter\n"));
983ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao
984ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  CapsuleIndex     = 0;
985ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  SizeLeft         = 0;
986ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  CapsuleTimes     = 0;
987ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  CapsuleImageSize = 0;
988ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  PrivateDataPtr   = NULL;
989ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  CapsuleHeader    = NULL;
990ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  CapsuleBeginFlag = TRUE;
991ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  CapsuleSize      = 0;
992ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  NumDescriptors   = 0;
993ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao
994ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
995ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // Build capsule descriptors list
996ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
997ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  Status = BuildCapsuleDescriptors (BlockListBuffer, &BlockList);
998ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  if (EFI_ERROR (Status)) {
999ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    return Status;
1000ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
1001ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
1002ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  DEBUG_CODE (
1003ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    CapsuleTestPatternPreCoalesce (PeiServices, BlockList);
1004ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  );
1005ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
1006ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
1007ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // Get the size of our descriptors and the capsule size. GetCapsuleInfo()
1008ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // returns the number of descriptors that actually point to data, so add
1009ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // one for a terminator. Do that below.
1010ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
1011ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  Status = GetCapsuleInfo (BlockList, &NumDescriptors, &CapsuleSize, &CapsuleNumber);
1012ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  if (EFI_ERROR (Status)) {
1013ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    return Status;
1014ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  }
1015ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  DEBUG ((EFI_D_INFO, "CapsuleSize - 0x%x\n", CapsuleSize));
1016ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  DEBUG ((EFI_D_INFO, "CapsuleNumber - 0x%x\n", CapsuleNumber));
1017ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  DEBUG ((EFI_D_INFO, "NumDescriptors - 0x%x\n", NumDescriptors));
1018ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  if ((CapsuleSize == 0) || (NumDescriptors == 0) || (CapsuleNumber == 0)) {
1019ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    return EFI_NOT_FOUND;
1020ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
1021ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
1022ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  if (CapsuleNumber - 1 >= (MAX_ADDRESS - (sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA)  + sizeof(UINT64))) / sizeof(UINT64)) {
1023ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    DEBUG ((EFI_D_ERROR, "ERROR: CapsuleNumber - 0x%x\n", CapsuleNumber));
1024ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    return EFI_BUFFER_TOO_SMALL;
1025ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  }
1026ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao
1027ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
1028ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // Initialize our local copy of private data. When we're done, we'll create a
1029ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // descriptor for it as well so that it can be put into free memory without
1030ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // trashing anything.
1031ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
1032ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  PrivateData.Signature           = EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE;
1033ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  PrivateData.CapsuleAllImageSize = (UINT64) CapsuleSize;
1034ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  PrivateData.CapsuleNumber       = (UINT64) CapsuleNumber;
1035ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  PrivateData.CapsuleOffset[0]    = 0;
1036ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  //
1037ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  // NOTE: Only data in sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) is valid, CapsuleOffset field is unitialized at this moment.
1038ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  // The code sets partial length here for Descriptor.Length check, but later it will use full length to reserve those PrivateData region.
1039ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  //
1040ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  PrivateDataDesc[0].Union.DataBlock  = (EFI_PHYSICAL_ADDRESS) (UINTN) &PrivateData;
1041ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  PrivateDataDesc[0].Length           = sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA);
1042ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  PrivateDataDesc[1].Union.DataBlock  = (EFI_PHYSICAL_ADDRESS) (UINTN) BlockList;
1043ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  PrivateDataDesc[1].Length           = 0;
1044ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
1045ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  // Add PrivateDataDesc[0] in beginning beginning, as it is new descriptor. PrivateDataDesc[1] is NOT needed.
1046ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  // In addition, one NULL terminator is added in the end. See RelocateBlockDescriptors().
1047ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  //
1048ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  NumDescriptors  += 2;
1049ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
1050ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  // Sandity check
1051ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  //
1052ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  if (CapsuleSize >= (MAX_ADDRESS - (sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64) + sizeof(UINT64)))) {
1053ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    DEBUG ((EFI_D_ERROR, "ERROR: CapsuleSize - 0x%x\n", CapsuleSize));
1054ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    return EFI_BUFFER_TOO_SMALL;
1055ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  }
1056ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  //
1057ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  // Need add sizeof(UINT64) for PrivateData alignment
1058ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  //
1059ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  CapsuleSize     += sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64) + sizeof(UINT64);
1060ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  BlockList        = PrivateDataDesc;
1061ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  //
1062ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  // Sandity check
1063ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  //
1064ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  if (NumDescriptors >= (MAX_ADDRESS / sizeof(EFI_CAPSULE_BLOCK_DESCRIPTOR))) {
1065ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    DEBUG ((EFI_D_ERROR, "ERROR: NumDescriptors - 0x%x\n", NumDescriptors));
1066ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    return EFI_BUFFER_TOO_SMALL;
1067ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  }
1068ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  DescriptorsSize  = NumDescriptors * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
1069ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  //
1070ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  // Sandity check
1071ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  //
1072ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  if (DescriptorsSize >= (MAX_ADDRESS - CapsuleSize)) {
1073ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    DEBUG ((EFI_D_ERROR, "ERROR: DescriptorsSize - 0x%lx, CapsuleSize - 0x%lx\n", (UINT64)DescriptorsSize, (UINT64)CapsuleSize));
1074ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    return EFI_BUFFER_TOO_SMALL;
1075ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  }
1076ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
1077ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
1078ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // Don't go below some min address. If the base is below it,
1079ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // then move it up and adjust the size accordingly.
1080ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
1081ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  DEBUG ((EFI_D_INFO, "Capsule Memory range from 0x%8X to 0x%8X\n", (UINTN) *MemoryBase, (UINTN)*MemoryBase + *MemorySize));
1082ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  if ((UINTN)*MemoryBase < (UINTN) MIN_COALESCE_ADDR) {
1083ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    if (((UINTN)*MemoryBase + *MemorySize) < (UINTN) MIN_COALESCE_ADDR) {
1084ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      DEBUG ((EFI_D_ERROR, "ERROR: *MemoryBase + *MemorySize - 0x%x\n", (UINTN)*MemoryBase + *MemorySize));
1085ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      return EFI_BUFFER_TOO_SMALL;
1086ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    } else {
1087ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      *MemorySize = *MemorySize - ((UINTN) MIN_COALESCE_ADDR - (UINTN) *MemoryBase);
1088ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      *MemoryBase = (VOID *) (UINTN) MIN_COALESCE_ADDR;
1089ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    }
1090ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
1091ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
1092ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  if (*MemorySize <= (CapsuleSize + DescriptorsSize)) {
1093ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    DEBUG ((EFI_D_ERROR, "ERROR: CapsuleSize + DescriptorsSize - 0x%x\n", CapsuleSize + DescriptorsSize));
1094ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    return EFI_BUFFER_TOO_SMALL;
1095ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
1096ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
1097ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  FreeMemBase = *MemoryBase;
1098ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  FreeMemSize = *MemorySize;
1099ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  DEBUG ((EFI_D_INFO, "Capsule Free Memory from 0x%8X to 0x%8X\n", (UINTN) FreeMemBase, (UINTN) FreeMemBase + FreeMemSize));
1100ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
1101ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
1102ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // Relocate all the block descriptors to low memory to make further
1103ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // processing easier.
1104ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
1105ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  BlockList = RelocateBlockDescriptors (PeiServices, BlockList, NumDescriptors, FreeMemBase, FreeMemSize);
1106ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  if (BlockList == NULL) {
1107ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
1108ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    // Not enough room to relocate the descriptors
1109ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
1110ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    return EFI_BUFFER_TOO_SMALL;
1111ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
1112ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
1113ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
1114ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  // Take the top of memory for the capsule. UINT64 align up.
1115ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
1116ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  DestPtr         = FreeMemBase + FreeMemSize - CapsuleSize;
1117ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  DestPtr         = (UINT8 *) (((UINTN)DestPtr + sizeof (UINT64) - 1) & ~(sizeof (UINT64) - 1));
1118ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  FreeMemBase     = (UINT8 *) BlockList + DescriptorsSize;
11194694dd1ba8ad0242a7cf7467568ce001619d3fdelzeng  FreeMemSize     = (UINTN) DestPtr - (UINTN) FreeMemBase;
1120ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  NewCapsuleBase  = (VOID *) DestPtr;
1121ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  CapsuleImageBase = (UINT8 *)NewCapsuleBase + sizeof(EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64);
1122ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao
1123ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  PrivateDataPtr = (EFI_CAPSULE_PEIM_PRIVATE_DATA *) NewCapsuleBase;
1124ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
1125ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
1126ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // Move all the blocks to the top (high) of memory.
1127ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // Relocate all the obstructing blocks. Note that the block descriptors
1128ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // were coalesced when they were relocated, so we can just ++ the pointer.
1129ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
1130ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  CurrentBlockDesc = BlockList;
1131ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  while ((CurrentBlockDesc->Length != 0) || (CurrentBlockDesc->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
1132ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    if (CapsuleTimes == 0) {
1133ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      //
1134ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      // The first entry is the block descriptor for EFI_CAPSULE_PEIM_PRIVATE_DATA.
1135ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      // CapsuleOffset field is uninitialized at this time. No need copy it, but need to reserve for future use.
1136ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      //
1137ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      ASSERT (CurrentBlockDesc->Union.DataBlock == (UINT64)(UINTN)&PrivateData);
1138ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      DestLength = sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64);
1139ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    } else {
1140ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      DestLength = (UINTN)CurrentBlockDesc->Length;
1141ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao    }
1142ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
1143ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    // See if any of the remaining capsule blocks are in the way
1144ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
1145ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    TempBlockDesc = CurrentBlockDesc;
1146ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    while (TempBlockDesc->Length != 0) {
1147ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
1148ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      // Is this block in the way of where we want to copy the current descriptor to?
1149ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
1150ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      if (IsOverlapped (
1151ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin            (UINT8 *) DestPtr,
1152ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao            (UINTN) DestLength,
1153ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin            (UINT8 *) (UINTN) TempBlockDesc->Union.DataBlock,
1154ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin            (UINTN) TempBlockDesc->Length
1155ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin            )) {
1156ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        //
1157ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        // Relocate the block
1158ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        //
1159ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        RelocPtr = FindFreeMem (BlockList, FreeMemBase, FreeMemSize, (UINTN) TempBlockDesc->Length);
1160ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        if (RelocPtr == NULL) {
1161ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin          return EFI_BUFFER_TOO_SMALL;
1162ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        }
1163ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
1164ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        CopyMem ((VOID *) RelocPtr, (VOID *) (UINTN) TempBlockDesc->Union.DataBlock, (UINTN) TempBlockDesc->Length);
1165ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        DEBUG ((EFI_D_INFO, "Capsule reloc data block from 0x%8X to 0x%8X with size 0x%8X\n",
1166ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin                (UINTN) TempBlockDesc->Union.DataBlock, (UINTN) RelocPtr, (UINTN) TempBlockDesc->Length));
1167ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
1168ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        TempBlockDesc->Union.DataBlock = (EFI_PHYSICAL_ADDRESS) (UINTN) RelocPtr;
1169ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      }
1170ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
1171ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      // Next descriptor
1172ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
1173ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      TempBlockDesc++;
1174ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    }
1175ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
1176ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    // Ok, we made it through. Copy the block.
1177ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    // we just support greping one capsule from the lists of block descs list.
1178ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
1179ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    CapsuleTimes ++;
1180ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
1181ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //Skip the first block descriptor that filled with EFI_CAPSULE_PEIM_PRIVATE_DATA
1182ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
1183ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    if (CapsuleTimes > 1) {
1184ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
1185ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //For every capsule entry point, check its header to determine whether to relocate it.
1186ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //If it is invalid, skip it and move on to the next capsule. If it is valid, relocate it.
1187ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
1188ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      if (CapsuleBeginFlag) {
1189ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        CapsuleBeginFlag  = FALSE;
1190ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        CapsuleHeader     = (EFI_CAPSULE_HEADER*)(UINTN)CurrentBlockDesc->Union.DataBlock;
1191ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        SizeLeft          = CapsuleHeader->CapsuleImageSize;
1192ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
1193ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        //
1194ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        // No more check here is needed, because IsCapsuleCorrupted() already in ValidateCapsuleIntegrity()
1195ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        //
1196ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        ASSERT (CapsuleIndex < CapsuleNumber);
1197ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
1198ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        //
1199ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        // Relocate this capsule
1200ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        //
1201ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        CapsuleImageSize += SizeLeft;
1202ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        //
1203ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        // Cache the begin offset of this capsule
1204ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        //
1205ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        ASSERT (PrivateDataPtr->Signature == EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE);
1206ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        ASSERT ((UINTN)DestPtr >= (UINTN)CapsuleImageBase);
1207ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao        PrivateDataPtr->CapsuleOffset[CapsuleIndex++] = (UINT64)((UINTN)DestPtr - (UINTN)CapsuleImageBase);
1208240bc4ee8fdd73054b6dd58547ef416b9d9e2a7flzeng      }
1209240bc4ee8fdd73054b6dd58547ef416b9d9e2a7flzeng
1210ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      //
1211ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      // Below ASSERT is checked in ValidateCapsuleIntegrity()
1212ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      //
1213ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      ASSERT (CurrentBlockDesc->Length <= SizeLeft);
1214ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao
1215ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      CopyMem ((VOID *) DestPtr, (VOID *) (UINTN) (CurrentBlockDesc->Union.DataBlock), (UINTN)CurrentBlockDesc->Length);
1216ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      DEBUG ((EFI_D_INFO, "Capsule coalesce block no.0x%lX from 0x%lX to 0x%lX with size 0x%lX\n",(UINT64)CapsuleTimes,
1217ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao             CurrentBlockDesc->Union.DataBlock, (UINT64)(UINTN)DestPtr, CurrentBlockDesc->Length));
1218ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      DestPtr += CurrentBlockDesc->Length;
1219ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      SizeLeft -= CurrentBlockDesc->Length;
1220ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao
1221ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      if (SizeLeft == 0) {
1222ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        //
1223240bc4ee8fdd73054b6dd58547ef416b9d9e2a7flzeng        //Here is the end of the current capsule image.
1224ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin        //
1225240bc4ee8fdd73054b6dd58547ef416b9d9e2a7flzeng        CapsuleBeginFlag = TRUE;
1226ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      }
1227ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    } else {
1228ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
1229ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      // The first entry is the block descriptor for EFI_CAPSULE_PEIM_PRIVATE_DATA.
1230ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      // CapsuleOffset field is uninitialized at this time. No need copy it, but need to reserve for future use.
1231ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      //
1232ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      ASSERT (CurrentBlockDesc->Length == sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA));
1233ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      ASSERT ((UINTN)DestPtr == (UINTN)NewCapsuleBase);
1234ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin      CopyMem ((VOID *) DestPtr, (VOID *) (UINTN) CurrentBlockDesc->Union.DataBlock, (UINTN) CurrentBlockDesc->Length);
1235ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao      DestPtr += sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64);
1236ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    }
1237ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
1238ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //Walk through the block descriptor list.
1239ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    //
1240ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin    CurrentBlockDesc++;
1241ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  }
1242ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
1243ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // We return the base of memory we want reserved, and the size.
1244ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  // The memory peim should handle it appropriately from there.
1245ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  //
12462e4c9e0158cc10226dc0e2de679bc984e288f18alzeng  *MemorySize = (UINTN) CapsuleSize;
1247ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  *MemoryBase = (VOID *) NewCapsuleBase;
1248ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
1249ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  ASSERT (PrivateDataPtr->Signature == EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE);
1250ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  ASSERT (PrivateDataPtr->CapsuleAllImageSize == CapsuleImageSize);
1251ff284c56a11a9a9b32777c91bc069093d5b5d8a9jyao  ASSERT (PrivateDataPtr->CapsuleNumber == CapsuleIndex);
1252ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin
1253ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin  return EFI_SUCCESS;
1254ab7017fe2bf2c1944090d347e7853e087d8641e8li-elvin}
1255