UefiPayloadPkg: Add FIT support
Provide Fit format for UniversalPayload, developer can use argument "--Fit" to build UniversalPayload.fit Cc: Guo Dong <guo.dong@intel.com> Cc: Sean Rhodes <sean@starlabs.systems> Cc: James Lu <james.lu@intel.com> Cc: Gua Guo <gua.guo@intel.com> Reviewed-by: Gua Guo <gua.guo@intel.com> Signed-off-by: BruceX Wang <brucex.wang@intel.com>
This commit is contained in:
committed by
mergify[bot]
parent
d6b05375b4
commit
39f3c26e8c
653
UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
Normal file
653
UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
Normal file
@@ -0,0 +1,653 @@
|
||||
/** @file
|
||||
Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
#include "UefiPayloadEntry.h"
|
||||
#include <Library/FdtLib.h>
|
||||
#include <Guid/UniversalPayloadBase.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;
|
||||
|
||||
CHAR8 *mLineBuffer = NULL;
|
||||
|
||||
/**
|
||||
Print all HOBs info from the HOB list.
|
||||
@return The pointer to the HOB list.
|
||||
**/
|
||||
VOID
|
||||
PrintHob (
|
||||
IN CONST VOID *HobStart
|
||||
);
|
||||
|
||||
/**
|
||||
Find the first substring.
|
||||
@param String Point to the string where to find the substring.
|
||||
@param CharSet Point to the string to be found.
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
AsciiStrSpn (
|
||||
IN CHAR8 *String,
|
||||
IN CHAR8 *CharSet
|
||||
)
|
||||
{
|
||||
UINTN Count;
|
||||
CHAR8 *Str1;
|
||||
CHAR8 *Str2;
|
||||
|
||||
Count = 0;
|
||||
|
||||
for (Str1 = String; *Str1 != L'\0'; Str1++) {
|
||||
for (Str2 = CharSet; *Str2 != L'\0'; Str2++) {
|
||||
if (*Str1 == *Str2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (*Str2 == L'\0') {
|
||||
return Count;
|
||||
}
|
||||
|
||||
Count++;
|
||||
}
|
||||
|
||||
return Count;
|
||||
}
|
||||
|
||||
/**
|
||||
Searches a string for the first occurrence of a character contained in a
|
||||
specified buffer.
|
||||
@param String Point to the string where to find the substring.
|
||||
@param CharSet Point to the string to be found.
|
||||
**/
|
||||
CHAR8 *
|
||||
EFIAPI
|
||||
AsciiStrBrk (
|
||||
IN CHAR8 *String,
|
||||
IN CHAR8 *CharSet
|
||||
)
|
||||
{
|
||||
CHAR8 *Str1;
|
||||
CHAR8 *Str2;
|
||||
|
||||
for (Str1 = String; *Str1 != L'\0'; Str1++) {
|
||||
for (Str2 = CharSet; *Str2 != L'\0'; Str2++) {
|
||||
if (*Str1 == *Str2) {
|
||||
return (CHAR8 *)Str1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
Find the next token after one or more specified characters.
|
||||
@param String Point to the string where to find the substring.
|
||||
@param CharSet Point to the string to be found.
|
||||
**/
|
||||
CHAR8 *
|
||||
EFIAPI
|
||||
AsciiStrTokenLine (
|
||||
IN CHAR8 *String OPTIONAL,
|
||||
IN CHAR8 *CharSet
|
||||
)
|
||||
{
|
||||
CHAR8 *Begin;
|
||||
CHAR8 *End;
|
||||
|
||||
Begin = (String == NULL) ? mLineBuffer : String;
|
||||
if (Begin == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Begin += AsciiStrSpn (Begin, CharSet);
|
||||
if (*Begin == L'\0') {
|
||||
mLineBuffer = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
End = AsciiStrBrk (Begin, CharSet);
|
||||
if ((End != NULL) && (*End != L'\0')) {
|
||||
*End = L'\0';
|
||||
End++;
|
||||
}
|
||||
|
||||
mLineBuffer = End;
|
||||
return Begin;
|
||||
}
|
||||
|
||||
/**
|
||||
Some bootloader may pass a pcd database, and UPL also contain a PCD database.
|
||||
Dxe PCD driver has the assumption that the two PCD database can be catenated and
|
||||
the local token number should be successive.
|
||||
This function will fix up the UPL PCD database to meet that assumption.
|
||||
@param[in] DxeFv The FV where to find the Universal PCD database.
|
||||
@retval EFI_SUCCESS If it completed successfully.
|
||||
@retval other Failed to fix up.
|
||||
**/
|
||||
EFI_STATUS
|
||||
FixUpPcdDatabase (
|
||||
IN EFI_FIRMWARE_VOLUME_HEADER *DxeFv
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_FFS_FILE_HEADER *FileHeader;
|
||||
VOID *PcdRawData;
|
||||
PEI_PCD_DATABASE *PeiDatabase;
|
||||
PEI_PCD_DATABASE *UplDatabase;
|
||||
EFI_HOB_GUID_TYPE *GuidHob;
|
||||
DYNAMICEX_MAPPING *ExMapTable;
|
||||
UINTN Index;
|
||||
|
||||
GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);
|
||||
if (GuidHob == NULL) {
|
||||
//
|
||||
// No fix-up is needed.
|
||||
//
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
PeiDatabase = (PEI_PCD_DATABASE *)GET_GUID_HOB_DATA (GuidHob);
|
||||
DEBUG ((DEBUG_INFO, "Find the Pei PCD data base, the total local token number is %d\n", PeiDatabase->LocalTokenCount));
|
||||
|
||||
Status = FvFindFileByTypeGuid (DxeFv, EFI_FV_FILETYPE_DRIVER, PcdGetPtr (PcdPcdDriverFile), &FileHeader);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = FileFindSection (FileHeader, EFI_SECTION_RAW, &PcdRawData);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
UplDatabase = (PEI_PCD_DATABASE *)PcdRawData;
|
||||
ExMapTable = (DYNAMICEX_MAPPING *)(UINTN)((UINTN)PcdRawData + UplDatabase->ExMapTableOffset);
|
||||
|
||||
for (Index = 0; Index < UplDatabase->ExTokenCount; Index++) {
|
||||
ExMapTable[Index].TokenNumber += PeiDatabase->LocalTokenCount;
|
||||
}
|
||||
|
||||
DEBUG ((DEBUG_INFO, "Fix up UPL PCD database successfully\n"));
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
It will build Fv HOBs based on information from bootloaders.
|
||||
@param[out] DxeFv The pointer to the DXE FV in memory.
|
||||
@retval EFI_SUCCESS If it completed successfully.
|
||||
@retval EFI_NOT_FOUND If it failed to find node in fit image.
|
||||
@retval Others If it failed to build required HOBs.
|
||||
**/
|
||||
EFI_STATUS
|
||||
BuildFitLoadablesFvHob (
|
||||
OUT EFI_FIRMWARE_VOLUME_HEADER **DxeFv
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
VOID *Fdt;
|
||||
UINT8 *GuidHob;
|
||||
UNIVERSAL_PAYLOAD_BASE *PayloadBase;
|
||||
INT32 ConfigNode;
|
||||
INT32 Config1Node;
|
||||
INT32 ImageNode;
|
||||
INT32 FvNode;
|
||||
INT32 Depth;
|
||||
CONST FDT_PROPERTY *PropertyPtr;
|
||||
INT32 TempLen;
|
||||
CONST CHAR8 *Fvname;
|
||||
UINT32 DataOffset;
|
||||
UINT32 DataSize;
|
||||
UINT32 *Data32;
|
||||
|
||||
GuidHob = GetFirstGuidHob (&gUniversalPayloadBaseGuid);
|
||||
if (GuidHob != NULL) {
|
||||
PayloadBase = (UNIVERSAL_PAYLOAD_BASE *)GET_GUID_HOB_DATA (GuidHob);
|
||||
Fdt = (VOID *)(UINTN)PayloadBase->Entry;
|
||||
DEBUG ((DEBUG_INFO, "PayloadBase Entry = 0x%08x\n", PayloadBase->Entry));
|
||||
}
|
||||
|
||||
Status = FdtCheckHeader (Fdt);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
ConfigNode = FdtSubnodeOffsetNameLen (Fdt, 0, "configurations", (INT32)AsciiStrLen ("configurations"));
|
||||
if (ConfigNode <= 0) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
Config1Node = FdtSubnodeOffsetNameLen (Fdt, ConfigNode, "conf-1", (INT32)AsciiStrLen ("conf-1"));
|
||||
if (Config1Node <= 0) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
ImageNode = FdtSubnodeOffsetNameLen (Fdt, 0, "images", (INT32)AsciiStrLen ("images"));
|
||||
if (ImageNode <= 0) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
FvNode = FdtSubnodeOffsetNameLen (Fdt, ImageNode, "tianocore", (INT32)AsciiStrLen ("tianocore"));
|
||||
Depth = FdtNodeDepth (Fdt, FvNode);
|
||||
FvNode = FdtNextNode (Fdt, FvNode, &Depth);
|
||||
Fvname = FdtGetName (Fdt, FvNode, &TempLen);
|
||||
while ((AsciiStrCmp ((Fvname + AsciiStrLen (Fvname) - 2), "fv") == 0)) {
|
||||
if (FvNode <= 0) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
PropertyPtr = FdtGetProperty (Fdt, FvNode, "data-offset", &TempLen);
|
||||
Data32 = (UINT32 *)(PropertyPtr->Data);
|
||||
DataOffset = SwapBytes32 (*Data32);
|
||||
|
||||
PropertyPtr = FdtGetProperty (Fdt, FvNode, "data-size", &TempLen);
|
||||
Data32 = (UINT32 *)(PropertyPtr->Data);
|
||||
DataSize = SwapBytes32 (*Data32);
|
||||
|
||||
if (AsciiStrCmp (Fvname, "uefi-fv") == 0) {
|
||||
*DxeFv = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)PayloadBase->Entry + (UINTN)DataOffset);
|
||||
ASSERT ((*DxeFv)->FvLength == DataSize);
|
||||
} else {
|
||||
BuildFvHob (((UINTN)PayloadBase->Entry + (UINTN)DataOffset), DataSize);
|
||||
}
|
||||
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
"UPL Multiple fv[%a], Base=0x%08x, size=0x%08x\n",
|
||||
Fvname,
|
||||
((UINTN)PayloadBase->Entry + (UINTN)DataOffset),
|
||||
DataSize
|
||||
));
|
||||
Depth = FdtNodeDepth (Fdt, FvNode);
|
||||
FvNode = FdtNextNode (Fdt, FvNode, &Depth);
|
||||
Fvname = FdtGetName (Fdt, FvNode, &TempLen);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
It will build HOBs based on information from bootloaders.
|
||||
@param[in] BootloaderParameter The starting memory address of bootloader parameter block.
|
||||
@param[out] DxeFv The pointer to the DXE FV in memory.
|
||||
@retval EFI_SUCCESS If it completed successfully.
|
||||
@retval Others If it failed to build required HOBs.
|
||||
**/
|
||||
EFI_STATUS
|
||||
BuildHobs (
|
||||
IN UINTN BootloaderParameter,
|
||||
OUT EFI_FIRMWARE_VOLUME_HEADER **DxeFv
|
||||
)
|
||||
{
|
||||
EFI_PEI_HOB_POINTERS Hob;
|
||||
UINTN MinimalNeededSize;
|
||||
EFI_PHYSICAL_ADDRESS FreeMemoryBottom;
|
||||
EFI_PHYSICAL_ADDRESS FreeMemoryTop;
|
||||
EFI_PHYSICAL_ADDRESS MemoryBottom;
|
||||
EFI_PHYSICAL_ADDRESS MemoryTop;
|
||||
EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob;
|
||||
EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
|
||||
UINT8 *GuidHob;
|
||||
EFI_HOB_FIRMWARE_VOLUME *FvHob;
|
||||
UNIVERSAL_PAYLOAD_ACPI_TABLE *AcpiTable;
|
||||
ACPI_BOARD_INFO *AcpiBoardInfo;
|
||||
EFI_HOB_HANDOFF_INFO_TABLE *HobInfo;
|
||||
|
||||
Hob.Raw = (UINT8 *)BootloaderParameter;
|
||||
MinimalNeededSize = FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
|
||||
|
||||
ASSERT (Hob.Raw != NULL);
|
||||
ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryTop == Hob.HandoffInformationTable->EfiFreeMemoryTop);
|
||||
ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryTop == Hob.HandoffInformationTable->EfiMemoryTop);
|
||||
ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryBottom == Hob.HandoffInformationTable->EfiFreeMemoryBottom);
|
||||
ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryBottom == Hob.HandoffInformationTable->EfiMemoryBottom);
|
||||
|
||||
//
|
||||
// Try to find Resource Descriptor HOB that contains Hob range EfiMemoryBottom..EfiMemoryTop
|
||||
//
|
||||
PhitResourceHob = FindResourceDescriptorByRange (Hob.Raw, Hob.HandoffInformationTable->EfiMemoryBottom, Hob.HandoffInformationTable->EfiMemoryTop);
|
||||
if (PhitResourceHob == NULL) {
|
||||
//
|
||||
// Boot loader's Phit Hob is not in an available Resource Descriptor, find another Resource Descriptor for new Phit Hob
|
||||
//
|
||||
ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, MinimalNeededSize, NULL);
|
||||
if (ResourceHob == NULL) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
MemoryBottom = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize;
|
||||
FreeMemoryBottom = MemoryBottom;
|
||||
FreeMemoryTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength;
|
||||
MemoryTop = FreeMemoryTop;
|
||||
} else if (PhitResourceHob->PhysicalStart + PhitResourceHob->ResourceLength - Hob.HandoffInformationTable->EfiMemoryTop >= MinimalNeededSize) {
|
||||
//
|
||||
// New availiable Memory range in new hob is right above memory top in old hob.
|
||||
//
|
||||
MemoryBottom = Hob.HandoffInformationTable->EfiFreeMemoryTop;
|
||||
FreeMemoryBottom = Hob.HandoffInformationTable->EfiMemoryTop;
|
||||
FreeMemoryTop = FreeMemoryBottom + MinimalNeededSize;
|
||||
MemoryTop = FreeMemoryTop;
|
||||
} else if (Hob.HandoffInformationTable->EfiMemoryBottom - PhitResourceHob->PhysicalStart >= MinimalNeededSize) {
|
||||
//
|
||||
// New availiable Memory range in new hob is right below memory bottom in old hob.
|
||||
//
|
||||
MemoryBottom = Hob.HandoffInformationTable->EfiMemoryBottom - MinimalNeededSize;
|
||||
FreeMemoryBottom = MemoryBottom;
|
||||
FreeMemoryTop = Hob.HandoffInformationTable->EfiMemoryBottom;
|
||||
MemoryTop = Hob.HandoffInformationTable->EfiMemoryTop;
|
||||
} else {
|
||||
//
|
||||
// In the Resource Descriptor HOB contains boot loader Hob, there is no enough free memory size for payload hob
|
||||
// Find another Resource Descriptor Hob
|
||||
//
|
||||
ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, MinimalNeededSize, PhitResourceHob);
|
||||
if (ResourceHob == NULL) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
MemoryBottom = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize;
|
||||
FreeMemoryBottom = MemoryBottom;
|
||||
FreeMemoryTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength;
|
||||
MemoryTop = FreeMemoryTop;
|
||||
}
|
||||
|
||||
HobInfo = HobConstructor ((VOID *)(UINTN)MemoryBottom, (VOID *)(UINTN)MemoryTop, (VOID *)(UINTN)FreeMemoryBottom, (VOID *)(UINTN)FreeMemoryTop);
|
||||
HobInfo->BootMode = Hob.HandoffInformationTable->BootMode;
|
||||
//
|
||||
// From now on, mHobList will point to the new Hob range.
|
||||
//
|
||||
|
||||
//
|
||||
// Create an empty FvHob for the DXE FV that contains DXE core.
|
||||
//
|
||||
BuildFvHob ((EFI_PHYSICAL_ADDRESS)0, 0);
|
||||
//
|
||||
// Since payload created new Hob, move all hobs except PHIT from boot loader hob list.
|
||||
//
|
||||
while (!END_OF_HOB_LIST (Hob)) {
|
||||
if (IsHobNeed (Hob)) {
|
||||
// Add this hob to payload HOB
|
||||
AddNewHob (&Hob);
|
||||
}
|
||||
|
||||
Hob.Raw = GET_NEXT_HOB (Hob);
|
||||
}
|
||||
|
||||
BuildFitLoadablesFvHob (DxeFv);
|
||||
|
||||
//
|
||||
// Create guid hob for acpi board information
|
||||
//
|
||||
GuidHob = GetFirstGuidHob (&gUniversalPayloadAcpiTableGuid);
|
||||
if (GuidHob != NULL) {
|
||||
AcpiTable = (UNIVERSAL_PAYLOAD_ACPI_TABLE *)GET_GUID_HOB_DATA (GuidHob);
|
||||
GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid);
|
||||
if (GuidHob == NULL) {
|
||||
AcpiBoardInfo = BuildHobFromAcpi ((UINT64)AcpiTable->Rsdp);
|
||||
ASSERT (AcpiBoardInfo != NULL);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Update DXE FV information to first fv hob in the hob list, which
|
||||
// is the empty FvHob created before.
|
||||
//
|
||||
FvHob = GetFirstHob (EFI_HOB_TYPE_FV);
|
||||
FvHob->BaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)*DxeFv;
|
||||
FvHob->Length = (*DxeFv)->FvLength;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Entry point to the C language phase of UEFI payload.
|
||||
@param[in] BootloaderParameter The starting address of bootloader parameter block.
|
||||
@retval It will not return if SUCCESS, and return error when passing bootloader parameter.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
_ModuleEntryPoint (
|
||||
IN UINTN BootloaderParameter
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
PHYSICAL_ADDRESS DxeCoreEntryPoint;
|
||||
EFI_PEI_HOB_POINTERS Hob;
|
||||
EFI_FIRMWARE_VOLUME_HEADER *DxeFv;
|
||||
|
||||
mHobList = (VOID *)BootloaderParameter;
|
||||
DxeFv = NULL;
|
||||
// Call constructor for all libraries
|
||||
ProcessLibraryConstructorList ();
|
||||
|
||||
DEBUG ((DEBUG_INFO, "Entering Universal Payload...\n"));
|
||||
DEBUG ((DEBUG_INFO, "sizeof(UINTN) = 0x%x\n", sizeof (UINTN)));
|
||||
|
||||
DEBUG_CODE (
|
||||
//
|
||||
// Dump the Hobs from boot loader
|
||||
//
|
||||
PrintHob (mHobList);
|
||||
);
|
||||
|
||||
// Initialize floating point operating environment to be compliant with UEFI spec.
|
||||
InitializeFloatingPointUnits ();
|
||||
|
||||
// Build HOB based on information from Bootloader
|
||||
Status = BuildHobs (BootloaderParameter, &DxeFv);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
FixUpPcdDatabase (DxeFv);
|
||||
Status = UniversalLoadDxeCore (DxeFv, &DxeCoreEntryPoint);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Mask off all legacy 8259 interrupt sources
|
||||
//
|
||||
IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF);
|
||||
IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF);
|
||||
|
||||
Hob.HandoffInformationTable = (EFI_HOB_HANDOFF_INFO_TABLE *)GetFirstHob (EFI_HOB_TYPE_HANDOFF);
|
||||
HandOffToDxeCore (DxeCoreEntryPoint, Hob);
|
||||
|
||||
// Should not get here
|
||||
CpuDeadLoop ();
|
||||
return EFI_SUCCESS;
|
||||
}
|
98
UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
Normal file
98
UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
Normal file
@@ -0,0 +1,98 @@
|
||||
## @file
|
||||
# This is the first module for UEFI payload.
|
||||
#
|
||||
# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = FitUniversalPayloadEntry
|
||||
FILE_GUID = CED5A8A9-B6EA-4D5A-8689-577EE88566CF
|
||||
MODULE_TYPE = SEC
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64
|
||||
#
|
||||
|
||||
[Sources]
|
||||
FitUniversalPayloadEntry.c
|
||||
LoadDxeCore.c
|
||||
MemoryAllocation.c
|
||||
PrintHob.c
|
||||
AcpiTable.c
|
||||
|
||||
[Sources.Ia32]
|
||||
X64/VirtualMemory.h
|
||||
X64/VirtualMemory.c
|
||||
Ia32/DxeLoadFunc.c
|
||||
Ia32/IdtVectorAsm.nasm
|
||||
|
||||
[Sources.X64]
|
||||
X64/VirtualMemory.h
|
||||
X64/VirtualMemory.c
|
||||
X64/DxeLoadFunc.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
UefiCpuPkg/UefiCpuPkg.dec
|
||||
UefiPayloadPkg/UefiPayloadPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseMemoryLib
|
||||
DebugLib
|
||||
BaseLib
|
||||
SerialPortLib
|
||||
IoLib
|
||||
HobLib
|
||||
PeCoffLib
|
||||
CpuLib
|
||||
FdtLib
|
||||
|
||||
[Guids]
|
||||
gEfiMemoryTypeInformationGuid
|
||||
gEfiFirmwareFileSystem2Guid
|
||||
gEfiGraphicsInfoHobGuid
|
||||
gEfiGraphicsDeviceInfoHobGuid
|
||||
gUefiAcpiBoardInfoGuid
|
||||
gEfiSmbiosTableGuid
|
||||
gUefiSerialPortInfoGuid
|
||||
gUniversalPayloadExtraDataGuid
|
||||
gUniversalPayloadBaseGuid
|
||||
gPcdDataBaseHobGuid
|
||||
gUniversalPayloadSmbiosTableGuid
|
||||
gEfiHobMemoryAllocBspStoreGuid
|
||||
gUniversalPayloadAcpiTableGuid
|
||||
gUniversalPayloadPciRootBridgeInfoGuid
|
||||
gUniversalPayloadSmbios3TableGuid
|
||||
|
||||
[FeaturePcd.IA32]
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES
|
||||
|
||||
[FeaturePcd.X64]
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables ## CONSUMES
|
||||
|
||||
|
||||
[Pcd.IA32,Pcd.X64]
|
||||
gUefiPayloadPkgTokenSpaceGuid.PcdPcdDriverFile
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIMES_CONSUMES
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ## CONSUMES
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask ## CONSUMES
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ## CONSUMES
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize ## CONSUMES
|
||||
|
||||
gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase
|
||||
gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize
|
||||
gUefiPayloadPkgTokenSpaceGuid.PcdSystemMemoryUefiRegionSize
|
||||
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## SOMETIMES_CONSUMES
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy ## SOMETIMES_CONSUMES
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy ## SOMETIMES_CONSUMES
|
Reference in New Issue
Block a user