mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-25 22:54:51 +02:00
CapsulePei coalesce need add more sanity check for each Capsule Fragment.
Signed-off by: jiewen yao <jiewen.yao@intel.com> Reviewed by: elvin li <elvin.li@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15137 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
3a1966c4e2
commit
ff284c56a1
@ -9,7 +9,7 @@
|
|||||||
CapsuleDataCoalesce() will do basic validation before coalesce capsule data
|
CapsuleDataCoalesce() will do basic validation before coalesce capsule data
|
||||||
into memory.
|
into memory.
|
||||||
|
|
||||||
Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -30,15 +30,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#include <Library/PrintLib.h>
|
#include <Library/PrintLib.h>
|
||||||
#include <Library/BaseLib.h>
|
#include <Library/BaseLib.h>
|
||||||
|
|
||||||
|
#include "CommonHeader.h"
|
||||||
|
|
||||||
#define MIN_COALESCE_ADDR (1024 * 1024)
|
#define MIN_COALESCE_ADDR (1024 * 1024)
|
||||||
#define MAX_SUPPORT_CAPSULE_NUM 50
|
|
||||||
|
|
||||||
#define EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('C', 'a', 'p', 'D')
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
UINT32 Signature;
|
|
||||||
UINT32 CapsuleSize;
|
|
||||||
} EFI_CAPSULE_PEIM_PRIVATE_DATA;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Given a pointer to the capsule block list, info on the available system
|
Given a pointer to the capsule block list, info on the available system
|
||||||
@ -87,10 +81,11 @@ ValidateCapsuleIntegrity (
|
|||||||
they are relocated into memory to turn them into a contiguous (null
|
they are relocated into memory to turn them into a contiguous (null
|
||||||
terminated) array.
|
terminated) array.
|
||||||
|
|
||||||
@param PeiServices pointer to PEI services table
|
@param PeiServices pointer to PEI services table
|
||||||
@param BlockList pointer to the capsule block descriptors
|
@param BlockList pointer to the capsule block descriptors
|
||||||
@param MemBase base of system memory in which we can work
|
@param NumDescriptors number of capsule data block descriptors, whose Length is non-zero.
|
||||||
@param MemSize size of the system memory pointed to by MemBase
|
@param MemBase base of system memory in which we can work
|
||||||
|
@param MemSize size of the system memory pointed to by MemBase
|
||||||
|
|
||||||
@retval NULL could not relocate the descriptors
|
@retval NULL could not relocate the descriptors
|
||||||
@retval Pointer to the base of the successfully-relocated block descriptors.
|
@retval Pointer to the base of the successfully-relocated block descriptors.
|
||||||
@ -100,6 +95,7 @@ EFI_CAPSULE_BLOCK_DESCRIPTOR *
|
|||||||
RelocateBlockDescriptors (
|
RelocateBlockDescriptors (
|
||||||
IN EFI_PEI_SERVICES **PeiServices,
|
IN EFI_PEI_SERVICES **PeiServices,
|
||||||
IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList,
|
IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList,
|
||||||
|
IN UINTN NumDescriptors,
|
||||||
IN UINT8 *MemBase,
|
IN UINT8 *MemBase,
|
||||||
IN UINTN MemSize
|
IN UINTN MemSize
|
||||||
);
|
);
|
||||||
@ -144,10 +140,9 @@ IsOverlapped (
|
|||||||
refers to is.
|
refers to is.
|
||||||
|
|
||||||
@param Desc Pointer to the capsule block descriptors
|
@param Desc Pointer to the capsule block descriptors
|
||||||
NumDescriptors - optional pointer to where to return the number of descriptors
|
@param NumDescriptors Optional pointer to where to return the number of capsule data descriptors, whose Length is non-zero.
|
||||||
CapsuleSize - optional pointer to where to return the capsule size
|
@param CapsuleSize Optional pointer to where to return the capsule image size
|
||||||
@param NumDescriptors Optional pointer to where to return the number of descriptors
|
@param CapsuleNumber Optional pointer to where to return the number of capsule
|
||||||
@param CapsuleSize Optional pointer to where to return the capsule size
|
|
||||||
|
|
||||||
@retval EFI_NOT_FOUND No descriptors containing data in the list
|
@retval EFI_NOT_FOUND No descriptors containing data in the list
|
||||||
@retval EFI_SUCCESS Return data is valid
|
@retval EFI_SUCCESS Return data is valid
|
||||||
@ -157,7 +152,8 @@ EFI_STATUS
|
|||||||
GetCapsuleInfo (
|
GetCapsuleInfo (
|
||||||
IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Desc,
|
IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Desc,
|
||||||
IN OUT UINTN *NumDescriptors OPTIONAL,
|
IN OUT UINTN *NumDescriptors OPTIONAL,
|
||||||
IN OUT UINTN *CapsuleSize OPTIONAL
|
IN OUT UINTN *CapsuleSize OPTIONAL,
|
||||||
|
IN OUT UINTN *CapsuleNumber OPTIONAL
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -266,34 +262,69 @@ ValidateCapsuleIntegrity (
|
|||||||
{
|
{
|
||||||
EFI_CAPSULE_HEADER *CapsuleHeader;
|
EFI_CAPSULE_HEADER *CapsuleHeader;
|
||||||
UINT64 CapsuleSize;
|
UINT64 CapsuleSize;
|
||||||
UINT32 CapsuleCount;
|
UINTN CapsuleCount;
|
||||||
EFI_CAPSULE_BLOCK_DESCRIPTOR *Ptr;
|
EFI_CAPSULE_BLOCK_DESCRIPTOR *Ptr;
|
||||||
|
|
||||||
|
DEBUG ((EFI_D_INFO, "ValidateCapsuleIntegrity\n"));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Go through the list to look for inconsistencies. Check for:
|
// Go through the list to look for inconsistencies. Check for:
|
||||||
// * misaligned block descriptors.
|
// * misaligned block descriptors.
|
||||||
// * The first capsule header guid
|
// * The first capsule header guid
|
||||||
// * The first capsule header flag
|
// * The first capsule header flag
|
||||||
// * Data + Length < Data (wrap)
|
// * The first capsule header HeaderSize
|
||||||
|
// * Length > MAX_ADDRESS
|
||||||
|
// * ContinuationPointer > MAX_ADDRESS
|
||||||
|
// * DataBlock + Length > MAX_ADDRESS
|
||||||
|
//
|
||||||
CapsuleSize = 0;
|
CapsuleSize = 0;
|
||||||
CapsuleCount = 0;
|
CapsuleCount = 0;
|
||||||
Ptr = BlockList;
|
Ptr = BlockList;
|
||||||
|
|
||||||
|
DEBUG ((EFI_D_INFO, "Ptr - 0x%x\n", Ptr));
|
||||||
|
DEBUG ((EFI_D_INFO, "Ptr->Length - 0x%x\n", Ptr->Length));
|
||||||
|
DEBUG ((EFI_D_INFO, "Ptr->Union - 0x%x\n", Ptr->Union.ContinuationPointer));
|
||||||
while ((Ptr->Length != 0) || (Ptr->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
|
while ((Ptr->Length != 0) || (Ptr->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
|
||||||
//
|
//
|
||||||
// Make sure the descriptor is aligned at UINT64 in memory
|
// Make sure the descriptor is aligned at UINT64 in memory
|
||||||
//
|
//
|
||||||
if ((UINTN) Ptr & 0x07) {
|
if ((UINTN) Ptr & (sizeof(UINT64) - 1)) {
|
||||||
DEBUG ((EFI_D_ERROR, "BlockList address failed alignment check\n"));
|
DEBUG ((EFI_D_ERROR, "ERROR: BlockList address failed alignment check\n"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Sanity Check
|
||||||
|
//
|
||||||
|
if (Ptr->Length > MAX_ADDRESS) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "ERROR: Ptr->Length(0x%lx) > MAX_ADDRESS\n", Ptr->Length));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Ptr->Length == 0) {
|
if (Ptr->Length == 0) {
|
||||||
|
//
|
||||||
|
// Sanity Check
|
||||||
|
//
|
||||||
|
if (Ptr->Union.ContinuationPointer > MAX_ADDRESS) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "ERROR: Ptr->Union.ContinuationPointer(0x%lx) > MAX_ADDRESS\n", Ptr->Union.ContinuationPointer));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
//
|
//
|
||||||
// Descriptor points to another list of block descriptors somewhere
|
// Descriptor points to another list of block descriptors somewhere
|
||||||
// else.
|
// else.
|
||||||
//
|
//
|
||||||
Ptr = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) Ptr->Union.ContinuationPointer;
|
Ptr = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) Ptr->Union.ContinuationPointer;
|
||||||
|
DEBUG ((EFI_D_INFO, "Ptr(C) - 0x%x\n", Ptr));
|
||||||
|
DEBUG ((EFI_D_INFO, "Ptr->Length - 0x%x\n", Ptr->Length));
|
||||||
|
DEBUG ((EFI_D_INFO, "Ptr->Union - 0x%x\n", Ptr->Union.ContinuationPointer));
|
||||||
} else {
|
} else {
|
||||||
|
//
|
||||||
|
// Sanity Check
|
||||||
|
//
|
||||||
|
if (Ptr->Union.DataBlock > (MAX_ADDRESS - (UINTN)Ptr->Length)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "ERROR: Ptr->Union.DataBlock(0x%lx) > (MAX_ADDRESS - (UINTN)Ptr->Length(0x%lx))\n", Ptr->Union.DataBlock, Ptr->Length));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
//To enhance the reliability of check-up, the first capsule's header is checked here.
|
//To enhance the reliability of check-up, the first capsule's header is checked here.
|
||||||
//More reliabilities check-up will do later.
|
//More reliabilities check-up will do later.
|
||||||
@ -303,6 +334,20 @@ ValidateCapsuleIntegrity (
|
|||||||
//Move to the first capsule to check its header.
|
//Move to the first capsule to check its header.
|
||||||
//
|
//
|
||||||
CapsuleHeader = (EFI_CAPSULE_HEADER*)((UINTN)Ptr->Union.DataBlock);
|
CapsuleHeader = (EFI_CAPSULE_HEADER*)((UINTN)Ptr->Union.DataBlock);
|
||||||
|
//
|
||||||
|
// Sanity check
|
||||||
|
//
|
||||||
|
if (Ptr->Length < sizeof(EFI_CAPSULE_HEADER)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "ERROR: Ptr->Length(0x%lx) < sizeof(EFI_CAPSULE_HEADER)\n", Ptr->Length));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Make sure HeaderSize field is valid
|
||||||
|
//
|
||||||
|
if (CapsuleHeader->HeaderSize > CapsuleHeader->CapsuleImageSize) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "ERROR: CapsuleHeader->HeaderSize(0x%x) > CapsuleHeader->CapsuleImageSize(0x%x)\n", CapsuleHeader->HeaderSize, CapsuleHeader->CapsuleImageSize));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if (IsCapsuleCorrupted (CapsuleHeader)) {
|
if (IsCapsuleCorrupted (CapsuleHeader)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -313,20 +358,36 @@ ValidateCapsuleIntegrity (
|
|||||||
if (CapsuleSize >= Ptr->Length) {
|
if (CapsuleSize >= Ptr->Length) {
|
||||||
CapsuleSize = CapsuleSize - Ptr->Length;
|
CapsuleSize = CapsuleSize - Ptr->Length;
|
||||||
} else {
|
} else {
|
||||||
CapsuleSize = 0;
|
DEBUG ((EFI_D_ERROR, "ERROR: CapsuleSize(0x%lx) < Ptr->Length(0x%lx)\n", CapsuleSize, Ptr->Length));
|
||||||
|
//
|
||||||
|
// Sanity check
|
||||||
|
//
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Move to next BLOCK descriptor
|
// Move to next BLOCK descriptor
|
||||||
//
|
//
|
||||||
Ptr++;
|
Ptr++;
|
||||||
|
DEBUG ((EFI_D_INFO, "Ptr(B) - 0x%x\n", Ptr));
|
||||||
|
DEBUG ((EFI_D_INFO, "Ptr->Length - 0x%x\n", Ptr->Length));
|
||||||
|
DEBUG ((EFI_D_INFO, "Ptr->Union - 0x%x\n", Ptr->Union.ContinuationPointer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((CapsuleCount == 0) || (CapsuleSize != 0)) {
|
if (CapsuleCount == 0) {
|
||||||
//
|
//
|
||||||
// No any capsule is found in BlockList or capsule data is corrupted.
|
// No any capsule is found in BlockList
|
||||||
//
|
//
|
||||||
|
DEBUG ((EFI_D_ERROR, "ERROR: CapsuleCount(0x%x) == 0\n", CapsuleCount));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CapsuleSize != 0) {
|
||||||
|
//
|
||||||
|
// Capsule data is incomplete.
|
||||||
|
//
|
||||||
|
DEBUG ((EFI_D_ERROR, "ERROR: CapsuleSize(0x%lx) != 0\n", CapsuleSize));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,10 +403,11 @@ ValidateCapsuleIntegrity (
|
|||||||
they are relocated into memory to turn them into a contiguous (null
|
they are relocated into memory to turn them into a contiguous (null
|
||||||
terminated) array.
|
terminated) array.
|
||||||
|
|
||||||
@param PeiServices pointer to PEI services table
|
@param PeiServices pointer to PEI services table
|
||||||
@param BlockList pointer to the capsule block descriptors
|
@param BlockList pointer to the capsule block descriptors
|
||||||
@param MemBase base of system memory in which we can work
|
@param NumDescriptors number of capsule data block descriptors, whose Length is non-zero.
|
||||||
@param MemSize size of the system memory pointed to by MemBase
|
@param MemBase base of system memory in which we can work
|
||||||
|
@param MemSize size of the system memory pointed to by MemBase
|
||||||
|
|
||||||
@retval NULL could not relocate the descriptors
|
@retval NULL could not relocate the descriptors
|
||||||
@retval Pointer to the base of the successfully-relocated block descriptors.
|
@retval Pointer to the base of the successfully-relocated block descriptors.
|
||||||
@ -355,6 +417,7 @@ EFI_CAPSULE_BLOCK_DESCRIPTOR *
|
|||||||
RelocateBlockDescriptors (
|
RelocateBlockDescriptors (
|
||||||
IN EFI_PEI_SERVICES **PeiServices,
|
IN EFI_PEI_SERVICES **PeiServices,
|
||||||
IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList,
|
IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList,
|
||||||
|
IN UINTN NumDescriptors,
|
||||||
IN UINT8 *MemBase,
|
IN UINT8 *MemBase,
|
||||||
IN UINTN MemSize
|
IN UINTN MemSize
|
||||||
)
|
)
|
||||||
@ -363,21 +426,17 @@ RelocateBlockDescriptors (
|
|||||||
EFI_CAPSULE_BLOCK_DESCRIPTOR *CurrBlockDescHead;
|
EFI_CAPSULE_BLOCK_DESCRIPTOR *CurrBlockDescHead;
|
||||||
EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockDesc;
|
EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockDesc;
|
||||||
EFI_CAPSULE_BLOCK_DESCRIPTOR *PrevBlockDescTail;
|
EFI_CAPSULE_BLOCK_DESCRIPTOR *PrevBlockDescTail;
|
||||||
UINTN NumDescriptors;
|
|
||||||
UINTN BufferSize;
|
UINTN BufferSize;
|
||||||
UINT8 *RelocBuffer;
|
UINT8 *RelocBuffer;
|
||||||
UINTN BlockListSize;
|
UINTN BlockListSize;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the info on the blocks and descriptors. Since we're going to move
|
// Get the info on the blocks and descriptors. Since we're going to move
|
||||||
// the descriptors low in memory, adjust the base/size values accordingly here.
|
// the descriptors low in memory, adjust the base/size values accordingly here.
|
||||||
// GetCapsuleInfo() returns the number of legit descriptors, so add one for
|
// NumDescriptors is the number of legit data descriptors, so add one for
|
||||||
// a terminator.
|
// a terminator. (Already done by caller, no check is needed.)
|
||||||
//
|
//
|
||||||
if (GetCapsuleInfo (BlockList, &NumDescriptors, NULL) != EFI_SUCCESS) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
NumDescriptors++;
|
|
||||||
BufferSize = NumDescriptors * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
|
BufferSize = NumDescriptors * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
|
||||||
NewBlockList = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) MemBase;
|
NewBlockList = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) MemBase;
|
||||||
if (MemSize < BufferSize) {
|
if (MemSize < BufferSize) {
|
||||||
@ -416,7 +475,7 @@ RelocateBlockDescriptors (
|
|||||||
}
|
}
|
||||||
|
|
||||||
CopyMem ((VOID *) RelocBuffer, (VOID *) (UINTN) TempBlockDesc->Union.DataBlock, (UINTN) TempBlockDesc->Length);
|
CopyMem ((VOID *) RelocBuffer, (VOID *) (UINTN) TempBlockDesc->Union.DataBlock, (UINTN) TempBlockDesc->Length);
|
||||||
DEBUG ((EFI_D_INFO, "Capsule relocate descriptors from/to/size 0x%X 0x%X 0x%X\n", (UINT32)(UINTN)TempBlockDesc->Union.DataBlock, (UINT32)(UINTN)RelocBuffer, (UINT32)(UINTN)TempBlockDesc->Length));
|
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));
|
||||||
TempBlockDesc->Union.DataBlock = (EFI_PHYSICAL_ADDRESS) (UINTN) RelocBuffer;
|
TempBlockDesc->Union.DataBlock = (EFI_PHYSICAL_ADDRESS) (UINTN) RelocBuffer;
|
||||||
}
|
}
|
||||||
TempBlockDesc++;
|
TempBlockDesc++;
|
||||||
@ -530,10 +589,9 @@ IsOverlapped (
|
|||||||
refers to is.
|
refers to is.
|
||||||
|
|
||||||
@param Desc Pointer to the capsule block descriptors
|
@param Desc Pointer to the capsule block descriptors
|
||||||
NumDescriptors - optional pointer to where to return the number of descriptors
|
@param NumDescriptors Optional pointer to where to return the number of capsule data descriptors, whose Length is non-zero.
|
||||||
CapsuleSize - optional pointer to where to return the capsule size
|
@param CapsuleSize Optional pointer to where to return the capsule image size
|
||||||
@param NumDescriptors Optional pointer to where to return the number of descriptors
|
@param CapsuleNumber Optional pointer to where to return the number of capsule
|
||||||
@param CapsuleSize Optional pointer to where to return the capsule size
|
|
||||||
|
|
||||||
@retval EFI_NOT_FOUND No descriptors containing data in the list
|
@retval EFI_NOT_FOUND No descriptors containing data in the list
|
||||||
@retval EFI_SUCCESS Return data is valid
|
@retval EFI_SUCCESS Return data is valid
|
||||||
@ -543,16 +601,24 @@ EFI_STATUS
|
|||||||
GetCapsuleInfo (
|
GetCapsuleInfo (
|
||||||
IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Desc,
|
IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Desc,
|
||||||
IN OUT UINTN *NumDescriptors OPTIONAL,
|
IN OUT UINTN *NumDescriptors OPTIONAL,
|
||||||
IN OUT UINTN *CapsuleSize OPTIONAL
|
IN OUT UINTN *CapsuleSize OPTIONAL,
|
||||||
|
IN OUT UINTN *CapsuleNumber OPTIONAL
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINTN Count;
|
UINTN Count;
|
||||||
UINTN Size;
|
UINTN Size;
|
||||||
|
UINTN Number;
|
||||||
|
UINTN ThisCapsuleImageSize;
|
||||||
|
EFI_CAPSULE_HEADER *CapsuleHeader;
|
||||||
|
|
||||||
|
DEBUG ((EFI_D_INFO, "GetCapsuleInfo enter\n"));
|
||||||
|
|
||||||
ASSERT (Desc != NULL);
|
ASSERT (Desc != NULL);
|
||||||
|
|
||||||
Count = 0;
|
Count = 0;
|
||||||
Size = 0;
|
Size = 0;
|
||||||
|
Number = 0;
|
||||||
|
ThisCapsuleImageSize = 0;
|
||||||
|
|
||||||
while (Desc->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL) {
|
while (Desc->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL) {
|
||||||
if (Desc->Length == 0) {
|
if (Desc->Length == 0) {
|
||||||
@ -561,8 +627,39 @@ GetCapsuleInfo (
|
|||||||
//
|
//
|
||||||
Desc = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) Desc->Union.ContinuationPointer;
|
Desc = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) Desc->Union.ContinuationPointer;
|
||||||
} else {
|
} else {
|
||||||
|
//
|
||||||
|
// Sanity Check
|
||||||
|
// It is needed, because ValidateCapsuleIntegrity() only validate one individual capsule Size.
|
||||||
|
// While here we need check all capsules size.
|
||||||
|
//
|
||||||
|
if (Desc->Length >= (MAX_ADDRESS - Size)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "ERROR: Desc->Length(0x%lx) >= (MAX_ADDRESS - Size(0x%x))\n", Desc->Length, Size));
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
Size += (UINTN) Desc->Length;
|
Size += (UINTN) Desc->Length;
|
||||||
Count++;
|
Count++;
|
||||||
|
|
||||||
|
//
|
||||||
|
// See if this is first capsule's header
|
||||||
|
//
|
||||||
|
if (ThisCapsuleImageSize == 0) {
|
||||||
|
CapsuleHeader = (EFI_CAPSULE_HEADER*)((UINTN)Desc->Union.DataBlock);
|
||||||
|
//
|
||||||
|
// This has been checked in ValidateCapsuleIntegrity()
|
||||||
|
//
|
||||||
|
Number ++;
|
||||||
|
ThisCapsuleImageSize = CapsuleHeader->CapsuleImageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// This has been checked in ValidateCapsuleIntegrity()
|
||||||
|
//
|
||||||
|
ASSERT (ThisCapsuleImageSize >= Desc->Length);
|
||||||
|
ThisCapsuleImageSize = (UINTN)(ThisCapsuleImageSize - Desc->Length);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Move to next
|
||||||
|
//
|
||||||
Desc++;
|
Desc++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -570,9 +667,15 @@ GetCapsuleInfo (
|
|||||||
// If no descriptors, then fail
|
// If no descriptors, then fail
|
||||||
//
|
//
|
||||||
if (Count == 0) {
|
if (Count == 0) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "ERROR: Count == 0\n"));
|
||||||
return EFI_NOT_FOUND;
|
return EFI_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// checked in ValidateCapsuleIntegrity()
|
||||||
|
//
|
||||||
|
ASSERT (ThisCapsuleImageSize == 0);
|
||||||
|
|
||||||
if (NumDescriptors != NULL) {
|
if (NumDescriptors != NULL) {
|
||||||
*NumDescriptors = Count;
|
*NumDescriptors = Count;
|
||||||
}
|
}
|
||||||
@ -581,6 +684,10 @@ GetCapsuleInfo (
|
|||||||
*CapsuleSize = Size;
|
*CapsuleSize = Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CapsuleNumber != NULL) {
|
||||||
|
*CapsuleNumber = Number;
|
||||||
|
}
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -639,6 +746,9 @@ CapsuleTestPatternPreCoalesce (
|
|||||||
UINT32 *TestPtr;
|
UINT32 *TestPtr;
|
||||||
UINT32 TestCounter;
|
UINT32 TestCounter;
|
||||||
UINT32 TestSize;
|
UINT32 TestSize;
|
||||||
|
|
||||||
|
DEBUG ((EFI_D_INFO, "CapsuleTestPatternPreCoalesce\n"));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Find first data descriptor
|
// Find first data descriptor
|
||||||
//
|
//
|
||||||
@ -721,6 +831,8 @@ BuildCapsuleDescriptors (
|
|||||||
EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlock;
|
EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlock;
|
||||||
EFI_CAPSULE_BLOCK_DESCRIPTOR *HeadBlock;
|
EFI_CAPSULE_BLOCK_DESCRIPTOR *HeadBlock;
|
||||||
|
|
||||||
|
DEBUG ((EFI_D_INFO, "BuildCapsuleDescriptors enter\n"));
|
||||||
|
|
||||||
LastBlock = NULL;
|
LastBlock = NULL;
|
||||||
HeadBlock = NULL;
|
HeadBlock = NULL;
|
||||||
TempBlock = NULL;
|
TempBlock = NULL;
|
||||||
@ -730,23 +842,27 @@ BuildCapsuleDescriptors (
|
|||||||
//
|
//
|
||||||
// Test integrity of descriptors.
|
// Test integrity of descriptors.
|
||||||
//
|
//
|
||||||
TempBlock = ValidateCapsuleIntegrity ((EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)BlockListBuffer[Index]);
|
if (BlockListBuffer[Index] < MAX_ADDRESS) {
|
||||||
if (TempBlock != NULL) {
|
TempBlock = ValidateCapsuleIntegrity ((EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)BlockListBuffer[Index]);
|
||||||
if (LastBlock == NULL) {
|
if (TempBlock != NULL) {
|
||||||
LastBlock = TempBlock;
|
if (LastBlock == NULL) {
|
||||||
|
LastBlock = TempBlock;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Return the base of the block descriptors
|
// Return the base of the block descriptors
|
||||||
//
|
//
|
||||||
HeadBlock = (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)BlockListBuffer[Index];
|
HeadBlock = (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)BlockListBuffer[Index];
|
||||||
} else {
|
} else {
|
||||||
//
|
//
|
||||||
// Combine the different BlockList into single BlockList.
|
// Combine the different BlockList into single BlockList.
|
||||||
//
|
//
|
||||||
LastBlock->Union.DataBlock = (EFI_PHYSICAL_ADDRESS)(UINTN)BlockListBuffer[Index];
|
LastBlock->Union.DataBlock = (EFI_PHYSICAL_ADDRESS)(UINTN)BlockListBuffer[Index];
|
||||||
LastBlock->Length = 0;
|
LastBlock->Length = 0;
|
||||||
LastBlock = TempBlock;
|
LastBlock = TempBlock;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
DEBUG ((EFI_D_ERROR, "ERROR: BlockListBuffer[Index](0x%lx) < MAX_ADDRESS\n", BlockListBuffer[Index]));
|
||||||
}
|
}
|
||||||
Index ++;
|
Index ++;
|
||||||
}
|
}
|
||||||
@ -763,26 +879,32 @@ BuildCapsuleDescriptors (
|
|||||||
|
|
||||||
Memory Map for coalesced capsule:
|
Memory Map for coalesced capsule:
|
||||||
MemBase + ---->+---------------------------+<-----------+
|
MemBase + ---->+---------------------------+<-----------+
|
||||||
MemSize | CapsuleOffset[49] | |
|
MemSize | ------------------------- | |
|
||||||
+---------------------------+ |
|
| | Capsule [Num-1] | | |
|
||||||
| ................ | |
|
| ------------------------- | |
|
||||||
+---------------------------+ |
|
| | ................ | | |
|
||||||
| CapsuleOffset[2] | |
|
| ------------------------- | |
|
||||||
+---------------------------+ |
|
| | Capsule [1] | | |
|
||||||
| CapsuleOffset[1] | |
|
| ------------------------- | |
|
||||||
+---------------------------+ |
|
| | Capsule [0] | | |
|
||||||
| CapsuleOffset[0] | CapsuleSize
|
| ------------------------- | |
|
||||||
+---------------------------+ |
|
|
||||||
| CapsuleNumber | |
|
|
||||||
+---------------------------+ |
|
|
||||||
| | |
|
|
||||||
| | |
|
|
||||||
| Capsule Image | |
|
| Capsule Image | |
|
||||||
| | |
|
CapsuleImageBase-->+---------------------------+
|
||||||
| | |
|
| ------------------------- | |
|
||||||
+---------------------------+ |
|
| | CapsuleOffset[Num-1] | | |
|
||||||
|
| ------------------------- | |
|
||||||
|
| | ................ | | CapsuleSize
|
||||||
|
| ------------------------- | |
|
||||||
|
| | CapsuleOffset[1] | | |
|
||||||
|
| ------------------------- | |
|
||||||
|
| | CapsuleOffset[0] | | |
|
||||||
|
|---------------------------| |
|
||||||
|
| | CapsuleNumber | | |
|
||||||
|
| ------------------------- | |
|
||||||
|
| | CapsuleAllImageSize | | |
|
||||||
|
| ------------------------- | |
|
||||||
| PrivateData | |
|
| PrivateData | |
|
||||||
DestPtr ----> +---------------------------+<-----------+
|
DestPtr ---->+---------------------------+<-----------+
|
||||||
| | |
|
| | |
|
||||||
| FreeMem | FreeMemSize
|
| FreeMem | FreeMemSize
|
||||||
| | |
|
| | |
|
||||||
@ -832,21 +954,21 @@ CapsuleDataCoalesce (
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
VOID *NewCapsuleBase;
|
VOID *NewCapsuleBase;
|
||||||
VOID *DataPtr;
|
VOID *CapsuleImageBase;
|
||||||
UINT8 CapsuleIndex;
|
UINTN CapsuleIndex;
|
||||||
UINT8 *FreeMemBase;
|
UINT8 *FreeMemBase;
|
||||||
UINT8 *DestPtr;
|
UINT8 *DestPtr;
|
||||||
|
UINTN DestLength;
|
||||||
UINT8 *RelocPtr;
|
UINT8 *RelocPtr;
|
||||||
UINT32 CapsuleOffset[MAX_SUPPORT_CAPSULE_NUM];
|
UINT64 *AddDataPtr;
|
||||||
UINT32 *AddDataPtr;
|
UINTN CapsuleTimes;
|
||||||
UINT32 CapsuleTimes;
|
|
||||||
UINT64 SizeLeft;
|
UINT64 SizeLeft;
|
||||||
UINT64 CapsuleImageSize;
|
UINT64 CapsuleImageSize;
|
||||||
UINTN CapsuleSize;
|
UINTN CapsuleSize;
|
||||||
|
UINTN CapsuleNumber;
|
||||||
UINTN DescriptorsSize;
|
UINTN DescriptorsSize;
|
||||||
UINTN FreeMemSize;
|
UINTN FreeMemSize;
|
||||||
UINTN NumDescriptors;
|
UINTN NumDescriptors;
|
||||||
BOOLEAN IsCorrupted;
|
|
||||||
BOOLEAN CapsuleBeginFlag;
|
BOOLEAN CapsuleBeginFlag;
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
EFI_CAPSULE_HEADER *CapsuleHeader;
|
EFI_CAPSULE_HEADER *CapsuleHeader;
|
||||||
@ -857,6 +979,8 @@ CapsuleDataCoalesce (
|
|||||||
EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockDesc;
|
EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockDesc;
|
||||||
EFI_CAPSULE_BLOCK_DESCRIPTOR PrivateDataDesc[2];
|
EFI_CAPSULE_BLOCK_DESCRIPTOR PrivateDataDesc[2];
|
||||||
|
|
||||||
|
DEBUG ((EFI_D_INFO, "CapsuleDataCoalesce enter\n"));
|
||||||
|
|
||||||
CapsuleIndex = 0;
|
CapsuleIndex = 0;
|
||||||
SizeLeft = 0;
|
SizeLeft = 0;
|
||||||
CapsuleTimes = 0;
|
CapsuleTimes = 0;
|
||||||
@ -865,10 +989,9 @@ CapsuleDataCoalesce (
|
|||||||
AddDataPtr = NULL;
|
AddDataPtr = NULL;
|
||||||
CapsuleHeader = NULL;
|
CapsuleHeader = NULL;
|
||||||
CapsuleBeginFlag = TRUE;
|
CapsuleBeginFlag = TRUE;
|
||||||
IsCorrupted = TRUE;
|
|
||||||
CapsuleSize = 0;
|
CapsuleSize = 0;
|
||||||
NumDescriptors = 0;
|
NumDescriptors = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Build capsule descriptors list
|
// Build capsule descriptors list
|
||||||
//
|
//
|
||||||
@ -886,30 +1009,71 @@ CapsuleDataCoalesce (
|
|||||||
// returns the number of descriptors that actually point to data, so add
|
// returns the number of descriptors that actually point to data, so add
|
||||||
// one for a terminator. Do that below.
|
// one for a terminator. Do that below.
|
||||||
//
|
//
|
||||||
GetCapsuleInfo (BlockList, &NumDescriptors, &CapsuleSize);
|
Status = GetCapsuleInfo (BlockList, &NumDescriptors, &CapsuleSize, &CapsuleNumber);
|
||||||
if ((CapsuleSize == 0) || (NumDescriptors == 0)) {
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
DEBUG ((EFI_D_INFO, "CapsuleSize - 0x%x\n", CapsuleSize));
|
||||||
|
DEBUG ((EFI_D_INFO, "CapsuleNumber - 0x%x\n", CapsuleNumber));
|
||||||
|
DEBUG ((EFI_D_INFO, "NumDescriptors - 0x%x\n", NumDescriptors));
|
||||||
|
if ((CapsuleSize == 0) || (NumDescriptors == 0) || (CapsuleNumber == 0)) {
|
||||||
return EFI_NOT_FOUND;
|
return EFI_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CapsuleNumber - 1 >= (MAX_ADDRESS - (sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) + sizeof(UINT64))) / sizeof(UINT64)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "ERROR: CapsuleNumber - 0x%x\n", CapsuleNumber));
|
||||||
|
return EFI_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Initialize our local copy of private data. When we're done, we'll create a
|
// Initialize our local copy of private data. When we're done, we'll create a
|
||||||
// descriptor for it as well so that it can be put into free memory without
|
// descriptor for it as well so that it can be put into free memory without
|
||||||
// trashing anything.
|
// trashing anything.
|
||||||
//
|
//
|
||||||
PrivateData.Signature = EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE;
|
PrivateData.Signature = EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE;
|
||||||
PrivateData.CapsuleSize = (UINT32) CapsuleSize;
|
PrivateData.CapsuleAllImageSize = (UINT64) CapsuleSize;
|
||||||
|
PrivateData.CapsuleNumber = (UINT64) CapsuleNumber;
|
||||||
|
PrivateData.CapsuleOffset[0] = 0;
|
||||||
|
//
|
||||||
|
// NOTE: Only data in sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) is valid, CapsuleOffset field is unitialized at this moment.
|
||||||
|
// The code sets partial length here for Descriptor.Length check, but later it will use full length to reserve those PrivateData region.
|
||||||
|
//
|
||||||
PrivateDataDesc[0].Union.DataBlock = (EFI_PHYSICAL_ADDRESS) (UINTN) &PrivateData;
|
PrivateDataDesc[0].Union.DataBlock = (EFI_PHYSICAL_ADDRESS) (UINTN) &PrivateData;
|
||||||
PrivateDataDesc[0].Length = sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA);
|
PrivateDataDesc[0].Length = sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA);
|
||||||
PrivateDataDesc[1].Union.DataBlock = (EFI_PHYSICAL_ADDRESS) (UINTN) BlockList;
|
PrivateDataDesc[1].Union.DataBlock = (EFI_PHYSICAL_ADDRESS) (UINTN) BlockList;
|
||||||
PrivateDataDesc[1].Length = 0;
|
PrivateDataDesc[1].Length = 0;
|
||||||
//
|
//
|
||||||
// In addition to PrivateDataDesc[1:0], one terminator is added
|
// Add PrivateDataDesc[0] in beginning beginning, as it is new descriptor. PrivateDataDesc[1] is NOT needed.
|
||||||
// See below RelocateBlockDescriptors()
|
// In addition, one NULL terminator is added in the end. See RelocateBlockDescriptors().
|
||||||
//
|
//
|
||||||
NumDescriptors += 3;
|
NumDescriptors += 2;
|
||||||
CapsuleSize += sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) + sizeof(CapsuleOffset) + sizeof(UINT32);
|
//
|
||||||
|
// Sandity check
|
||||||
|
//
|
||||||
|
if (CapsuleSize >= (MAX_ADDRESS - (sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64) + sizeof(UINT64)))) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "ERROR: CapsuleSize - 0x%x\n", CapsuleSize));
|
||||||
|
return EFI_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Need add sizeof(UINT64) for PrivateData alignment
|
||||||
|
//
|
||||||
|
CapsuleSize += sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64) + sizeof(UINT64);
|
||||||
BlockList = PrivateDataDesc;
|
BlockList = PrivateDataDesc;
|
||||||
|
//
|
||||||
|
// Sandity check
|
||||||
|
//
|
||||||
|
if (NumDescriptors >= (MAX_ADDRESS / sizeof(EFI_CAPSULE_BLOCK_DESCRIPTOR))) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "ERROR: NumDescriptors - 0x%x\n", NumDescriptors));
|
||||||
|
return EFI_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
DescriptorsSize = NumDescriptors * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
|
DescriptorsSize = NumDescriptors * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
|
||||||
|
//
|
||||||
|
// Sandity check
|
||||||
|
//
|
||||||
|
if (DescriptorsSize >= (MAX_ADDRESS - CapsuleSize)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "ERROR: DescriptorsSize - 0x%lx, CapsuleSize - 0x%lx\n", (UINT64)DescriptorsSize, (UINT64)CapsuleSize));
|
||||||
|
return EFI_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Don't go below some min address. If the base is below it,
|
// Don't go below some min address. If the base is below it,
|
||||||
@ -918,6 +1082,7 @@ CapsuleDataCoalesce (
|
|||||||
DEBUG ((EFI_D_INFO, "Capsule Memory range from 0x%8X to 0x%8X\n", (UINTN) *MemoryBase, (UINTN)*MemoryBase + *MemorySize));
|
DEBUG ((EFI_D_INFO, "Capsule Memory range from 0x%8X to 0x%8X\n", (UINTN) *MemoryBase, (UINTN)*MemoryBase + *MemorySize));
|
||||||
if ((UINTN)*MemoryBase < (UINTN) MIN_COALESCE_ADDR) {
|
if ((UINTN)*MemoryBase < (UINTN) MIN_COALESCE_ADDR) {
|
||||||
if (((UINTN)*MemoryBase + *MemorySize) < (UINTN) MIN_COALESCE_ADDR) {
|
if (((UINTN)*MemoryBase + *MemorySize) < (UINTN) MIN_COALESCE_ADDR) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "ERROR: *MemoryBase + *MemorySize - 0x%x\n", (UINTN)*MemoryBase + *MemorySize));
|
||||||
return EFI_BUFFER_TOO_SMALL;
|
return EFI_BUFFER_TOO_SMALL;
|
||||||
} else {
|
} else {
|
||||||
*MemorySize = *MemorySize - ((UINTN) MIN_COALESCE_ADDR - (UINTN) *MemoryBase);
|
*MemorySize = *MemorySize - ((UINTN) MIN_COALESCE_ADDR - (UINTN) *MemoryBase);
|
||||||
@ -926,6 +1091,7 @@ CapsuleDataCoalesce (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (*MemorySize <= (CapsuleSize + DescriptorsSize)) {
|
if (*MemorySize <= (CapsuleSize + DescriptorsSize)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "ERROR: CapsuleSize + DescriptorsSize - 0x%x\n", CapsuleSize + DescriptorsSize));
|
||||||
return EFI_BUFFER_TOO_SMALL;
|
return EFI_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -937,7 +1103,7 @@ CapsuleDataCoalesce (
|
|||||||
// Relocate all the block descriptors to low memory to make further
|
// Relocate all the block descriptors to low memory to make further
|
||||||
// processing easier.
|
// processing easier.
|
||||||
//
|
//
|
||||||
BlockList = RelocateBlockDescriptors (PeiServices, BlockList, FreeMemBase, FreeMemSize);
|
BlockList = RelocateBlockDescriptors (PeiServices, BlockList, NumDescriptors, FreeMemBase, FreeMemSize);
|
||||||
if (BlockList == NULL) {
|
if (BlockList == NULL) {
|
||||||
//
|
//
|
||||||
// Not enough room to relocate the descriptors
|
// Not enough room to relocate the descriptors
|
||||||
@ -946,13 +1112,16 @@ CapsuleDataCoalesce (
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Take the top of memory for the capsule. Naturally align.
|
// Take the top of memory for the capsule. UINT64 align up.
|
||||||
//
|
//
|
||||||
DestPtr = FreeMemBase + FreeMemSize - CapsuleSize;
|
DestPtr = FreeMemBase + FreeMemSize - CapsuleSize;
|
||||||
DestPtr = (UINT8 *) ((UINTN) DestPtr &~ (UINTN) (sizeof (UINTN) - 1));
|
DestPtr = (UINT8 *) (((UINTN)DestPtr + sizeof (UINT64) - 1) & ~(sizeof (UINT64) - 1));
|
||||||
FreeMemBase = (UINT8 *) BlockList + DescriptorsSize;
|
FreeMemBase = (UINT8 *) BlockList + DescriptorsSize;
|
||||||
FreeMemSize = (UINTN) DestPtr - (UINTN) FreeMemBase;
|
FreeMemSize = (UINTN) DestPtr - (UINTN) FreeMemBase;
|
||||||
NewCapsuleBase = (VOID *) DestPtr;
|
NewCapsuleBase = (VOID *) DestPtr;
|
||||||
|
CapsuleImageBase = (UINT8 *)NewCapsuleBase + sizeof(EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64);
|
||||||
|
|
||||||
|
PrivateDataPtr = (EFI_CAPSULE_PEIM_PRIVATE_DATA *) NewCapsuleBase;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Move all the blocks to the top (high) of memory.
|
// Move all the blocks to the top (high) of memory.
|
||||||
@ -961,6 +1130,16 @@ CapsuleDataCoalesce (
|
|||||||
//
|
//
|
||||||
CurrentBlockDesc = BlockList;
|
CurrentBlockDesc = BlockList;
|
||||||
while ((CurrentBlockDesc->Length != 0) || (CurrentBlockDesc->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
|
while ((CurrentBlockDesc->Length != 0) || (CurrentBlockDesc->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
|
||||||
|
if (CapsuleTimes == 0) {
|
||||||
|
//
|
||||||
|
// The first entry is the block descriptor for EFI_CAPSULE_PEIM_PRIVATE_DATA.
|
||||||
|
// CapsuleOffset field is uninitialized at this time. No need copy it, but need to reserve for future use.
|
||||||
|
//
|
||||||
|
ASSERT (CurrentBlockDesc->Union.DataBlock == (UINT64)(UINTN)&PrivateData);
|
||||||
|
DestLength = sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64);
|
||||||
|
} else {
|
||||||
|
DestLength = (UINTN)CurrentBlockDesc->Length;
|
||||||
|
}
|
||||||
//
|
//
|
||||||
// See if any of the remaining capsule blocks are in the way
|
// See if any of the remaining capsule blocks are in the way
|
||||||
//
|
//
|
||||||
@ -971,7 +1150,7 @@ CapsuleDataCoalesce (
|
|||||||
//
|
//
|
||||||
if (IsOverlapped (
|
if (IsOverlapped (
|
||||||
(UINT8 *) DestPtr,
|
(UINT8 *) DestPtr,
|
||||||
(UINTN) CurrentBlockDesc->Length,
|
(UINTN) DestLength,
|
||||||
(UINT8 *) (UINTN) TempBlockDesc->Union.DataBlock,
|
(UINT8 *) (UINTN) TempBlockDesc->Union.DataBlock,
|
||||||
(UINTN) TempBlockDesc->Length
|
(UINTN) TempBlockDesc->Length
|
||||||
)) {
|
)) {
|
||||||
@ -1011,56 +1190,50 @@ CapsuleDataCoalesce (
|
|||||||
CapsuleBeginFlag = FALSE;
|
CapsuleBeginFlag = FALSE;
|
||||||
CapsuleHeader = (EFI_CAPSULE_HEADER*)(UINTN)CurrentBlockDesc->Union.DataBlock;
|
CapsuleHeader = (EFI_CAPSULE_HEADER*)(UINTN)CurrentBlockDesc->Union.DataBlock;
|
||||||
SizeLeft = CapsuleHeader->CapsuleImageSize;
|
SizeLeft = CapsuleHeader->CapsuleImageSize;
|
||||||
if (!IsCapsuleCorrupted (CapsuleHeader)) {
|
|
||||||
|
|
||||||
if (CapsuleIndex > (MAX_SUPPORT_CAPSULE_NUM - 1)) {
|
//
|
||||||
DEBUG ((EFI_D_ERROR, "Capsule number exceeds the max number of %d!\n", MAX_SUPPORT_CAPSULE_NUM));
|
// No more check here is needed, because IsCapsuleCorrupted() already in ValidateCapsuleIntegrity()
|
||||||
return EFI_BUFFER_TOO_SMALL;
|
//
|
||||||
}
|
ASSERT (CapsuleIndex < CapsuleNumber);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Relocate this valid capsule
|
// Relocate this capsule
|
||||||
//
|
//
|
||||||
IsCorrupted = FALSE;
|
CapsuleImageSize += SizeLeft;
|
||||||
CapsuleImageSize += SizeLeft;
|
//
|
||||||
//
|
// Cache the begin offset of this capsule
|
||||||
// Cache the begin offset of this capsule
|
//
|
||||||
//
|
ASSERT (PrivateDataPtr->Signature == EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE);
|
||||||
CapsuleOffset[CapsuleIndex++] = (UINT32) (UINTN) DestPtr - (UINT32)(UINTN)NewCapsuleBase - (UINT32)sizeof(EFI_CAPSULE_PEIM_PRIVATE_DATA);
|
ASSERT ((UINTN)DestPtr >= (UINTN)CapsuleImageBase);
|
||||||
}
|
PrivateDataPtr->CapsuleOffset[CapsuleIndex++] = (UINT64)((UINTN)DestPtr - (UINTN)CapsuleImageBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CurrentBlockDesc->Length < SizeLeft) {
|
//
|
||||||
if (!IsCorrupted) {
|
// Below ASSERT is checked in ValidateCapsuleIntegrity()
|
||||||
CopyMem ((VOID *) DestPtr, (VOID *) (UINTN) (CurrentBlockDesc->Union.DataBlock), (UINTN)CurrentBlockDesc->Length);
|
//
|
||||||
DEBUG ((EFI_D_INFO, "Capsule coalesce block no.0x%8X from 0x%8lX to 0x%8lX with size 0x%8X\n",CapsuleTimes,
|
ASSERT (CurrentBlockDesc->Length <= SizeLeft);
|
||||||
(UINTN)CurrentBlockDesc->Union.DataBlock, (UINTN)DestPtr, (UINTN)CurrentBlockDesc->Length));
|
|
||||||
DestPtr += CurrentBlockDesc->Length;
|
CopyMem ((VOID *) DestPtr, (VOID *) (UINTN) (CurrentBlockDesc->Union.DataBlock), (UINTN)CurrentBlockDesc->Length);
|
||||||
}
|
DEBUG ((EFI_D_INFO, "Capsule coalesce block no.0x%lX from 0x%lX to 0x%lX with size 0x%lX\n",(UINT64)CapsuleTimes,
|
||||||
SizeLeft -= CurrentBlockDesc->Length;
|
CurrentBlockDesc->Union.DataBlock, (UINT64)(UINTN)DestPtr, CurrentBlockDesc->Length));
|
||||||
} else {
|
DestPtr += CurrentBlockDesc->Length;
|
||||||
|
SizeLeft -= CurrentBlockDesc->Length;
|
||||||
|
|
||||||
|
if (SizeLeft == 0) {
|
||||||
//
|
//
|
||||||
//Here is the end of the current capsule image.
|
//Here is the end of the current capsule image.
|
||||||
//
|
//
|
||||||
if (!IsCorrupted) {
|
|
||||||
CopyMem ((VOID *) DestPtr, (VOID *)(UINTN)(CurrentBlockDesc->Union.DataBlock), (UINTN) SizeLeft);
|
|
||||||
DEBUG ((EFI_D_INFO, "Capsule coalesce block no.0x%8X from 0x%8lX to 0x%8lX with size 0x%8X\n",CapsuleTimes,
|
|
||||||
(UINTN)CurrentBlockDesc->Union.DataBlock, (UINTN)DestPtr, (UINTN) SizeLeft));
|
|
||||||
DestPtr += SizeLeft;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// Start the next cycle
|
|
||||||
//
|
|
||||||
SizeLeft = 0;
|
|
||||||
IsCorrupted = TRUE;
|
|
||||||
CapsuleBeginFlag = TRUE;
|
CapsuleBeginFlag = TRUE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//
|
//
|
||||||
//The first entry is the block descriptor for EFI_CAPSULE_PEIM_PRIVATE_DATA.
|
// The first entry is the block descriptor for EFI_CAPSULE_PEIM_PRIVATE_DATA.
|
||||||
|
// CapsuleOffset field is uninitialized at this time. No need copy it, but need to reserve for future use.
|
||||||
//
|
//
|
||||||
|
ASSERT (CurrentBlockDesc->Length == sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA));
|
||||||
|
ASSERT ((UINTN)DestPtr == (UINTN)NewCapsuleBase);
|
||||||
CopyMem ((VOID *) DestPtr, (VOID *) (UINTN) CurrentBlockDesc->Union.DataBlock, (UINTN) CurrentBlockDesc->Length);
|
CopyMem ((VOID *) DestPtr, (VOID *) (UINTN) CurrentBlockDesc->Union.DataBlock, (UINTN) CurrentBlockDesc->Length);
|
||||||
DestPtr += CurrentBlockDesc->Length;
|
DestPtr += sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
//Walk through the block descriptor list.
|
//Walk through the block descriptor list.
|
||||||
@ -1074,18 +1247,9 @@ CapsuleDataCoalesce (
|
|||||||
*MemorySize = (UINTN) CapsuleSize;
|
*MemorySize = (UINTN) CapsuleSize;
|
||||||
*MemoryBase = (VOID *) NewCapsuleBase;
|
*MemoryBase = (VOID *) NewCapsuleBase;
|
||||||
|
|
||||||
//
|
ASSERT (PrivateDataPtr->Signature == EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE);
|
||||||
//Append the offsets of mutiply capsules to the continous buffer
|
ASSERT (PrivateDataPtr->CapsuleAllImageSize == CapsuleImageSize);
|
||||||
//
|
ASSERT (PrivateDataPtr->CapsuleNumber == CapsuleIndex);
|
||||||
DataPtr = (VOID*)((UINTN)NewCapsuleBase + sizeof(EFI_CAPSULE_PEIM_PRIVATE_DATA) + (UINTN)CapsuleImageSize);
|
|
||||||
AddDataPtr = (UINT32*)(((UINTN) DataPtr + sizeof(UINT32) - 1) &~ (UINT32) (sizeof (UINT32) - 1));
|
|
||||||
|
|
||||||
*AddDataPtr++ = CapsuleIndex;
|
|
||||||
|
|
||||||
CopyMem (AddDataPtr, &CapsuleOffset[0], sizeof (UINT32) * CapsuleIndex);
|
|
||||||
|
|
||||||
PrivateDataPtr = (EFI_CAPSULE_PEIM_PRIVATE_DATA *) NewCapsuleBase;
|
|
||||||
PrivateDataPtr->CapsuleSize = (UINT32) CapsuleImageSize;
|
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/** @file
|
/** @file
|
||||||
Common header file.
|
Common header file.
|
||||||
|
|
||||||
Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -19,12 +19,16 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
// This capsule PEIM puts its private data at the start of the
|
// This capsule PEIM puts its private data at the start of the
|
||||||
// coalesced capsule. Here's the structure definition.
|
// coalesced capsule. Here's the structure definition.
|
||||||
//
|
//
|
||||||
#define EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('C', 'a', 'p', 'D')
|
#define EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('C', 'a', 'p', 'P')
|
||||||
|
|
||||||
|
#pragma pack(1)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
UINT32 Signature;
|
UINT64 Signature;
|
||||||
UINTN CapsuleSize;
|
UINT64 CapsuleAllImageSize;
|
||||||
|
UINT64 CapsuleNumber;
|
||||||
|
UINT64 CapsuleOffset[1];
|
||||||
} EFI_CAPSULE_PEIM_PRIVATE_DATA;
|
} EFI_CAPSULE_PEIM_PRIVATE_DATA;
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
#define CAPSULE_TEST_SIGNATURE SIGNATURE_32('T', 'E', 'S', 'T')
|
#define CAPSULE_TEST_SIGNATURE SIGNATURE_32('T', 'E', 'S', 'T')
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/** @file
|
/** @file
|
||||||
Capsule update PEIM for UEFI2.0
|
Capsule update PEIM for UEFI2.0
|
||||||
|
|
||||||
Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions
|
are licensed and made available under the terms and conditions
|
||||||
@ -987,25 +987,28 @@ CreateState (
|
|||||||
EFI_CAPSULE_PEIM_PRIVATE_DATA *PrivateData;
|
EFI_CAPSULE_PEIM_PRIVATE_DATA *PrivateData;
|
||||||
UINTN Size;
|
UINTN Size;
|
||||||
EFI_PHYSICAL_ADDRESS NewBuffer;
|
EFI_PHYSICAL_ADDRESS NewBuffer;
|
||||||
UINT32 *DataPtr;
|
UINTN CapsuleNumber;
|
||||||
UINT32 CapsuleNumber;
|
|
||||||
UINT32 Index;
|
UINT32 Index;
|
||||||
EFI_PHYSICAL_ADDRESS BaseAddress;
|
EFI_PHYSICAL_ADDRESS BaseAddress;
|
||||||
UINT64 Length;
|
UINT64 Length;
|
||||||
|
|
||||||
DataPtr = NULL;
|
|
||||||
CapsuleNumber = 0;
|
|
||||||
PrivateData = (EFI_CAPSULE_PEIM_PRIVATE_DATA *) CapsuleBase;
|
PrivateData = (EFI_CAPSULE_PEIM_PRIVATE_DATA *) CapsuleBase;
|
||||||
if (PrivateData->Signature != EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE) {
|
if (PrivateData->Signature != EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE) {
|
||||||
return EFI_VOLUME_CORRUPTED;
|
return EFI_VOLUME_CORRUPTED;
|
||||||
}
|
}
|
||||||
|
if (PrivateData->CapsuleAllImageSize >= MAX_ADDRESS) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "CapsuleAllImageSize too big - 0x%lx\n", PrivateData->CapsuleAllImageSize));
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
if (PrivateData->CapsuleNumber >= MAX_ADDRESS) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "CapsuleNumber too big - 0x%lx\n", PrivateData->CapsuleNumber));
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
//
|
//
|
||||||
// Capsule Number and Capsule Offset is in the tail of Capsule data.
|
// Capsule Number and Capsule Offset is in the tail of Capsule data.
|
||||||
//
|
//
|
||||||
Size = (UINTN) PrivateData->CapsuleSize;
|
Size = (UINTN)PrivateData->CapsuleAllImageSize;
|
||||||
DataPtr = (UINT32*)((UINTN)CapsuleBase + (UINTN)sizeof(EFI_CAPSULE_PEIM_PRIVATE_DATA)+ Size);
|
CapsuleNumber = (UINTN)PrivateData->CapsuleNumber;
|
||||||
DataPtr = (UINT32*)(((UINTN) DataPtr + sizeof(UINT32) - 1) & ~(sizeof (UINT32) - 1));
|
|
||||||
CapsuleNumber = *DataPtr++;
|
|
||||||
//
|
//
|
||||||
// Allocate the memory so that it gets preserved into DXE
|
// Allocate the memory so that it gets preserved into DXE
|
||||||
//
|
//
|
||||||
@ -1022,8 +1025,8 @@ CreateState (
|
|||||||
//
|
//
|
||||||
// Copy to our new buffer for DXE
|
// Copy to our new buffer for DXE
|
||||||
//
|
//
|
||||||
DEBUG ((EFI_D_INFO, "Capsule copy from 0x%8X to 0x%8X with size 0x%8X\n", (UINTN) (PrivateData + 1), (UINTN) NewBuffer, Size));
|
DEBUG ((EFI_D_INFO, "Capsule copy from 0x%8X to 0x%8X with size 0x%8X\n", (UINTN)((UINT8 *)PrivateData + sizeof(EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64)), (UINTN) NewBuffer, Size));
|
||||||
CopyMem ((VOID *) (UINTN) NewBuffer, (VOID *) (UINTN) (PrivateData + 1), Size);
|
CopyMem ((VOID *) (UINTN) NewBuffer, (VOID *) (UINTN) ((UINT8 *)PrivateData + sizeof(EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64)), Size);
|
||||||
//
|
//
|
||||||
// Check for test data pattern. If it is the test pattern, then we'll
|
// Check for test data pattern. If it is the test pattern, then we'll
|
||||||
// test it ans still create the HOB so that it can be used to verify
|
// test it ans still create the HOB so that it can be used to verify
|
||||||
@ -1039,7 +1042,7 @@ CreateState (
|
|||||||
// Build the UEFI Capsule Hob for each capsule image.
|
// Build the UEFI Capsule Hob for each capsule image.
|
||||||
//
|
//
|
||||||
for (Index = 0; Index < CapsuleNumber; Index ++) {
|
for (Index = 0; Index < CapsuleNumber; Index ++) {
|
||||||
BaseAddress = NewBuffer + DataPtr[Index];
|
BaseAddress = NewBuffer + PrivateData->CapsuleOffset[Index];
|
||||||
Length = ((EFI_CAPSULE_HEADER *)((UINTN) BaseAddress))->CapsuleImageSize;
|
Length = ((EFI_CAPSULE_HEADER *)((UINTN) BaseAddress))->CapsuleImageSize;
|
||||||
|
|
||||||
BuildCvHob (BaseAddress, Length);
|
BuildCvHob (BaseAddress, Length);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user