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:
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user