MdeModulePkg CapsulePei: Validate capsule integrity by memory resource hob

Cc: Jiewen Yao <jiewen.yao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
This commit is contained in:
Star Zeng
2016-04-26 12:52:42 +08:00
parent ed3ff1acb4
commit 359cb1a3b9
6 changed files with 241 additions and 48 deletions

View File

@@ -59,20 +59,6 @@ FindFreeMem (
UINTN DataSize
);
/**
Check the integrity of the capsule descriptors.
@param BlockList Pointer to the capsule descriptors
@retval NULL BlockList is not valid.
@retval LastBlockDesc Last one Block in BlockList
**/
EFI_CAPSULE_BLOCK_DESCRIPTOR *
ValidateCapsuleIntegrity (
IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList
);
/**
The capsule block descriptors may be fragmented and spread all over memory.
To simplify the coalescing of capsule blocks, first coalesce all the
@@ -247,10 +233,69 @@ FindFreeMem (
return MemBase;
}
/**
Validate capsule by MemoryResource.
@param MemoryResource Pointer to the buffer of memory resource descriptor.
@param Address Address to be validated.
@param Size Size to be validated.
@retval TRUE No memory resource descriptor reported in HOB list before capsule Coalesce,
or it is valid in one MemoryResource.
FALSE It is not in any MemoryResource.
**/
BOOLEAN
ValidateCapsuleByMemoryResource (
IN MEMORY_RESOURCE_DESCRIPTOR *MemoryResource,
IN EFI_PHYSICAL_ADDRESS Address,
IN UINT64 Size
)
{
UINTN Index;
//
// Sanity Check
//
if (Size > MAX_ADDRESS) {
DEBUG ((EFI_D_ERROR, "ERROR: Size(0x%lx) > MAX_ADDRESS\n", Size));
return FALSE;
}
//
// Sanity Check
//
if (Address > (MAX_ADDRESS - Size)) {
DEBUG ((EFI_D_ERROR, "ERROR: Address(0x%lx) > (MAX_ADDRESS - Size(0x%lx))\n", Address, Size));
return FALSE;
}
if (MemoryResource == NULL) {
//
// No memory resource descriptor reported in HOB list before capsule Coalesce.
//
return TRUE;
}
for (Index = 0; MemoryResource[Index].ResourceLength != 0; Index++) {
if ((Address >= MemoryResource[Index].PhysicalStart) &&
((Address + Size) <= (MemoryResource[Index].PhysicalStart + MemoryResource[Index].ResourceLength))) {
DEBUG ((EFI_D_INFO, "Address(0x%lx) Size(0x%lx) in MemoryResource[0x%x] - Start(0x%lx) Length(0x%lx)\n",
Address, Size,
Index, MemoryResource[Index].PhysicalStart, MemoryResource[Index].ResourceLength));
return TRUE;
}
}
DEBUG ((EFI_D_ERROR, "ERROR: Address(0x%lx) Size(0x%lx) not in any MemoryResource\n", Address, Size));
return FALSE;
}
/**
Check the integrity of the capsule descriptors.
@param BlockList Pointer to the capsule descriptors
@param BlockList Pointer to the capsule descriptors
@param MemoryResource Pointer to the buffer of memory resource descriptor.
@retval NULL BlockList is not valid.
@retval LastBlockDesc Last one Block in BlockList
@@ -258,7 +303,8 @@ FindFreeMem (
**/
EFI_CAPSULE_BLOCK_DESCRIPTOR *
ValidateCapsuleIntegrity (
IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList
IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList,
IN MEMORY_RESOURCE_DESCRIPTOR *MemoryResource
)
{
EFI_CAPSULE_HEADER *CapsuleHeader;
@@ -274,14 +320,19 @@ ValidateCapsuleIntegrity (
// * The first capsule header guid
// * The first capsule header flag
// * The first capsule header HeaderSize
// * Length > MAX_ADDRESS
// * ContinuationPointer > MAX_ADDRESS
// * DataBlock + Length > MAX_ADDRESS
// * Below check will be done in ValidateCapsuleByMemoryResource()
// Length > MAX_ADDRESS
// Ptr + sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR) > MAX_ADDRESS
// DataBlock + Length > MAX_ADDRESS
//
CapsuleSize = 0;
CapsuleCount = 0;
Ptr = BlockList;
if (!ValidateCapsuleByMemoryResource (MemoryResource, (EFI_PHYSICAL_ADDRESS) (UINTN) Ptr, sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR))) {
return NULL;
}
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));
@@ -293,36 +344,21 @@ ValidateCapsuleIntegrity (
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;
}
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
// else.
//
Ptr = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) Ptr->Union.ContinuationPointer;
if (!ValidateCapsuleByMemoryResource (MemoryResource, (EFI_PHYSICAL_ADDRESS) (UINTN) Ptr, sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR))) {
return NULL;
}
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 {
//
// 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));
if (!ValidateCapsuleByMemoryResource (MemoryResource, Ptr->Union.DataBlock, Ptr->Length)) {
return NULL;
}
@@ -370,6 +406,9 @@ ValidateCapsuleIntegrity (
// Move to next BLOCK descriptor
//
Ptr++;
if (!ValidateCapsuleByMemoryResource (MemoryResource, (EFI_PHYSICAL_ADDRESS) (UINTN) Ptr, sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR))) {
return NULL;
}
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));
@@ -816,6 +855,7 @@ CapsuleTestPatternPreCoalesce (
Get capsule descriptors from variable CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
@param BlockListBuffer Pointer to the buffer of capsule descriptors variables
@param MemoryResource Pointer to the buffer of memory resource descriptor.
@param BlockDescriptorList Pointer to the capsule descriptors list
@retval EFI_SUCCESS a valid capsule is present
@@ -824,6 +864,7 @@ CapsuleTestPatternPreCoalesce (
EFI_STATUS
BuildCapsuleDescriptors (
IN EFI_PHYSICAL_ADDRESS *BlockListBuffer,
IN MEMORY_RESOURCE_DESCRIPTOR *MemoryResource,
OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptorList
)
{
@@ -844,7 +885,7 @@ BuildCapsuleDescriptors (
// Test integrity of descriptors.
//
if (BlockListBuffer[Index] < MAX_ADDRESS) {
TempBlock = ValidateCapsuleIntegrity ((EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)BlockListBuffer[Index]);
TempBlock = ValidateCapsuleIntegrity ((EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)BlockListBuffer[Index], MemoryResource);
if (TempBlock != NULL) {
if (LastBlock == NULL) {
LastBlock = TempBlock;
@@ -928,7 +969,8 @@ CapsuleImageBase-->+---------------------------+
coalesce capsule data into memory.
@param PeiServices General purpose services available to every PEIM.
@param BlockListBuffer Point to the buffer of Capsule Descriptor Variables.
@param BlockListBuffer Pointer to the buffer of Capsule Descriptor Variables.
@param MemoryResource Pointer to the buffer of memory resource descriptor.
@param MemoryBase Pointer to the base of a block of memory that we can walk
all over while trying to coalesce our buffers.
On output, this variable will hold the base address of
@@ -950,6 +992,7 @@ EFIAPI
CapsuleDataCoalesce (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PHYSICAL_ADDRESS *BlockListBuffer,
IN MEMORY_RESOURCE_DESCRIPTOR *MemoryResource,
IN OUT VOID **MemoryBase,
IN OUT UINTN *MemorySize
)
@@ -994,7 +1037,7 @@ CapsuleDataCoalesce (
//
// Build capsule descriptors list
//
Status = BuildCapsuleDescriptors (BlockListBuffer, &BlockList);
Status = BuildCapsuleDescriptors (BlockListBuffer, MemoryResource, &BlockList);
if (EFI_ERROR (Status)) {
return Status;
}