mirror of https://github.com/acidanthera/audk.git
414 lines
12 KiB
C
414 lines
12 KiB
C
/** @file
|
|
Sample to provide FSP hob process related function.
|
|
|
|
Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
|
|
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 <PiPei.h>
|
|
|
|
#include <Library/PeiServicesLib.h>
|
|
#include <Library/PeiServicesTablePointerLib.h>
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/HobLib.h>
|
|
#include <Library/PcdLib.h>
|
|
#include <Library/FspPlatformInfoLib.h>
|
|
|
|
#include <Guid/GuidHobFspEas.h>
|
|
#include <Guid/MemoryTypeInformation.h>
|
|
#include <Guid/PcdDataBaseHobGuid.h>
|
|
#include <Ppi/Capsule.h>
|
|
|
|
//
|
|
// 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[in] PeiServices PEI Services table.
|
|
|
|
@return the mem size in memory type infromation table.
|
|
**/
|
|
UINT64
|
|
GetMemorySizeInMemoryTypeInformation (
|
|
IN EFI_PEI_SERVICES **PeiServices
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_PEI_HOB_POINTERS Hob;
|
|
EFI_MEMORY_TYPE_INFORMATION *MemoryData;
|
|
UINT8 Index;
|
|
UINTN TempPageNum;
|
|
|
|
MemoryData = NULL;
|
|
Status = (*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[in] 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[in] PeiServices PEI Services table.
|
|
@param[in] 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 for 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
|
|
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;
|
|
EFI_PEI_CAPSULE_PPI *Capsule;
|
|
VOID *CapsuleBuffer;
|
|
UINTN CapsuleBufferLength;
|
|
UINT64 RequiredMemSize;
|
|
EFI_PEI_SERVICES **PeiServices;
|
|
|
|
PeiServices = (EFI_PEI_SERVICES **)GetPeiServicesTablePointer ();
|
|
|
|
PeiServicesGetBootMode (&BootMode);
|
|
|
|
PeiMemBase = 0;
|
|
LowMemorySize = 0;
|
|
FspMemorySize = 0;
|
|
FspMemoryBase = 0;
|
|
FoundFspMemHob = 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));
|
|
}
|
|
|
|
//
|
|
// 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
|
|
);
|
|
|
|
S3PeiMemBase = 0;
|
|
S3PeiMemSize = 0;
|
|
Status = GetS3MemoryInfo (&S3PeiMemSize, &S3PeiMemBase);
|
|
ASSERT_EFI_ERROR (Status);
|
|
DEBUG((DEBUG_INFO, "S3 memory %Xh - %Xh bytes\n", S3PeiMemBase, S3PeiMemSize));
|
|
|
|
//
|
|
// Make sure Stack and PeiMemory are not overlap
|
|
//
|
|
|
|
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 (
|
|
&gEfiPeiCapsulePpiGuid,
|
|
0,
|
|
NULL,
|
|
(VOID **) &Capsule
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
if (Status == EFI_SUCCESS) {
|
|
//
|
|
// Make sure Stack and CapsuleBuffer are not overlap
|
|
//
|
|
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
|
|
//
|
|
|
|
//
|
|
// 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);
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Process FSP HOB list
|
|
|
|
@param[in] FspHobList Pointer to the HOB data structure produced by FSP.
|
|
|
|
**/
|
|
VOID
|
|
ProcessFspHobList (
|
|
IN VOID *FspHobList
|
|
)
|
|
{
|
|
EFI_PEI_HOB_POINTERS FspHob;
|
|
|
|
FspHob.Raw = FspHobList;
|
|
|
|
//
|
|
// Add all the HOBs from FSP binary to FSP wrapper
|
|
//
|
|
while (!END_OF_HOB_LIST (FspHob)) {
|
|
if (FspHob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION) {
|
|
//
|
|
// Skip FSP binary creates PcdDataBaseHobGuid
|
|
//
|
|
if (!CompareGuid(&FspHob.Guid->Name, &gPcdDataBaseHobGuid)) {
|
|
BuildGuidDataHob (
|
|
&FspHob.Guid->Name,
|
|
GET_GUID_HOB_DATA(FspHob),
|
|
GET_GUID_HOB_DATA_SIZE(FspHob)
|
|
);
|
|
}
|
|
}
|
|
FspHob.Raw = GET_NEXT_HOB (FspHob);
|
|
}
|
|
}
|
|
|
|
/**
|
|
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
|
|
)
|
|
{
|
|
ProcessFspHobList (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;
|
|
}
|