/** @file
Null instance of Platform Sec Lib.
Copyright (c) 2014, Intel Corporation. All rights reserved.
This program and the accompanying materials
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
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
EFI_GUID gFspReservedMemoryResourceHobTsegGuid = {0xd038747c, 0xd00c, 0x4980, {0xb3, 0x19, 0x49, 0x01, 0x99, 0xa4, 0x7d, 0x55}};
//
// Additional pages are used by DXE memory manager.
// It should be consistent between RetrieveRequiredMemorySize() and GetPeiMemSize()
//
#define PEI_ADDITIONAL_MEMORY_SIZE (16 * EFI_PAGE_SIZE)
/**
Get the mem size in memory type infromation table.
@param PeiServices PEI Services table.
@return the mem size in memory type infromation table.
**/
UINT64
GetMemorySizeInMemoryTypeInformation (
IN EFI_PEI_SERVICES **PeiServices
)
{
EFI_PEI_HOB_POINTERS Hob;
EFI_MEMORY_TYPE_INFORMATION *MemoryData;
UINT8 Index;
UINTN TempPageNum;
MemoryData = NULL;
(*PeiServices)->GetHobList ((CONST EFI_PEI_SERVICES **)PeiServices, (VOID **) &Hob.Raw);
while (!END_OF_HOB_LIST (Hob)) {
if (Hob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION &&
CompareGuid (&Hob.Guid->Name, &gEfiMemoryTypeInformationGuid)) {
MemoryData = (EFI_MEMORY_TYPE_INFORMATION *) (Hob.Raw + sizeof (EFI_HOB_GENERIC_HEADER) + sizeof (EFI_GUID));
break;
}
Hob.Raw = GET_NEXT_HOB (Hob);
}
if (MemoryData == NULL) {
return 0;
}
TempPageNum = 0;
for (Index = 0; MemoryData[Index].Type != EfiMaxMemoryType; Index++) {
//
// Accumulate default memory size requirements
//
TempPageNum += MemoryData[Index].NumberOfPages;
}
return TempPageNum * EFI_PAGE_SIZE;
}
/**
Get the mem size need to be reserved in PEI phase.
@param PeiServices PEI Services table.
@return the mem size need to be reserved in PEI phase.
**/
UINT64
RetrieveRequiredMemorySize (
IN EFI_PEI_SERVICES **PeiServices
)
{
UINT64 Size;
Size = GetMemorySizeInMemoryTypeInformation (PeiServices);
return Size + PEI_ADDITIONAL_MEMORY_SIZE;
}
/**
Get the mem size need to be consumed and reserved in PEI phase.
@param PeiServices PEI Services table.
@param BootMode Current boot mode.
@return the mem size need to be consumed and reserved in PEI phase.
**/
UINT64
GetPeiMemSize (
IN EFI_PEI_SERVICES **PeiServices,
IN UINT32 BootMode
)
{
UINT64 Size;
UINT64 MinSize;
if (BootMode == BOOT_IN_RECOVERY_MODE) {
return PcdGet32 (PcdPeiRecoveryMinMemSize);
}
Size = GetMemorySizeInMemoryTypeInformation (PeiServices);
if (BootMode == BOOT_ON_FLASH_UPDATE) {
//
// Maybe more size when in CapsuleUpdate phase ?
//
MinSize = PcdGet32 (PcdPeiMinMemSize);
} else {
MinSize = PcdGet32 (PcdPeiMinMemSize);
}
return MinSize + Size + PEI_ADDITIONAL_MEMORY_SIZE;
}
/**
BIOS process FspBobList.
@param FspHobList Pointer to the HOB data structure produced by FSP.
@return If platform process the FSP hob list successfully.
**/
EFI_STATUS
EFIAPI
FspHobProcessForMemoryResource (
IN VOID *FspHobList
)
{
EFI_PEI_HOB_POINTERS Hob;
UINT64 LowMemorySize;
UINT64 FspMemorySize;
EFI_PHYSICAL_ADDRESS FspMemoryBase;
UINT64 PeiMemSize;
EFI_PHYSICAL_ADDRESS PeiMemBase;
UINT64 S3PeiMemSize;
EFI_PHYSICAL_ADDRESS S3PeiMemBase;
BOOLEAN FoundFspMemHob;
EFI_STATUS Status;
EFI_BOOT_MODE BootMode;
PEI_CAPSULE_PPI *Capsule;
VOID *CapsuleBuffer;
UINTN CapsuleBufferLength;
UINT64 RequiredMemSize;
EFI_PEI_SERVICES **PeiServices;
UINT64 TsegSize;
EFI_PHYSICAL_ADDRESS TsegBase;
BOOLEAN FoundTsegHob;
PeiServices = (EFI_PEI_SERVICES **)GetPeiServicesTablePointer ();
PeiServicesGetBootMode (&BootMode);
PeiMemBase = 0;
LowMemorySize = 0;
FspMemorySize = 0;
FspMemoryBase = 0;
FoundFspMemHob = FALSE;
TsegSize = 0;
TsegBase = 0;
FoundTsegHob = FALSE;
//
// Parse the hob list from fsp
// Report all the resource hob except the memory between 1M and 4G
//
Hob.Raw = (UINT8 *)(UINTN)FspHobList;
DEBUG((DEBUG_INFO, "FspHobList - 0x%x\n", FspHobList));
while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw)) != NULL) {
DEBUG((DEBUG_INFO, "\nResourceType: 0x%x\n", Hob.ResourceDescriptor->ResourceType));
if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) ||
(Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED)) {
DEBUG((DEBUG_INFO, "ResourceAttribute: 0x%x\n", Hob.ResourceDescriptor->ResourceAttribute));
DEBUG((DEBUG_INFO, "PhysicalStart: 0x%x\n", Hob.ResourceDescriptor->PhysicalStart));
DEBUG((DEBUG_INFO, "ResourceLength: 0x%x\n", Hob.ResourceDescriptor->ResourceLength));
DEBUG((DEBUG_INFO, "Owner: %g\n\n", &Hob.ResourceDescriptor->Owner));
}
if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) // Found the low memory length below 4G
&& (Hob.ResourceDescriptor->PhysicalStart >= BASE_1MB)
&& (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength <= BASE_4GB)) {
LowMemorySize += Hob.ResourceDescriptor->ResourceLength;
Hob.Raw = GET_NEXT_HOB (Hob);
continue;
}
if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED) // Found the low memory length below 4G
&& (Hob.ResourceDescriptor->PhysicalStart >= BASE_1MB)
&& (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength <= BASE_4GB)
&& (CompareGuid (&Hob.ResourceDescriptor->Owner, &gFspReservedMemoryResourceHobGuid))) {
FoundFspMemHob = TRUE;
FspMemoryBase = Hob.ResourceDescriptor->PhysicalStart;
FspMemorySize = Hob.ResourceDescriptor->ResourceLength;
DEBUG((DEBUG_INFO, "Find fsp mem hob, base 0x%x, len 0x%x\n", FspMemoryBase, FspMemorySize));
}
if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED) // Found the low memory length below 4G
&& (Hob.ResourceDescriptor->PhysicalStart >= 0x100000)
&& (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength <= 0x100000000)
&& (CompareGuid (&Hob.ResourceDescriptor->Owner, &gFspReservedMemoryResourceHobTsegGuid))) {
FoundTsegHob = TRUE;
TsegBase = Hob.ResourceDescriptor->PhysicalStart;
if ((Hob.ResourceDescriptor->ResourceLength == 0 ) || (Hob.ResourceDescriptor->ResourceLength > 0x800000)){
Hob.ResourceDescriptor->ResourceLength = 0x800000;
}
TsegSize = Hob.ResourceDescriptor->ResourceLength;
DEBUG((EFI_D_ERROR, "Find Tseg mem hob, base 0x%lx, len 0x%lx\n", TsegBase, TsegSize));
}
//
// Report the resource hob
//
BuildResourceDescriptorHob (
Hob.ResourceDescriptor->ResourceType,
Hob.ResourceDescriptor->ResourceAttribute,
Hob.ResourceDescriptor->PhysicalStart,
Hob.ResourceDescriptor->ResourceLength
);
Hob.Raw = GET_NEXT_HOB (Hob);
}
if (!FoundFspMemHob) {
DEBUG((DEBUG_INFO, "Didn't find the fsp used memory information.\n"));
//ASSERT(FALSE);
}
DEBUG((DEBUG_INFO, "LowMemorySize: 0x%x.\n", LowMemorySize));
DEBUG((DEBUG_INFO, "FspMemoryBase: 0x%x.\n", FspMemoryBase));
DEBUG((DEBUG_INFO, "FspMemorySize: 0x%x.\n", FspMemorySize));
if (BootMode == BOOT_ON_S3_RESUME) {
BuildResourceDescriptorHob (
EFI_RESOURCE_SYSTEM_MEMORY,
(
EFI_RESOURCE_ATTRIBUTE_PRESENT |
EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
// EFI_RESOURCE_ATTRIBUTE_TESTED |
EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
),
BASE_1MB,
LowMemorySize
);
Status = GetS3MemoryInfo (&S3PeiMemBase, &S3PeiMemSize);
ASSERT_EFI_ERROR (Status);
DEBUG((DEBUG_INFO, "S3 memory %Xh - %Xh bytes\n", S3PeiMemBase, S3PeiMemSize));
//
// Make sure Stack and PeiMemory are not overlap - JYAO1
//
Status = PeiServicesInstallPeiMemory (
S3PeiMemBase,
S3PeiMemSize
);
ASSERT_EFI_ERROR (Status);
} else {
PeiMemSize = GetPeiMemSize (PeiServices, BootMode);
DEBUG((DEBUG_INFO, "PEI memory size = %Xh bytes\n", PeiMemSize));
//
// Capsule mode
//
Capsule = NULL;
CapsuleBuffer = NULL;
CapsuleBufferLength = 0;
if (BootMode == BOOT_ON_FLASH_UPDATE) {
Status = PeiServicesLocatePpi (
&gPeiCapsulePpiGuid,
0,
NULL,
(VOID **) &Capsule
);
ASSERT_EFI_ERROR (Status);
if (Status == EFI_SUCCESS) {
//
// Make sure Stack and CapsuleBuffer are not overlap - JYAO1
//
CapsuleBuffer = (VOID *)(UINTN)BASE_1MB;
CapsuleBufferLength = (UINTN)(LowMemorySize - PeiMemSize);
//
// Call the Capsule PPI Coalesce function to coalesce the capsule data.
//
Status = Capsule->Coalesce (PeiServices, &CapsuleBuffer, &CapsuleBufferLength);
}
}
RequiredMemSize = RetrieveRequiredMemorySize (PeiServices);
DEBUG((DEBUG_INFO, "Required memory size = %Xh bytes\n", RequiredMemSize));
//
// Report the main memory
//
BuildResourceDescriptorHob (
EFI_RESOURCE_SYSTEM_MEMORY,
(
EFI_RESOURCE_ATTRIBUTE_PRESENT |
EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
EFI_RESOURCE_ATTRIBUTE_TESTED |
EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
),
BASE_1MB,
LowMemorySize
);
//
// Make sure Stack and CapsuleBuffer are not overlap - JYAO1
//
//
// Install efi memory
//
PeiMemBase = BASE_1MB + LowMemorySize - PeiMemSize;
Status = PeiServicesInstallPeiMemory (
PeiMemBase,
PeiMemSize - RequiredMemSize
);
ASSERT_EFI_ERROR (Status);
if (Capsule != NULL) {
Status = Capsule->CreateState (PeiServices, CapsuleBuffer, CapsuleBufferLength);
}
}
//
// Report GUIDed HOB for reserving SMRAM regions
//
if (FoundTsegHob) {
EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *SmramHobDescriptorBlock;
SmramHobDescriptorBlock = BuildGuidHob (
&gEfiSmmPeiSmramMemoryReserveGuid,
sizeof (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK)
);
ASSERT (SmramHobDescriptorBlock != NULL);
SmramHobDescriptorBlock->NumberOfSmmReservedRegions = 1;
SmramHobDescriptorBlock->Descriptor[0].PhysicalStart = TsegBase;
SmramHobDescriptorBlock->Descriptor[0].CpuStart = TsegBase;
SmramHobDescriptorBlock->Descriptor[0].PhysicalSize = TsegSize;
SmramHobDescriptorBlock->Descriptor[0].RegionState = EFI_SMRAM_CLOSED;
}
return EFI_SUCCESS;
}
/**
BIOS process FspBobList for other data (not Memory Resource Descriptor).
@param[in] FspHobList Pointer to the HOB data structure produced by FSP.
@return If platform process the FSP hob list successfully.
**/
EFI_STATUS
EFIAPI
FspHobProcessForOtherData (
IN VOID *FspHobList
)
{
EFI_PEI_SERVICES **PeiServices;
PeiServices = (EFI_PEI_SERVICES **)GetPeiServicesTablePointer ();
//
// Other hob for platform
//
PlatformHobCreateFromFsp ((CONST EFI_PEI_SERVICES **) PeiServices, FspHobList);
return EFI_SUCCESS;
}
/**
BIOS process FspBobList.
@param[in] FspHobList Pointer to the HOB data structure produced by FSP.
@return If platform process the FSP hob list successfully.
**/
EFI_STATUS
EFIAPI
FspHobProcess (
IN VOID *FspHobList
)
{
EFI_STATUS Status;
Status = FspHobProcessForMemoryResource (FspHobList);
if (EFI_ERROR (Status)) {
return Status;
}
Status = FspHobProcessForOtherData (FspHobList);
return Status;
}