mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-25 22:54:51 +02:00
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:
parent
ed3ff1acb4
commit
359cb1a3b9
@ -24,6 +24,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#include <Ppi/ReadOnlyVariable2.h>
|
#include <Ppi/ReadOnlyVariable2.h>
|
||||||
#include <Guid/CapsuleVendor.h>
|
#include <Guid/CapsuleVendor.h>
|
||||||
|
|
||||||
|
#include <Library/BaseLib.h>
|
||||||
#include <Library/DebugLib.h>
|
#include <Library/DebugLib.h>
|
||||||
#include <Library/PeimEntryPoint.h>
|
#include <Library/PeimEntryPoint.h>
|
||||||
#include <Library/PeiServicesLib.h>
|
#include <Library/PeiServicesLib.h>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
# This external input must be validated carefully to avoid security issue like
|
# This external input must be validated carefully to avoid security issue like
|
||||||
# buffer overflow, integer overflow.
|
# buffer overflow, integer overflow.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
|
# Copyright (c) 2006 - 2016, 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
|
||||||
@ -46,6 +46,7 @@
|
|||||||
|
|
||||||
|
|
||||||
[LibraryClasses]
|
[LibraryClasses]
|
||||||
|
BaseLib
|
||||||
HobLib
|
HobLib
|
||||||
BaseMemoryLib
|
BaseMemoryLib
|
||||||
PeiServicesLib
|
PeiServicesLib
|
||||||
|
@ -59,20 +59,6 @@ FindFreeMem (
|
|||||||
UINTN DataSize
|
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.
|
The capsule block descriptors may be fragmented and spread all over memory.
|
||||||
To simplify the coalescing of capsule blocks, first coalesce all the
|
To simplify the coalescing of capsule blocks, first coalesce all the
|
||||||
@ -247,10 +233,69 @@ FindFreeMem (
|
|||||||
return MemBase;
|
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.
|
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 NULL BlockList is not valid.
|
||||||
@retval LastBlockDesc Last one Block in BlockList
|
@retval LastBlockDesc Last one Block in BlockList
|
||||||
@ -258,7 +303,8 @@ FindFreeMem (
|
|||||||
**/
|
**/
|
||||||
EFI_CAPSULE_BLOCK_DESCRIPTOR *
|
EFI_CAPSULE_BLOCK_DESCRIPTOR *
|
||||||
ValidateCapsuleIntegrity (
|
ValidateCapsuleIntegrity (
|
||||||
IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList
|
IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList,
|
||||||
|
IN MEMORY_RESOURCE_DESCRIPTOR *MemoryResource
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_CAPSULE_HEADER *CapsuleHeader;
|
EFI_CAPSULE_HEADER *CapsuleHeader;
|
||||||
@ -274,14 +320,19 @@ ValidateCapsuleIntegrity (
|
|||||||
// * The first capsule header guid
|
// * The first capsule header guid
|
||||||
// * The first capsule header flag
|
// * The first capsule header flag
|
||||||
// * The first capsule header HeaderSize
|
// * The first capsule header HeaderSize
|
||||||
// * Length > MAX_ADDRESS
|
// * Below check will be done in ValidateCapsuleByMemoryResource()
|
||||||
// * ContinuationPointer > MAX_ADDRESS
|
// Length > MAX_ADDRESS
|
||||||
// * DataBlock + Length > MAX_ADDRESS
|
// Ptr + sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR) > MAX_ADDRESS
|
||||||
|
// DataBlock + Length > MAX_ADDRESS
|
||||||
//
|
//
|
||||||
CapsuleSize = 0;
|
CapsuleSize = 0;
|
||||||
CapsuleCount = 0;
|
CapsuleCount = 0;
|
||||||
Ptr = BlockList;
|
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 - 0x%x\n", Ptr));
|
||||||
DEBUG ((EFI_D_INFO, "Ptr->Length - 0x%x\n", Ptr->Length));
|
DEBUG ((EFI_D_INFO, "Ptr->Length - 0x%x\n", Ptr->Length));
|
||||||
DEBUG ((EFI_D_INFO, "Ptr->Union - 0x%x\n", Ptr->Union.ContinuationPointer));
|
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"));
|
DEBUG ((EFI_D_ERROR, "ERROR: BlockList address failed alignment check\n"));
|
||||||
return NULL;
|
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) {
|
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;
|
||||||
|
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(C) - 0x%x\n", Ptr));
|
||||||
DEBUG ((EFI_D_INFO, "Ptr->Length - 0x%x\n", Ptr->Length));
|
DEBUG ((EFI_D_INFO, "Ptr->Length - 0x%x\n", Ptr->Length));
|
||||||
DEBUG ((EFI_D_INFO, "Ptr->Union - 0x%x\n", Ptr->Union.ContinuationPointer));
|
DEBUG ((EFI_D_INFO, "Ptr->Union - 0x%x\n", Ptr->Union.ContinuationPointer));
|
||||||
} else {
|
} else {
|
||||||
//
|
if (!ValidateCapsuleByMemoryResource (MemoryResource, Ptr->Union.DataBlock, Ptr->Length)) {
|
||||||
// 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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,6 +406,9 @@ ValidateCapsuleIntegrity (
|
|||||||
// Move to next BLOCK descriptor
|
// Move to next BLOCK descriptor
|
||||||
//
|
//
|
||||||
Ptr++;
|
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(B) - 0x%x\n", Ptr));
|
||||||
DEBUG ((EFI_D_INFO, "Ptr->Length - 0x%x\n", Ptr->Length));
|
DEBUG ((EFI_D_INFO, "Ptr->Length - 0x%x\n", Ptr->Length));
|
||||||
DEBUG ((EFI_D_INFO, "Ptr->Union - 0x%x\n", Ptr->Union.ContinuationPointer));
|
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...
|
Get capsule descriptors from variable CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
|
||||||
|
|
||||||
@param BlockListBuffer Pointer to the buffer of capsule descriptors variables
|
@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
|
@param BlockDescriptorList Pointer to the capsule descriptors list
|
||||||
|
|
||||||
@retval EFI_SUCCESS a valid capsule is present
|
@retval EFI_SUCCESS a valid capsule is present
|
||||||
@ -824,6 +864,7 @@ CapsuleTestPatternPreCoalesce (
|
|||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BuildCapsuleDescriptors (
|
BuildCapsuleDescriptors (
|
||||||
IN EFI_PHYSICAL_ADDRESS *BlockListBuffer,
|
IN EFI_PHYSICAL_ADDRESS *BlockListBuffer,
|
||||||
|
IN MEMORY_RESOURCE_DESCRIPTOR *MemoryResource,
|
||||||
OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptorList
|
OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptorList
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -844,7 +885,7 @@ BuildCapsuleDescriptors (
|
|||||||
// Test integrity of descriptors.
|
// Test integrity of descriptors.
|
||||||
//
|
//
|
||||||
if (BlockListBuffer[Index] < MAX_ADDRESS) {
|
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 (TempBlock != NULL) {
|
||||||
if (LastBlock == NULL) {
|
if (LastBlock == NULL) {
|
||||||
LastBlock = TempBlock;
|
LastBlock = TempBlock;
|
||||||
@ -928,7 +969,8 @@ CapsuleImageBase-->+---------------------------+
|
|||||||
coalesce capsule data into memory.
|
coalesce capsule data into memory.
|
||||||
|
|
||||||
@param PeiServices General purpose services available to every PEIM.
|
@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
|
@param MemoryBase Pointer to the base of a block of memory that we can walk
|
||||||
all over while trying to coalesce our buffers.
|
all over while trying to coalesce our buffers.
|
||||||
On output, this variable will hold the base address of
|
On output, this variable will hold the base address of
|
||||||
@ -950,6 +992,7 @@ EFIAPI
|
|||||||
CapsuleDataCoalesce (
|
CapsuleDataCoalesce (
|
||||||
IN EFI_PEI_SERVICES **PeiServices,
|
IN EFI_PEI_SERVICES **PeiServices,
|
||||||
IN EFI_PHYSICAL_ADDRESS *BlockListBuffer,
|
IN EFI_PHYSICAL_ADDRESS *BlockListBuffer,
|
||||||
|
IN MEMORY_RESOURCE_DESCRIPTOR *MemoryResource,
|
||||||
IN OUT VOID **MemoryBase,
|
IN OUT VOID **MemoryBase,
|
||||||
IN OUT UINTN *MemorySize
|
IN OUT UINTN *MemorySize
|
||||||
)
|
)
|
||||||
@ -994,7 +1037,7 @@ CapsuleDataCoalesce (
|
|||||||
//
|
//
|
||||||
// Build capsule descriptors list
|
// Build capsule descriptors list
|
||||||
//
|
//
|
||||||
Status = BuildCapsuleDescriptors (BlockListBuffer, &BlockList);
|
Status = BuildCapsuleDescriptors (BlockListBuffer, MemoryResource, &BlockList);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/** @file
|
/** @file
|
||||||
Common header file.
|
Common header file.
|
||||||
|
|
||||||
Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2011 - 2016, 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
|
||||||
@ -35,6 +35,17 @@ typedef struct {
|
|||||||
} EFI_CAPSULE_PEIM_PRIVATE_DATA;
|
} EFI_CAPSULE_PEIM_PRIVATE_DATA;
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
///
|
||||||
|
/// The physical start address of the resource region.
|
||||||
|
///
|
||||||
|
EFI_PHYSICAL_ADDRESS PhysicalStart;
|
||||||
|
///
|
||||||
|
/// The number of bytes of the resource region.
|
||||||
|
///
|
||||||
|
UINT64 ResourceLength;
|
||||||
|
} MEMORY_RESOURCE_DESCRIPTOR;
|
||||||
|
|
||||||
#define CAPSULE_TEST_SIGNATURE SIGNATURE_32('T', 'E', 'S', 'T')
|
#define CAPSULE_TEST_SIGNATURE SIGNATURE_32('T', 'E', 'S', 'T')
|
||||||
|
|
||||||
#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)
|
#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)
|
||||||
@ -45,6 +56,7 @@ typedef struct {
|
|||||||
UINT64 StackBufferLength;
|
UINT64 StackBufferLength;
|
||||||
EFI_PHYSICAL_ADDRESS JumpBuffer;
|
EFI_PHYSICAL_ADDRESS JumpBuffer;
|
||||||
EFI_PHYSICAL_ADDRESS BlockListAddr;
|
EFI_PHYSICAL_ADDRESS BlockListAddr;
|
||||||
|
EFI_PHYSICAL_ADDRESS MemoryResource;
|
||||||
EFI_PHYSICAL_ADDRESS MemoryBase64Ptr;
|
EFI_PHYSICAL_ADDRESS MemoryBase64Ptr;
|
||||||
EFI_PHYSICAL_ADDRESS MemorySize64Ptr;
|
EFI_PHYSICAL_ADDRESS MemorySize64Ptr;
|
||||||
BOOLEAN Page1GSupport;
|
BOOLEAN Page1GSupport;
|
||||||
@ -71,6 +83,7 @@ typedef struct {
|
|||||||
|
|
||||||
@param PeiServices General purpose services available to every PEIM.
|
@param PeiServices General purpose services available to every PEIM.
|
||||||
@param BlockListBuffer Point to the buffer of Capsule Descriptor Variables.
|
@param BlockListBuffer Point 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
|
@param MemoryBase Pointer to the base of a block of memory that we can walk
|
||||||
all over while trying to coalesce our buffers.
|
all over while trying to coalesce our buffers.
|
||||||
On output, this variable will hold the base address of
|
On output, this variable will hold the base address of
|
||||||
@ -94,7 +107,8 @@ EFI_STATUS
|
|||||||
EFIAPI
|
EFIAPI
|
||||||
CapsuleDataCoalesce (
|
CapsuleDataCoalesce (
|
||||||
IN EFI_PEI_SERVICES **PeiServices,
|
IN EFI_PEI_SERVICES **PeiServices,
|
||||||
IN IN EFI_PHYSICAL_ADDRESS *BlockListBuffer,
|
IN EFI_PHYSICAL_ADDRESS *BlockListBuffer,
|
||||||
|
IN MEMORY_RESOURCE_DESCRIPTOR *MemoryResource,
|
||||||
IN OUT VOID **MemoryBase,
|
IN OUT VOID **MemoryBase,
|
||||||
IN OUT UINTN *MemorySize
|
IN OUT UINTN *MemorySize
|
||||||
);
|
);
|
||||||
|
@ -354,6 +354,7 @@ Thunk32To64 (
|
|||||||
@param LongModeBuffer The context of long mode.
|
@param LongModeBuffer The context of long mode.
|
||||||
@param CoalesceEntry Entry of coalesce image.
|
@param CoalesceEntry Entry of coalesce image.
|
||||||
@param BlockListAddr Address of block list.
|
@param BlockListAddr Address of block list.
|
||||||
|
@param MemoryResource Pointer to the buffer of memory resource descriptor.
|
||||||
@param MemoryBase Base of memory range.
|
@param MemoryBase Base of memory range.
|
||||||
@param MemorySize Size of memory range.
|
@param MemorySize Size of memory range.
|
||||||
|
|
||||||
@ -366,6 +367,7 @@ ModeSwitch (
|
|||||||
IN EFI_CAPSULE_LONG_MODE_BUFFER *LongModeBuffer,
|
IN EFI_CAPSULE_LONG_MODE_BUFFER *LongModeBuffer,
|
||||||
IN COALESCE_ENTRY CoalesceEntry,
|
IN COALESCE_ENTRY CoalesceEntry,
|
||||||
IN EFI_PHYSICAL_ADDRESS BlockListAddr,
|
IN EFI_PHYSICAL_ADDRESS BlockListAddr,
|
||||||
|
IN MEMORY_RESOURCE_DESCRIPTOR *MemoryResource,
|
||||||
IN OUT VOID **MemoryBase,
|
IN OUT VOID **MemoryBase,
|
||||||
IN OUT UINTN *MemorySize
|
IN OUT UINTN *MemorySize
|
||||||
)
|
)
|
||||||
@ -429,6 +431,7 @@ ModeSwitch (
|
|||||||
Context.StackBufferLength = LongModeBuffer->StackSize;
|
Context.StackBufferLength = LongModeBuffer->StackSize;
|
||||||
Context.EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)CoalesceEntry;
|
Context.EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)CoalesceEntry;
|
||||||
Context.BlockListAddr = BlockListAddr;
|
Context.BlockListAddr = BlockListAddr;
|
||||||
|
Context.MemoryResource = (EFI_PHYSICAL_ADDRESS)(UINTN)MemoryResource;
|
||||||
Context.MemoryBase64Ptr = (EFI_PHYSICAL_ADDRESS)(UINTN)&MemoryBase64;
|
Context.MemoryBase64Ptr = (EFI_PHYSICAL_ADDRESS)(UINTN)&MemoryBase64;
|
||||||
Context.MemorySize64Ptr = (EFI_PHYSICAL_ADDRESS)(UINTN)&MemorySize64;
|
Context.MemorySize64Ptr = (EFI_PHYSICAL_ADDRESS)(UINTN)&MemorySize64;
|
||||||
Context.Page1GSupport = Page1GSupport;
|
Context.Page1GSupport = Page1GSupport;
|
||||||
@ -560,6 +563,133 @@ GetLongModeContext (
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)
|
||||||
|
/**
|
||||||
|
Get physical address bits.
|
||||||
|
|
||||||
|
@return Physical address bits.
|
||||||
|
|
||||||
|
**/
|
||||||
|
UINT8
|
||||||
|
GetPhysicalAddressBits (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT32 RegEax;
|
||||||
|
UINT8 PhysicalAddressBits;
|
||||||
|
VOID *Hob;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get physical address bits supported.
|
||||||
|
//
|
||||||
|
Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
|
||||||
|
if (Hob != NULL) {
|
||||||
|
PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;
|
||||||
|
} else {
|
||||||
|
AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
|
||||||
|
if (RegEax >= 0x80000008) {
|
||||||
|
AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
|
||||||
|
PhysicalAddressBits = (UINT8) RegEax;
|
||||||
|
} else {
|
||||||
|
PhysicalAddressBits = 36;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.
|
||||||
|
//
|
||||||
|
ASSERT (PhysicalAddressBits <= 52);
|
||||||
|
if (PhysicalAddressBits > 48) {
|
||||||
|
PhysicalAddressBits = 48;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PhysicalAddressBits;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Build memory resource descriptor from resource descriptor in HOB list.
|
||||||
|
|
||||||
|
@return Pointer to the buffer of memory resource descriptor.
|
||||||
|
NULL if no memory resource descriptor reported in HOB list
|
||||||
|
before capsule Coalesce.
|
||||||
|
|
||||||
|
**/
|
||||||
|
MEMORY_RESOURCE_DESCRIPTOR *
|
||||||
|
BuildMemoryResourceDescriptor (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_PEI_HOB_POINTERS Hob;
|
||||||
|
UINTN Index;
|
||||||
|
EFI_HOB_RESOURCE_DESCRIPTOR *ResourceDescriptor;
|
||||||
|
MEMORY_RESOURCE_DESCRIPTOR *MemoryResource;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the count of memory resource descriptor.
|
||||||
|
//
|
||||||
|
Index = 0;
|
||||||
|
Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
|
||||||
|
while (Hob.Raw != NULL) {
|
||||||
|
ResourceDescriptor = (EFI_HOB_RESOURCE_DESCRIPTOR *) Hob.Raw;
|
||||||
|
if (ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
|
||||||
|
Index++;
|
||||||
|
}
|
||||||
|
Hob.Raw = GET_NEXT_HOB (Hob);
|
||||||
|
Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Index == 0) {
|
||||||
|
DEBUG ((EFI_D_INFO | EFI_D_WARN, "No memory resource descriptor reported in HOB list before capsule Coalesce\n"));
|
||||||
|
#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)
|
||||||
|
//
|
||||||
|
// Allocate memory to hold memory resource descriptor,
|
||||||
|
// include extra one NULL terminate memory resource descriptor.
|
||||||
|
//
|
||||||
|
Status = PeiServicesAllocatePool ((1 + 1) * sizeof (MEMORY_RESOURCE_DESCRIPTOR), (VOID **) &MemoryResource);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
ZeroMem (MemoryResource, (1 + 1) * sizeof (MEMORY_RESOURCE_DESCRIPTOR));
|
||||||
|
|
||||||
|
MemoryResource[0].PhysicalStart = 0;
|
||||||
|
MemoryResource[0].ResourceLength = LShiftU64 (1, GetPhysicalAddressBits ());
|
||||||
|
DEBUG ((EFI_D_INFO, "MemoryResource[0x0] - Start(0x%0lx) Length(0x%0lx)\n",
|
||||||
|
MemoryResource[0x0].PhysicalStart, MemoryResource[0x0].ResourceLength));
|
||||||
|
return MemoryResource;
|
||||||
|
#else
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Allocate memory to hold memory resource descriptor,
|
||||||
|
// include extra one NULL terminate memory resource descriptor.
|
||||||
|
//
|
||||||
|
Status = PeiServicesAllocatePool ((Index + 1) * sizeof (MEMORY_RESOURCE_DESCRIPTOR), (VOID **) &MemoryResource);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
ZeroMem (MemoryResource, (Index + 1) * sizeof (MEMORY_RESOURCE_DESCRIPTOR));
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the content of memory resource descriptor.
|
||||||
|
//
|
||||||
|
Index = 0;
|
||||||
|
Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
|
||||||
|
while (Hob.Raw != NULL) {
|
||||||
|
ResourceDescriptor = (EFI_HOB_RESOURCE_DESCRIPTOR *) Hob.Raw;
|
||||||
|
if (ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
|
||||||
|
DEBUG ((EFI_D_INFO, "MemoryResource[0x%x] - Start(0x%0lx) Length(0x%0lx)\n",
|
||||||
|
Index, ResourceDescriptor->PhysicalStart, ResourceDescriptor->ResourceLength));
|
||||||
|
MemoryResource[Index].PhysicalStart = ResourceDescriptor->PhysicalStart;
|
||||||
|
MemoryResource[Index].ResourceLength = ResourceDescriptor->ResourceLength;
|
||||||
|
Index++;
|
||||||
|
}
|
||||||
|
Hob.Raw = GET_NEXT_HOB (Hob);
|
||||||
|
Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
return MemoryResource;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Checks for the presence of capsule descriptors.
|
Checks for the presence of capsule descriptors.
|
||||||
Get capsule descriptors from variable CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
|
Get capsule descriptors from variable CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
|
||||||
@ -711,6 +841,7 @@ CapsuleCoalesce (
|
|||||||
EFI_BOOT_MODE BootMode;
|
EFI_BOOT_MODE BootMode;
|
||||||
EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices;
|
EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices;
|
||||||
EFI_PHYSICAL_ADDRESS *VariableArrayAddress;
|
EFI_PHYSICAL_ADDRESS *VariableArrayAddress;
|
||||||
|
MEMORY_RESOURCE_DESCRIPTOR *MemoryResource;
|
||||||
#ifdef MDE_CPU_IA32
|
#ifdef MDE_CPU_IA32
|
||||||
UINT16 CoalesceImageMachineType;
|
UINT16 CoalesceImageMachineType;
|
||||||
EFI_PHYSICAL_ADDRESS CoalesceImageEntryPoint;
|
EFI_PHYSICAL_ADDRESS CoalesceImageEntryPoint;
|
||||||
@ -800,6 +931,8 @@ CapsuleCoalesce (
|
|||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MemoryResource = BuildMemoryResourceDescriptor ();
|
||||||
|
|
||||||
#ifdef MDE_CPU_IA32
|
#ifdef MDE_CPU_IA32
|
||||||
if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
|
if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
|
||||||
//
|
//
|
||||||
@ -825,18 +958,18 @@ CapsuleCoalesce (
|
|||||||
}
|
}
|
||||||
ASSERT (CoalesceImageEntryPoint != 0);
|
ASSERT (CoalesceImageEntryPoint != 0);
|
||||||
CoalesceEntry = (COALESCE_ENTRY) (UINTN) CoalesceImageEntryPoint;
|
CoalesceEntry = (COALESCE_ENTRY) (UINTN) CoalesceImageEntryPoint;
|
||||||
Status = ModeSwitch (&LongModeBuffer, CoalesceEntry, (EFI_PHYSICAL_ADDRESS)(UINTN)VariableArrayAddress, MemoryBase, MemorySize);
|
Status = ModeSwitch (&LongModeBuffer, CoalesceEntry, (EFI_PHYSICAL_ADDRESS)(UINTN)VariableArrayAddress, MemoryResource, MemoryBase, MemorySize);
|
||||||
} else {
|
} else {
|
||||||
//
|
//
|
||||||
// Capsule is processed in IA32 mode.
|
// Capsule is processed in IA32 mode.
|
||||||
//
|
//
|
||||||
Status = CapsuleDataCoalesce (PeiServices, (EFI_PHYSICAL_ADDRESS *)(UINTN)VariableArrayAddress, MemoryBase, MemorySize);
|
Status = CapsuleDataCoalesce (PeiServices, (EFI_PHYSICAL_ADDRESS *)(UINTN)VariableArrayAddress, MemoryResource, MemoryBase, MemorySize);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
//
|
//
|
||||||
// Process capsule directly.
|
// Process capsule directly.
|
||||||
//
|
//
|
||||||
Status = CapsuleDataCoalesce (PeiServices, (EFI_PHYSICAL_ADDRESS *)(UINTN)VariableArrayAddress, MemoryBase, MemorySize);
|
Status = CapsuleDataCoalesce (PeiServices, (EFI_PHYSICAL_ADDRESS *)(UINTN)VariableArrayAddress, MemoryResource, MemoryBase, MemorySize);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEBUG ((EFI_D_INFO, "Capsule Coalesce Status = %r!\n", Status));
|
DEBUG ((EFI_D_INFO, "Capsule Coalesce Status = %r!\n", Status));
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/** @file
|
/** @file
|
||||||
The X64 entrypoint is used to process capsule in long mode.
|
The X64 entrypoint is used to process capsule in long mode.
|
||||||
|
|
||||||
Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2011 - 2016, 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
|
||||||
@ -258,6 +258,7 @@ _ModuleEntryPoint (
|
|||||||
Status = CapsuleDataCoalesce (
|
Status = CapsuleDataCoalesce (
|
||||||
NULL,
|
NULL,
|
||||||
(EFI_PHYSICAL_ADDRESS *) (UINTN) EntrypointContext->BlockListAddr,
|
(EFI_PHYSICAL_ADDRESS *) (UINTN) EntrypointContext->BlockListAddr,
|
||||||
|
(MEMORY_RESOURCE_DESCRIPTOR *) (UINTN) EntrypointContext->MemoryResource,
|
||||||
(VOID **) (UINTN) EntrypointContext->MemoryBase64Ptr,
|
(VOID **) (UINTN) EntrypointContext->MemoryBase64Ptr,
|
||||||
(UINTN *) (UINTN) EntrypointContext->MemorySize64Ptr
|
(UINTN *) (UINTN) EntrypointContext->MemorySize64Ptr
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user