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