mirror of https://github.com/acidanthera/audk.git
281 lines
8.0 KiB
C
281 lines
8.0 KiB
C
/** @file
|
|
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
**/
|
|
|
|
#include <PiPei.h>
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/HobLib.h>
|
|
#include <Library/PcdLib.h>
|
|
#include <Guid/MemoryAllocationHob.h>
|
|
#include <Library/IoLib.h>
|
|
#include <Library/CpuLib.h>
|
|
#include <IndustryStandard/Acpi.h>
|
|
#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
|
|
#include <Guid/AcpiBoardInfoGuid.h>
|
|
#include <UniversalPayload/AcpiTable.h>
|
|
#include <UniversalPayload/UniversalPayload.h>
|
|
#include <UniversalPayload/ExtraData.h>
|
|
|
|
#define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
|
|
EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
|
|
EFI_RESOURCE_ATTRIBUTE_TESTED | \
|
|
EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \
|
|
EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \
|
|
EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \
|
|
EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED | \
|
|
EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
|
|
EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
|
|
EFI_RESOURCE_ATTRIBUTE_64_BIT_IO | \
|
|
EFI_RESOURCE_ATTRIBUTE_PERSISTENT )
|
|
|
|
#define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
|
|
EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
|
|
EFI_RESOURCE_ATTRIBUTE_TESTED )
|
|
|
|
extern VOID *mHobList;
|
|
|
|
/**
|
|
Add a new HOB to the HOB List.
|
|
|
|
@param HobType Type of the new HOB.
|
|
@param HobLength Length of the new HOB to allocate.
|
|
|
|
@return NULL if there is no space to create a hob.
|
|
@return The address point to the new created hob.
|
|
|
|
**/
|
|
VOID *
|
|
EFIAPI
|
|
CreateHob (
|
|
IN UINT16 HobType,
|
|
IN UINT16 HobLength
|
|
);
|
|
|
|
/**
|
|
Build a Handoff Information Table HOB
|
|
|
|
This function initialize a HOB region from EfiMemoryBegin to
|
|
EfiMemoryTop. And EfiFreeMemoryBottom and EfiFreeMemoryTop should
|
|
be inside the HOB region.
|
|
|
|
@param[in] EfiMemoryBottom Total memory start address
|
|
@param[in] EfiMemoryTop Total memory end address.
|
|
@param[in] EfiFreeMemoryBottom Free memory start address
|
|
@param[in] EfiFreeMemoryTop Free memory end address.
|
|
|
|
@return The pointer to the handoff HOB table.
|
|
|
|
**/
|
|
EFI_HOB_HANDOFF_INFO_TABLE *
|
|
EFIAPI
|
|
HobConstructor (
|
|
IN VOID *EfiMemoryBottom,
|
|
IN VOID *EfiMemoryTop,
|
|
IN VOID *EfiFreeMemoryBottom,
|
|
IN VOID *EfiFreeMemoryTop
|
|
);
|
|
|
|
/**
|
|
Build ACPI board info HOB using infomation from ACPI table
|
|
|
|
@param AcpiTableBase ACPI table start address in memory
|
|
|
|
@retval A pointer to ACPI board HOB ACPI_BOARD_INFO. Null if build HOB failure.
|
|
**/
|
|
ACPI_BOARD_INFO *
|
|
BuildHobFromAcpi (
|
|
IN UINT64 AcpiTableBase
|
|
);
|
|
|
|
/**
|
|
*
|
|
Add HOB into HOB list
|
|
|
|
@param[in] Hob The HOB to be added into the HOB list.
|
|
**/
|
|
VOID
|
|
AddNewHob (
|
|
IN EFI_PEI_HOB_POINTERS *Hob
|
|
)
|
|
{
|
|
EFI_PEI_HOB_POINTERS NewHob;
|
|
|
|
if (Hob->Raw == NULL) {
|
|
return;
|
|
}
|
|
|
|
NewHob.Header = CreateHob (Hob->Header->HobType, Hob->Header->HobLength);
|
|
|
|
if (NewHob.Header != NULL) {
|
|
CopyMem (NewHob.Header + 1, Hob->Header + 1, Hob->Header->HobLength - sizeof (EFI_HOB_GENERIC_HEADER));
|
|
}
|
|
}
|
|
|
|
/**
|
|
Found the Resource Descriptor HOB that contains a range (Base, Top)
|
|
|
|
@param[in] HobList Hob start address
|
|
@param[in] Base Memory start address
|
|
@param[in] Top Memory end address.
|
|
|
|
@retval The pointer to the Resource Descriptor HOB.
|
|
**/
|
|
EFI_HOB_RESOURCE_DESCRIPTOR *
|
|
FindResourceDescriptorByRange (
|
|
IN VOID *HobList,
|
|
IN EFI_PHYSICAL_ADDRESS Base,
|
|
IN EFI_PHYSICAL_ADDRESS Top
|
|
)
|
|
{
|
|
EFI_PEI_HOB_POINTERS Hob;
|
|
EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
|
|
|
|
for (Hob.Raw = (UINT8 *)HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
|
|
//
|
|
// Skip all HOBs except Resource Descriptor HOBs
|
|
//
|
|
if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Skip Resource Descriptor HOBs that do not describe tested system memory
|
|
//
|
|
ResourceHob = Hob.ResourceDescriptor;
|
|
if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
|
|
continue;
|
|
}
|
|
|
|
if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
|
|
//
|
|
if (Base < ResourceHob->PhysicalStart) {
|
|
continue;
|
|
}
|
|
|
|
if (Top > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) {
|
|
continue;
|
|
}
|
|
|
|
return ResourceHob;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
Find the highest below 4G memory resource descriptor, except the input Resource Descriptor.
|
|
|
|
@param[in] HobList Hob start address
|
|
@param[in] MinimalNeededSize Minimal needed size.
|
|
@param[in] ExceptResourceHob Ignore this Resource Descriptor.
|
|
|
|
@retval The pointer to the Resource Descriptor HOB.
|
|
**/
|
|
EFI_HOB_RESOURCE_DESCRIPTOR *
|
|
FindAnotherHighestBelow4GResourceDescriptor (
|
|
IN VOID *HobList,
|
|
IN UINTN MinimalNeededSize,
|
|
IN EFI_HOB_RESOURCE_DESCRIPTOR *ExceptResourceHob
|
|
)
|
|
{
|
|
EFI_PEI_HOB_POINTERS Hob;
|
|
EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
|
|
EFI_HOB_RESOURCE_DESCRIPTOR *ReturnResourceHob;
|
|
|
|
ReturnResourceHob = NULL;
|
|
|
|
for (Hob.Raw = (UINT8 *)HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
|
|
//
|
|
// Skip all HOBs except Resource Descriptor HOBs
|
|
//
|
|
if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Skip Resource Descriptor HOBs that do not describe tested system memory
|
|
//
|
|
ResourceHob = Hob.ResourceDescriptor;
|
|
if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
|
|
continue;
|
|
}
|
|
|
|
if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Skip if the Resource Descriptor HOB equals to ExceptResourceHob
|
|
//
|
|
if (ResourceHob == ExceptResourceHob) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Skip Resource Descriptor HOBs that are beyond 4G
|
|
//
|
|
if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > BASE_4GB) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Skip Resource Descriptor HOBs that are too small
|
|
//
|
|
if (ResourceHob->ResourceLength < MinimalNeededSize) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Return the topest Resource Descriptor
|
|
//
|
|
if (ReturnResourceHob == NULL) {
|
|
ReturnResourceHob = ResourceHob;
|
|
} else {
|
|
if (ReturnResourceHob->PhysicalStart < ResourceHob->PhysicalStart) {
|
|
ReturnResourceHob = ResourceHob;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ReturnResourceHob;
|
|
}
|
|
|
|
/**
|
|
Check the HOB and decide if it is need inside Payload
|
|
|
|
Payload maintainer may make decision which HOB is need or needn't
|
|
Then add the check logic in the function.
|
|
|
|
@param[in] Hob The HOB to check
|
|
|
|
@retval TRUE If HOB is need inside Payload
|
|
@retval FALSE If HOB is needn't inside Payload
|
|
**/
|
|
BOOLEAN
|
|
IsHobNeed (
|
|
EFI_PEI_HOB_POINTERS Hob
|
|
)
|
|
{
|
|
if (Hob.Header->HobType == EFI_HOB_TYPE_HANDOFF) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
|
|
if (CompareGuid (&Hob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// Arrive here mean the HOB is need
|
|
return TRUE;
|
|
}
|