UefiPayloadPkg: Add FDT Paser relative LIBs.

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4786

Add FDTParser and CustomFdtNodePaser
to retrive all FDT node and create the relate hobs.

Signed-off-by: Linus Liu <linus.liu@intel.com>
This commit is contained in:
Linus Liu 2024-08-21 02:04:12 -07:00 committed by mergify[bot]
parent a297b81b62
commit b0c6b049c4
11 changed files with 2622 additions and 0 deletions

View File

@ -0,0 +1,65 @@
## @file
# Flat Device Tree Table Build Library.
#
# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = BuildFdtLib
FILE_GUID = 5DA69A29-C990-49EE-A4E6-BA5311A1ADAF
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = BuildFdtLib
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64
#
[Sources]
X86_BuildFdtLib.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
UefiPayloadPkg/UefiPayloadPkg.dec
[LibraryClasses]
DebugLib
PcdLib
HobLib
FdtLib
[Guids]
gUniversalPayloadDeviceTreeGuid
gEfiGraphicsInfoHobGuid
gEfiGraphicsDeviceInfoHobGuid
gUniversalPayloadAcpiTableGuid
gUniversalPayloadSerialPortInfoGuid
gEfiHobMemoryAllocModuleGuid
gEfiHobMemoryAllocStackGuid
gEfiHobMemoryAllocBspStoreGuid
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialBaudRate
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterStride
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseMmio
gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
[Ppis]
gEdkiiPeiPciDevicePpiGuid ## CONSUMES
[BuildOptions]
MSFT:*_*_*_CC_FLAGS = /wd4305
GCC:*_*_IA32_CC_FLAGS = -Wno-error=pointer-to-int-cast -Wno-error=int-to-pointer-cast
GCC:*_*_X64_CC_FLAGS = -Wno-error=pointer-to-int-cast -Wno-error=int-to-pointer-cast
GCC:*_*_ARM_CC_FLAGS = -Wno-error=pointer-to-int-cast -Wno-error=int-to-pointer-cast
GCC:*_*_AARCH64_CC_FLAGS = -Wno-error=pointer-to-int-cast -Wno-error=int-to-pointer-cast
GCC:*_*_RISCV64_CC_FLAGS = -Wno-error=pointer-to-int-cast -Wno-error=int-to-pointer-cast
GCC:*_*_LOONGARCH64_CC_FLAGS = -Wno-error=pointer-to-int-cast -Wno-error=int-to-pointer-cast

View File

@ -0,0 +1,945 @@
/** @file
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <PiPei.h>
#include <IndustryStandard/Pci22.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 <Library/IoLib.h>
#include <Library/PrintLib.h>
#include <Library/FdtLib.h>
#include <Library/PciLib.h>
#include <Library/PeiServicesLib.h>
#include <UniversalPayload/UniversalPayload.h>
#include <UniversalPayload/AcpiTable.h>
#include <UniversalPayload/SerialPortInfo.h>
#include <UniversalPayload/PciRootBridges.h>
#include <Guid/GraphicsInfoHob.h>
#include <Guid/UniversalPayloadSerialPortDeviceParentInfo.h>
#include <Guid/UniversalPayloadBase.h>
#include <Protocol/PciRootBridgeIo.h>
#include <Ppi/PciDevice.h>
#define IGD_BUS_NUM 0x00
#define IGD_DEV_NUM 0x02
#define IGD_FUN_NUM 0x00
EDKII_PCI_DEVICE_PPI *mPciDevicePpi;
BOOLEAN mResourceAssigned;
CHAR8 *mMemoryAllocType[] = {
"Reserved",
"LoaderCode",
"LoaderData",
"boot-code",
"boot-data",
"runtime-code",
"runtime-data",
"ConventionalMemory",
"UnusableMemory",
"acpi",
"acpi-nvs",
"mmio",
"MemoryMappedIOPortSpace",
"PalCode",
"PersistentMemory",
};
/**
The wrapper function of PeiServicesLocatePpi() for gEdkiiPeiPciDevicePpiGuid
and Save the PPI to mPciDevicePpi.
@retval EFI_SUCCESS If it locate gEdkiiPeiPciDevicePpiGuid successfully.
@retval EFI_NOT_FOUND If it can't find gEdkiiPeiPciDevicePpiGuid.
**/
EFI_STATUS
EFIAPI
LocatePciDevicePpi (
VOID
)
{
EFI_STATUS Status;
EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor;
mPciDevicePpi = NULL;
Status = PeiServicesLocatePpi (
&gEdkiiPeiPciDevicePpiGuid,
0,
&PpiDescriptor,
(void **)&mPciDevicePpi
);
if (EFI_ERROR (Status) || (mPciDevicePpi == NULL)) {
return EFI_NOT_FOUND;
}
return EFI_SUCCESS;
}
/**
It will build FDT based on memory information from Hobs.
@param[in] FdtBase Address of the Fdt data.
@retval EFI_SUCCESS If it completed successfully.
@retval Others If it failed to build required FDT.
**/
EFI_STATUS
BuildFdtForMemory (
IN VOID *FdtBase
)
{
EFI_STATUS Status;
EFI_PEI_HOB_POINTERS Hob;
EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
VOID *HobStart;
VOID *Fdt;
INT32 TempNode;
CHAR8 TempStr[32];
UINT64 RegTmp[2];
Fdt = FdtBase;
HobStart = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
//
// Scan resource descriptor hobs to set memory nodes
//
for (Hob.Raw = HobStart; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
ResourceHob = Hob.ResourceDescriptor;
// Memory
if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
// DEBUG ((DEBUG_ERROR, "Found hob for memory: base %016lX length %016lX\n", ResourceHob->PhysicalStart, ResourceHob->ResourceLength));
Status = AsciiSPrint (TempStr, sizeof (TempStr), "memory@%lX", ResourceHob->PhysicalStart);
TempNode = FdtAddSubnode (Fdt, 0, TempStr);
ASSERT (TempNode > 0);
RegTmp[0] = CpuToFdt64 (ResourceHob->PhysicalStart);
RegTmp[1] = CpuToFdt64 (ResourceHob->ResourceLength);
Status = FdtSetProp (Fdt, TempNode, "reg", &RegTmp, sizeof (RegTmp));
ASSERT_EFI_ERROR (Status);
Status = FdtSetProp (Fdt, TempNode, "device_type", "memory", (UINT32)(AsciiStrLen ("memory")+1));
ASSERT_EFI_ERROR (Status);
}
}
}
return Status;
}
/**
It will build FDT based on memory allocation information from Hobs.
@param[in] FdtBase Address of the Fdt data.
@retval EFI_SUCCESS If it completed successfully.
@retval Others If it failed to build required FDT.
**/
EFI_STATUS
BuildFdtForMemAlloc (
IN VOID *FdtBase
)
{
EFI_STATUS Status;
EFI_PEI_HOB_POINTERS Hob;
VOID *HobStart;
VOID *Fdt;
INT32 ParentNode;
INT32 TempNode;
CHAR8 TempStr[32];
UINT64 RegTmp[2];
UINT32 AllocMemType;
EFI_GUID *AllocMemName;
UINT8 IsStackHob;
UINT8 IsBspStore;
UINT32 Data32;
Fdt = FdtBase;
ParentNode = FdtAddSubnode (Fdt, 0, "reserved-memory");
ASSERT (ParentNode > 0);
Data32 = CpuToFdt32 (2);
Status = FdtSetProp (Fdt, ParentNode, "#address-cells", &Data32, sizeof (UINT32));
Status = FdtSetProp (Fdt, ParentNode, "#size-cells", &Data32, sizeof (UINT32));
HobStart = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);
//
// Scan memory allocation hobs to set memory type
//
for (Hob.Raw = HobStart; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
AllocMemName = NULL;
IsStackHob = 0;
IsBspStore = 0;
if (CompareGuid (&(Hob.MemoryAllocationModule->MemoryAllocationHeader.Name), &gEfiHobMemoryAllocModuleGuid)) {
continue;
} else if (IsZeroGuid (&(Hob.MemoryAllocationModule->MemoryAllocationHeader.Name)) == FALSE) {
AllocMemName = &(Hob.MemoryAllocationModule->MemoryAllocationHeader.Name);
if (CompareGuid (AllocMemName, &gEfiHobMemoryAllocStackGuid)) {
IsStackHob = 1;
} else if (CompareGuid (AllocMemName, &gEfiHobMemoryAllocBspStoreGuid)) {
IsBspStore = 1;
}
}
DEBUG ((
DEBUG_ERROR,
"Found hob for rsvd memory alloc: base %016lX length %016lX type %x\n",
Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress,
Hob.MemoryAllocation->AllocDescriptor.MemoryLength,
Hob.MemoryAllocation->AllocDescriptor.MemoryType
));
AllocMemType = Hob.MemoryAllocation->AllocDescriptor.MemoryType;
if (IsStackHob == 1) {
Status = AsciiSPrint (
TempStr,
sizeof (TempStr),
"%a@%lX",
"stackhob",
Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress
);
} else if (IsBspStore == 1) {
Status = AsciiSPrint (
TempStr,
sizeof (TempStr),
"%a@%lX",
"bspstore",
Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress
);
} else {
Status = AsciiSPrint (
TempStr,
sizeof (TempStr),
"%a@%lX",
mMemoryAllocType[AllocMemType],
Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress
);
}
if (AsciiStrCmp (mMemoryAllocType[AllocMemType], "ConventionalMemory") == 0) {
continue;
}
if (AsciiStrCmp (mMemoryAllocType[AllocMemType], "mmio") == 0) {
Status = AsciiSPrint (TempStr, sizeof (TempStr), "mmio@%lX", Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress);
} else {
Status = AsciiSPrint (TempStr, sizeof (TempStr), "memory@%lX", Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress);
}
TempNode = FdtAddSubnode (Fdt, ParentNode, TempStr);
DEBUG ((DEBUG_INFO, "FdtAddSubnode %x", TempNode));
if (TempNode < 0) {
continue;
}
RegTmp[0] = CpuToFdt64 (Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress);
RegTmp[1] = CpuToFdt64 (Hob.MemoryAllocation->AllocDescriptor.MemoryLength);
Status = FdtSetProp (Fdt, TempNode, "reg", &RegTmp, sizeof (RegTmp));
ASSERT_EFI_ERROR (Status);
if (!(AsciiStrCmp (mMemoryAllocType[AllocMemType], "mmio") == 0)) {
Status = FdtSetProp (Fdt, TempNode, "compatible", mMemoryAllocType[AllocMemType], (UINT32)(AsciiStrLen (mMemoryAllocType[AllocMemType])+1));
ASSERT_EFI_ERROR (Status);
}
}
}
return Status;
}
/**
It will build FDT based on serial information.
@param[in] ISANode ISANode.
@param[in] FdtBase Address of the Fdt data.
@retval EFI_SUCCESS If it completed successfully.
@retval Others If it failed to build required FDT.
**/
EFI_STATUS
BuildFdtForSerial (
IN INT32 ISANode,
IN VOID *FdtBase
)
{
EFI_STATUS Status;
VOID *Fdt;
INT32 TempNode;
UINT64 RegisterBase;
CHAR8 TempStr[32];
UINT32 RegData[3];
UINT32 Data32;
UINT64 Data64;
Fdt = FdtBase;
RegisterBase = 0;
//
// Create SerialPortInfo FDT node.
//
Status = AsciiSPrint (TempStr, sizeof (TempStr), "serial@%lX", (RegisterBase == 0) ? PcdGet64 (PcdSerialRegisterBase) : RegisterBase);
TempNode = FdtAddSubnode (Fdt, ISANode, TempStr);
ASSERT (TempNode > 0);
Data32 = CpuToFdt32 (PcdGet32 (PcdSerialBaudRate));
Status = FdtSetProp (Fdt, TempNode, "current-speed", &Data32, sizeof (Data32));
ASSERT_EFI_ERROR (Status);
if (PcdGetBool (PcdSerialUseMmio)) {
Data32 = 0;
RegData[0] = CpuToFdt32 (Data32);
} else {
Data32 = 1;
RegData[0] = CpuToFdt32 (Data32);
}
Data64 = (RegisterBase == 0) ? PcdGet64 (PcdSerialRegisterBase) : RegisterBase;
Data32 = (UINT32)((Data64 & 0x0FFFFFFFF));
RegData[1] = CpuToFdt32 (Data32);
RegData[2] = CpuToFdt32 (8);
Status = FdtSetProp (Fdt, TempNode, "reg", &RegData, sizeof (RegData));
ASSERT_EFI_ERROR (Status);
Data32 = CpuToFdt32 (1);
Status = FdtSetProp (Fdt, TempNode, "reg-io-width", &Data32, sizeof (Data32));
ASSERT_EFI_ERROR (Status);
Status = FdtSetProp (Fdt, TempNode, "compatible", "isa", (UINT32)(AsciiStrLen ("isa")+1));
ASSERT_EFI_ERROR (Status);
return Status;
}
/**
It will build FDT based on serial information.
@param[in] ISANode ISANode.
@param[in] FdtBase Address of the Fdt data.
@retval EFI_SUCCESS If it completed successfully.
@retval Others If it failed to build required FDT.
**/
EFI_STATUS
BuildFdtForSerialLpss (
IN INT32 ISANode,
IN VOID *FdtBase
)
{
EFI_HOB_GUID_TYPE *GuidHob;
EFI_STATUS Status;
UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo;
VOID *Fdt;
INT32 TempNode;
UINT32 Data32;
UINT32 RegData[2];
CHAR8 TempStr[32];
Status = EFI_SUCCESS;
SerialPortInfo = NULL;
Fdt = FdtBase;
DEBUG ((DEBUG_INFO, "BuildFdtForSerialLpss start \n"));
GuidHob = GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid);
while (GuidHob != NULL) {
SerialPortInfo = (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HOB_DATA (GuidHob);
if (!SerialPortInfo->UseMmio) {
GuidHob = GET_NEXT_HOB (GuidHob);
GuidHob = GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, GuidHob);
continue;
}
DEBUG ((DEBUG_INFO, "Create SerialPortInfo LPSS FDT node \n"));
//
// Create SerialPortInfo FDT node.
//
Status = AsciiSPrint (TempStr, sizeof (TempStr), "serial@%lX", SerialPortInfo->RegisterBase);
TempNode = FdtAddSubnode (Fdt, ISANode, TempStr);
ASSERT (TempNode > 0);
Data32 = CpuToFdt32 (SerialPortInfo->BaudRate);
Status = FdtSetProp (Fdt, TempNode, "current-speed", &Data32, sizeof (Data32));
ASSERT_EFI_ERROR (Status);
RegData[0] = CpuToFdt32 ((UINT32)SerialPortInfo->RegisterBase);
RegData[1] = CpuToFdt32 (0x80);
Status = FdtSetProp (Fdt, TempNode, "reg", &RegData, sizeof (RegData));
ASSERT_EFI_ERROR (Status);
Data32 = CpuToFdt32 (4);
Status = FdtSetProp (Fdt, TempNode, "reg-io-width", &Data32, sizeof (Data32));
ASSERT_EFI_ERROR (Status);
Status = FdtSetProp (Fdt, TempNode, "compatible", "ns16550a", (UINT32)(AsciiStrLen ("ns16550a")+1));
ASSERT_EFI_ERROR (Status);
GuidHob = GET_NEXT_HOB (GuidHob);
GuidHob = GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, GuidHob);
}
return Status;
}
/**
It will build FDT based on BuildFdtForPciRootBridge information.
@param[in] FdtBase Address of the Fdt data.
@retval EFI_SUCCESS If it completed successfully.
@retval Others If it failed to build required FDT.
**/
EFI_STATUS
BuildFdtForPciRootBridge (
IN VOID *FdtBase
)
{
EFI_STATUS Status;
VOID *Fdt;
INT32 TempNode;
INT32 GmaNode;
INT32 eSPINode;
CHAR8 TempStr[32];
CHAR8 GmaStr[32];
CHAR8 eSPIStr[32];
UINT32 RegTmp[2];
UINT32 RegData[21];
UINT32 DMARegData[8];
UINT32 Data32;
UINT64 Data64;
UINT8 BusNumber;
UINT8 BusLimit;
UINT8 BusBase;
UINT8 DevBase;
UINT8 FunBase;
EFI_HOB_GUID_TYPE *GuidHob;
UNIVERSAL_PAYLOAD_GENERIC_HEADER *GenericHeader;
UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES *PciRootBridgeInfo;
UINT8 Index;
PCI_TYPE00 PciData;
UNIVERSAL_PAYLOAD_SERIAL_PORT_PARENT_DEVICE_INFO *SerialParent;
Fdt = FdtBase;
BusNumber = 0;
BusLimit = 0;
BusBase = 0x80;
DevBase = 0x31;
FunBase = 0;
Status = EFI_SUCCESS;
PciRootBridgeInfo = NULL;
DEBUG ((DEBUG_INFO, "%a: #1 \n", __func__));
//
// Create BuildFdtForPciRootBridge FDT node.
//
GuidHob = GetFirstGuidHob (&gUniversalPayloadPciRootBridgeInfoGuid);
if (GuidHob != NULL) {
GenericHeader = (UNIVERSAL_PAYLOAD_GENERIC_HEADER *)GET_GUID_HOB_DATA (GuidHob);
if ((sizeof (UNIVERSAL_PAYLOAD_GENERIC_HEADER) <= GET_GUID_HOB_DATA_SIZE (GuidHob)) && (GenericHeader->Length <= GET_GUID_HOB_DATA_SIZE (GuidHob))) {
if ((GenericHeader->Revision == UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES_REVISION) && (GenericHeader->Length >= sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES))) {
DEBUG ((DEBUG_INFO, "%a: #2 \n", __func__));
//
// UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES structure is used when Revision equals to UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES_REVISION
//
PciRootBridgeInfo = (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES *)GET_GUID_HOB_DATA (GuidHob);
}
}
}
GuidHob = GetFirstGuidHob (&gUniversalPayloadSerialPortParentDeviceInfoGuid);
if (GuidHob != NULL) {
SerialParent = (UNIVERSAL_PAYLOAD_SERIAL_PORT_PARENT_DEVICE_INFO *)GET_GUID_HOB_DATA (GuidHob);
BusBase = (SerialParent->ParentDevicePcieBaseAddress >> 20) & 0xFF;
DevBase = (SerialParent->ParentDevicePcieBaseAddress >> 15) & 0x1F;
FunBase = (SerialParent->ParentDevicePcieBaseAddress >> 12) & 0x07;
}
DEBUG ((DEBUG_INFO, "PciRootBridgeInfo->Count %x\n", PciRootBridgeInfo->Count));
DEBUG ((DEBUG_INFO, "PciRootBridge->Segment %x, \n", PciRootBridgeInfo->RootBridge[0].Segment));
DEBUG ((DEBUG_INFO, "PciRootBridge->Bus.Base %x, \n", PciRootBridgeInfo->RootBridge[0].Bus.Base));
DEBUG ((DEBUG_INFO, "PciRootBridge->Bus.limit %x, \n", PciRootBridgeInfo->RootBridge[0].Bus.Limit));
DEBUG ((DEBUG_INFO, "PciRootBridge->Mem.Base %x, \n", PciRootBridgeInfo->RootBridge[0].Mem.Base));
DEBUG ((DEBUG_INFO, "PciRootBridge->Mem.limit %x, \n", PciRootBridgeInfo->RootBridge[0].Mem.Limit));
DEBUG ((DEBUG_INFO, "PciRootBridge->MemAbove4G.Base %llx, \n", PciRootBridgeInfo->RootBridge[0].MemAbove4G.Base));
DEBUG ((DEBUG_INFO, "PciRootBridge->MemAbove4G.limit %llx, \n", PciRootBridgeInfo->RootBridge[0].MemAbove4G.Limit));
DEBUG ((DEBUG_INFO, "PciRootBridge->PMem.Base %llx, \n", PciRootBridgeInfo->RootBridge[0].PMem.Base));
DEBUG ((DEBUG_INFO, "PciRootBridge->PMem.limit %llx, \n", PciRootBridgeInfo->RootBridge[0].PMem.Limit));
DEBUG ((DEBUG_INFO, "PciRootBridge->Bus.Base %x, \n", PciRootBridgeInfo->RootBridge[1].Bus.Base));
DEBUG ((DEBUG_INFO, "PciRootBridge->Bus.limit %x, \n", PciRootBridgeInfo->RootBridge[1].Bus.Limit));
DEBUG ((DEBUG_INFO, "PciRootBridge->Mem.Base %x, \n", PciRootBridgeInfo->RootBridge[1].Mem.Base));
DEBUG ((DEBUG_INFO, "PciRootBridge->Mem.limit %x, \n", PciRootBridgeInfo->RootBridge[1].Mem.Limit));
DEBUG ((DEBUG_INFO, "PciRootBridge->MemAbove4G.Base %llx, \n", PciRootBridgeInfo->RootBridge[1].MemAbove4G.Base));
DEBUG ((DEBUG_INFO, "PciRootBridge->MemAbove4G.limit %llx, \n", PciRootBridgeInfo->RootBridge[1].MemAbove4G.Limit));
DEBUG ((DEBUG_INFO, "PciRootBridge->PMem.Base %x, \n", PciRootBridgeInfo->RootBridge[1].PMem.Base));
DEBUG ((DEBUG_INFO, "PciRootBridge->PMem.limit %x, \n", PciRootBridgeInfo->RootBridge[1].PMem.Limit));
if (PciRootBridgeInfo != NULL) {
for (Index = 0; Index < PciRootBridgeInfo->Count; Index++) {
UINTN PciExpressBaseAddress;
mResourceAssigned = PciRootBridgeInfo->ResourceAssigned;
PciExpressBaseAddress = PcdGet64 (PcdPciExpressBaseAddress) + (PCI_LIB_ADDRESS (PciRootBridgeInfo->RootBridge[Index].Bus.Base, 0, 0, 0));
Status = AsciiSPrint (TempStr, sizeof (TempStr), "pci-rb%d@%lX", Index, PciExpressBaseAddress);
TempNode = FdtAddSubnode (Fdt, 0, TempStr);
ASSERT (TempNode > 0);
SetMem (RegData, sizeof (RegData), 0);
// non-reloc/non-prefetch/mmio, child-addr, parent-addr, length
Data32 = (N_NON_RELOCATABLE + SS_32BIT_MEMORY_SPACE);
RegData[0] = CpuToFdt32 (Data32);
DEBUG ((DEBUG_INFO, "PciRootBridge->Mem.Base RegData[0] %x, \n", Data32));
// child-addr
RegData[1] = CpuToFdt32 (0);
Data32 = (UINT32)PciRootBridgeInfo->RootBridge[Index].Mem.Base;
RegData[2] = CpuToFdt32 (Data32);
DEBUG ((DEBUG_INFO, "PciRootBridge->Mem.Base RegData[2] %x, \n", Data32));
// parent-addr
RegData[3] = CpuToFdt32 (0);
RegData[4] = CpuToFdt32 (Data32);
DEBUG ((DEBUG_INFO, "PciRootBridge->Mem.Base RegData[4] %x, \n", Data32));
// size
Data64 = (PciRootBridgeInfo->RootBridge[Index].Mem.Limit - PciRootBridgeInfo->RootBridge[Index].Mem.Base + 1);
if (Data64 & 0xFFFFFFFF00000000) {
Data32 = (UINT32)RShiftU64 ((Data64 & 0xFFFFFFFF00000000), 31);
} else {
Data32 = 0;
}
DEBUG ((DEBUG_INFO, "PciRootBridge->Mem.size RegData[5] %x, \n", Data32));
RegData[5] = CpuToFdt32 (Data32);
Data32 = (UINT32)((Data64 & 0x0FFFFFFFF));
DEBUG ((DEBUG_INFO, "PciRootBridge->Mem.size RegData[6] %x, \n", Data32));
RegData[6] = CpuToFdt32 (Data32);
// non-reloc/non-prefetch/64 mmio, child-addr, parent-addr, length
Data32 = (N_NON_RELOCATABLE + SS_64BIT_MEMORY_SPACE);
RegData[7] = CpuToFdt32 (Data32);
DEBUG ((DEBUG_INFO, "PciRootBridge->MemAbove4G.Base RegData[7] %x, \n", Data32));
// child-addr
Data64 = PciRootBridgeInfo->RootBridge[Index].MemAbove4G.Base;
Data32 = (UINT32)RShiftU64 ((Data64 & 0xFFFFFFFF00000000), 32);
RegData[8] = CpuToFdt32 (Data32);
DEBUG ((DEBUG_INFO, "PciRootBridge->MemAbove4G.Base RegData[8] %x, \n", Data32));
Data32 = (UINT32)((Data64 & 0x0FFFFFFFF));
RegData[9] = CpuToFdt32 (Data32);
DEBUG ((DEBUG_INFO, "PciRootBridge->MemAbove4G.Base RegData[9] %x, \n", Data32));
// parent-addr
RegData[10] = RegData[8];
RegData[11] = RegData[9];
// size
Data64 = (PciRootBridgeInfo->RootBridge[Index].MemAbove4G.Limit - PciRootBridgeInfo->RootBridge[Index].MemAbove4G.Base + 1);
if (Data64 & 0xFFFFFFFF00000000) {
Data32 = (UINT32)RShiftU64 ((Data64 & 0xFFFFFFFF00000000), 32);
} else {
Data32 = 0;
}
RegData[12] = CpuToFdt32 (Data32);
DEBUG ((DEBUG_INFO, "PciRootBridge->MemAbove4G.size RegData[12] %x, \n", Data32));
Data32 = (UINT32)((Data64 & 0x0FFFFFFFF));
RegData[13] = CpuToFdt32 (Data32);
DEBUG ((DEBUG_INFO, "PciRootBridge->MemAbove4G.size RegData[13] %x, \n", Data32));
// non-reloc/32bit/io, child-addr, parent-addr, length
Data32 = (N_NON_RELOCATABLE + SS_IO_SPACE);
RegData[14] = CpuToFdt32 (Data32);
DEBUG ((DEBUG_INFO, "PciRootBridge->Io.base RegData[14] %x, \n", Data32));
Data32 = (UINT32)PciRootBridgeInfo->RootBridge[Index].Io.Base;
// child-addr
RegData[15] = CpuToFdt32 (0);
RegData[16] = CpuToFdt32 (Data32);
DEBUG ((DEBUG_INFO, "PciRootBridge->Io.base RegData[16] %x, \n", Data32));
// parent-addr
RegData[17] = CpuToFdt32 (0);
RegData[18] = CpuToFdt32 (Data32);
// size
Data64 = (PciRootBridgeInfo->RootBridge[Index].Io.Limit - PciRootBridgeInfo->RootBridge[Index].Io.Base + 1);
if (Data64 & 0xFFFFFFFF00000000) {
Data32 = (UINT32)RShiftU64 ((Data64 & 0xFFFFFFFF00000000), 32);
} else {
Data32 = 0;
}
RegData[19] = CpuToFdt32 (Data32);
DEBUG ((DEBUG_INFO, "PciRootBridge->Io.base size [19] %x, \n", Data32));
Data32 = (UINT32)((Data64 & 0x0FFFFFFFF));
RegData[20] = CpuToFdt32 (Data32);
DEBUG ((DEBUG_INFO, "PciRootBridge->Io.base size [20] %x, \n", Data32));
Status = FdtSetProp (Fdt, TempNode, "ranges", &RegData, sizeof (RegData));
ASSERT_EFI_ERROR (Status);
// non-reloc/non-prefetch/memory, child-addr, parent-addr, length
// indicate rb1 does not support above 4GB DMA
Data32 = (N_NON_RELOCATABLE + SS_32BIT_MEMORY_SPACE);
DMARegData[0] = CpuToFdt32 (Data32);
DEBUG ((DEBUG_INFO, "PciRootBridge->DMA base RegData[0] %x, \n", Data32));
// child-addr
DMARegData[2] = CpuToFdt32 (0);
DMARegData[3] = CpuToFdt32 (0);
// parent-addr
DMARegData[4] = CpuToFdt32 (0);
DMARegData[5] = CpuToFdt32 (0);
// size
DMARegData[6] = CpuToFdt32 (1);
DMARegData[7] = CpuToFdt32 (0);
Status = FdtSetProp (Fdt, TempNode, "dma-ranges", &DMARegData, sizeof (DMARegData));
ASSERT_EFI_ERROR (Status);
Data32 = CpuToFdt32 (2);
Status = FdtSetProp (Fdt, TempNode, "#size-cells", &Data32, sizeof (UINT32));
Data32 = CpuToFdt32 (3);
Status = FdtSetProp (Fdt, TempNode, "#address-cells", &Data32, sizeof (UINT32));
BusNumber = PciRootBridgeInfo->RootBridge[Index].Bus.Base & 0xFF;
RegTmp[0] = CpuToFdt32 (BusNumber);
BusLimit = PciRootBridgeInfo->RootBridge[Index].Bus.Limit & 0xFF;
RegTmp[1] = CpuToFdt32 (BusLimit);
DEBUG ((DEBUG_INFO, "PciRootBridge->BusNumber %x, \n", BusNumber));
DEBUG ((DEBUG_INFO, "PciRootBridge->BusLimit %x, \n", BusLimit));
Status = FdtSetProp (Fdt, TempNode, "bus-range", &RegTmp, sizeof (RegTmp));
ASSERT_EFI_ERROR (Status);
Status = FdtSetProp (Fdt, TempNode, "compatible", "pci-rb", (UINT32)(AsciiStrLen ("pci-rb")+1));
ASSERT_EFI_ERROR (Status);
if (Index == 0) {
PciExpressBaseAddress = PcdGet64 (PcdPciExpressBaseAddress) + (PCI_LIB_ADDRESS (IGD_BUS_NUM, IGD_DEV_NUM, IGD_FUN_NUM, 0));
Status = AsciiSPrint (GmaStr, sizeof (GmaStr), "gma@%lX", PciExpressBaseAddress);
GmaNode = FdtAddSubnode (Fdt, TempNode, GmaStr);
Status = LocatePciDevicePpi ();
if (!EFI_ERROR (Status)) {
Status = mPciDevicePpi->PciIo.Pci.Read (
&mPciDevicePpi->PciIo,
(EFI_PCI_IO_PROTOCOL_WIDTH)EfiPciWidthUint16,
PCI_VENDOR_ID_OFFSET,
sizeof (PciData.Hdr.VendorId),
&(PciData.Hdr.VendorId)
);
Status = mPciDevicePpi->PciIo.Pci.Read (
&mPciDevicePpi->PciIo,
(EFI_PCI_IO_PROTOCOL_WIDTH)EfiPciWidthUint16,
PCI_DEVICE_ID_OFFSET,
sizeof (PciData.Hdr.DeviceId),
&(PciData.Hdr.DeviceId)
);
Status = mPciDevicePpi->PciIo.Pci.Read (
&mPciDevicePpi->PciIo,
(EFI_PCI_IO_PROTOCOL_WIDTH)EfiPciWidthUint8,
PCI_REVISION_ID_OFFSET,
sizeof (PciData.Hdr.RevisionID),
&(PciData.Hdr.RevisionID)
);
Status = mPciDevicePpi->PciIo.Pci.Read (
&mPciDevicePpi->PciIo,
(EFI_PCI_IO_PROTOCOL_WIDTH)EfiPciWidthUint16,
PCI_SVID_OFFSET,
sizeof (PciData.Device.SubsystemVendorID),
&(PciData.Device.SubsystemVendorID)
);
Status = mPciDevicePpi->PciIo.Pci.Read (
&mPciDevicePpi->PciIo,
(EFI_PCI_IO_PROTOCOL_WIDTH)EfiPciWidthUint16,
PCI_SID_OFFSET,
sizeof (PciData.Device.SubsystemID),
&(PciData.Device.SubsystemID)
);
}
Data32 = CpuToFdt32 (PciData.Device.SubsystemID);
Status = FdtSetProp (Fdt, GmaNode, "subsystem-id", &Data32, sizeof (UINT32));
Data32 = CpuToFdt32 (PciData.Device.SubsystemVendorID);
Status = FdtSetProp (Fdt, GmaNode, "subsystem-vendor-id", &Data32, sizeof (UINT32));
Data32 = CpuToFdt32 (PciData.Hdr.RevisionID);
Status = FdtSetProp (Fdt, GmaNode, "revision-id", &Data32, sizeof (UINT32));
Data32 = CpuToFdt32 (PciData.Hdr.DeviceId);
Status = FdtSetProp (Fdt, GmaNode, "device-id", &Data32, sizeof (UINT32));
Data32 = CpuToFdt32 (PciData.Hdr.VendorId);
Status = FdtSetProp (Fdt, GmaNode, "vendor-id", &Data32, sizeof (UINT32));
}
if (SerialParent != NULL) {
DEBUG ((DEBUG_INFO, "SerialParent->IsIsaCompatible :%x , SerialParent->ParentDevicePcieBaseAddress :%x\n", SerialParent->IsIsaCompatible, SerialParent->ParentDevicePcieBaseAddress));
DEBUG ((DEBUG_INFO, "BusBase :%x , PciRootBridgeInfo->RootBridge[Index].Bus.Base :%x\n", BusBase, PciRootBridgeInfo->RootBridge[Index].Bus.Base));
}
{
if ((BusBase >= PciRootBridgeInfo->RootBridge[Index].Bus.Base) && (BusBase <= PciRootBridgeInfo->RootBridge[Index].Bus.Limit)) {
eSPINode = TempNode;
if (SerialParent != NULL) {
if (SerialParent->IsIsaCompatible) {
Status = AsciiSPrint (eSPIStr, sizeof (eSPIStr), "isa@%X,%X", DevBase, FunBase);
eSPINode = FdtAddSubnode (Fdt, TempNode, eSPIStr);
Status = FdtSetProp (Fdt, eSPINode, "compatible", "isa", (UINT32)(AsciiStrLen ("isa")+1));
ASSERT_EFI_ERROR (Status);
Data32 = CpuToFdt32 (1);
Status = FdtSetProp (Fdt, eSPINode, "#size-cells", &Data32, sizeof (UINT32));
Data32 = CpuToFdt32 (2);
Status = FdtSetProp (Fdt, eSPINode, "#address-cells", &Data32, sizeof (UINT32));
Status = BuildFdtForSerial (eSPINode, FdtBase);
ASSERT_EFI_ERROR (Status);
}
} else {
Status = BuildFdtForSerialLpss (eSPINode, FdtBase);
ASSERT_EFI_ERROR (Status);
}
}
}
}
}
DEBUG ((DEBUG_INFO, "%a: #3 \n", __func__));
return Status;
}
/**
It will build FDT based on FrameBuffer.
@param[in] FdtBase Address of the Fdt data.
@retval EFI_SUCCESS If it completed successfully.
@retval Others If it failed to build required FDT.
**/
EFI_STATUS
BuildFdtForFrameBuffer (
IN VOID *FdtBase
)
{
EFI_STATUS Status;
VOID *Fdt;
INT32 TempNode;
UINT32 Data32;
CHAR8 TempStr[32];
UINT64 RegData[2];
EFI_HOB_GUID_TYPE *GuidHob;
EFI_PEI_GRAPHICS_INFO_HOB *GraphicsInfo;
Fdt = FdtBase;
GuidHob = GetFirstGuidHob (&gEfiGraphicsInfoHobGuid);
if (GuidHob != NULL) {
GraphicsInfo = (EFI_PEI_GRAPHICS_INFO_HOB *)(GET_GUID_HOB_DATA (GuidHob));
Status = AsciiSPrint (TempStr, sizeof (TempStr), "framebuffer@%lX", GraphicsInfo->FrameBufferBase);
TempNode = FdtAddSubnode (Fdt, 0, TempStr);
ASSERT (TempNode > 0);
Status = FdtSetProp (Fdt, TempNode, "display", "&gma", (UINT32)(AsciiStrLen ("&gma")+1));
ASSERT_EFI_ERROR (Status);
Status = FdtSetProp (Fdt, TempNode, "format", "a8r8g8b8", (UINT32)(AsciiStrLen ("a8r8g8b8")+1));
ASSERT_EFI_ERROR (Status);
Data32 = CpuToFdt32 (GraphicsInfo->GraphicsMode.VerticalResolution);
Status = FdtSetProp (Fdt, TempNode, "height", &Data32, sizeof (UINT32));
ASSERT_EFI_ERROR (Status);
Data32 = CpuToFdt32 (GraphicsInfo->GraphicsMode.HorizontalResolution);
Status = FdtSetProp (Fdt, TempNode, "width", &Data32, sizeof (UINT32));
ASSERT_EFI_ERROR (Status);
RegData[0] = CpuToFdt64 (GraphicsInfo->FrameBufferBase);
RegData[1] = CpuToFdt64 (GraphicsInfo->FrameBufferSize);
Status = FdtSetProp (Fdt, TempNode, "reg", &RegData, sizeof (RegData));
ASSERT_EFI_ERROR (Status);
Status = FdtSetProp (Fdt, TempNode, "compatible", "simple-framebuffer", (UINT32)(AsciiStrLen ("simple-framebuffer")+1));
ASSERT_EFI_ERROR (Status);
} else {
Status = AsciiSPrint (TempStr, sizeof (TempStr), "framebuffer@%lX", 0xB0000000);
TempNode = FdtAddSubnode (Fdt, 0, TempStr);
ASSERT (TempNode > 0);
Status = FdtSetProp (Fdt, TempNode, "display", "&gma", (UINT32)(AsciiStrLen ("&gma")+1));
ASSERT_EFI_ERROR (Status);
Status = FdtSetProp (Fdt, TempNode, "format", "a8r8g8b8", (UINT32)(AsciiStrLen ("a8r8g8b8")+1));
ASSERT_EFI_ERROR (Status);
Data32 = CpuToFdt32 (1024);
Status = FdtSetProp (Fdt, TempNode, "height", &Data32, sizeof (UINT32));
ASSERT_EFI_ERROR (Status);
Data32 = CpuToFdt32 (1280);
Status = FdtSetProp (Fdt, TempNode, "width", &Data32, sizeof (UINT32));
ASSERT_EFI_ERROR (Status);
RegData[0] = CpuToFdt64 (0xB0000000);
RegData[1] = CpuToFdt64 (0x500000);
Status = FdtSetProp (Fdt, TempNode, "reg", &RegData, sizeof (RegData));
ASSERT_EFI_ERROR (Status);
Status = FdtSetProp (Fdt, TempNode, "compatible", "simple-framebuffer", (UINT32)(AsciiStrLen ("simple-framebuffer")+1));
ASSERT_EFI_ERROR (Status);
}
return Status;
}
/**
It will build FDT for UPL required data.
@param[in] FdtBase Address of the Fdt data.
@retval EFI_SUCCESS If it completed successfully.
@retval Others If it failed to build required FDT.
**/
EFI_STATUS
BuildFdtForUplRequired (
IN VOID *FdtBase
)
{
EFI_STATUS Status;
VOID *Fdt;
VOID *Fit;
INT32 ParentNode;
INT32 CustomNode;
INT32 UPLParaNode;
INT32 UPLImageNode;
EFI_HOB_CPU *CpuHob;
UINT64 Data64;
UINT32 Data32;
VOID *HobPtr;
EFI_BOOT_MODE BootMode;
CHAR8 TempStr[32];
UINT8 *GuidHob;
UNIVERSAL_PAYLOAD_BASE *PayloadBase;
Fdt = FdtBase;
Fit = NULL;
//
// Create Hob list FDT node.
//
ParentNode = FdtAddSubnode (Fdt, 0, "options");
ASSERT (ParentNode > 0);
UPLParaNode = FdtAddSubnode (Fdt, ParentNode, "upl-params");
ASSERT (UPLParaNode > 0);
//
// Create CPU info FDT node
//
CpuHob = GetFirstHob (EFI_HOB_TYPE_CPU);
ASSERT (CpuHob != NULL);
if (mResourceAssigned) {
Status = FdtSetProp (Fdt, UPLParaNode, "pci-enum-done", NULL, 0);
ASSERT_EFI_ERROR (Status);
}
BootMode = GetBootModeHob ();
Data32 = CpuToFdt32 ((UINT32)CpuHob->SizeOfMemorySpace);
Status = FdtSetProp (Fdt, UPLParaNode, "addr-width", &Data32, sizeof (Data32));
ASSERT_EFI_ERROR (Status);
if (BootMode == BOOT_WITH_FULL_CONFIGURATION) {
Status = FdtSetProp (Fdt, UPLParaNode, "boot-mode", "normal", (UINT32)(AsciiStrLen ("normal")+1));
} else if (BootMode == BOOT_WITH_MINIMAL_CONFIGURATION) {
Status = FdtSetProp (Fdt, UPLParaNode, "boot-mode", "fast", (UINT32)(AsciiStrLen ("fast")+1));
} else if (BootMode == BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS) {
Status = FdtSetProp (Fdt, UPLParaNode, "boot-mode", "full", (UINT32)(AsciiStrLen ("full")+1));
} else if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {
Status = FdtSetProp (Fdt, UPLParaNode, "boot-mode", "default", (UINT32)(AsciiStrLen ("default")+1));
} else if (BootMode == BOOT_ON_S4_RESUME) {
Status = FdtSetProp (Fdt, UPLParaNode, "boot-mode", "s4", (UINT32)(AsciiStrLen ("s4")+1));
} else if (BootMode == BOOT_ON_S3_RESUME) {
Status = FdtSetProp (Fdt, UPLParaNode, "boot-mode", "s3", (UINT32)(AsciiStrLen ("s3")+1));
} else {
Status = FdtSetProp (Fdt, UPLParaNode, "boot-mode", "na", (UINT32)(AsciiStrLen ("na")+1));
}
ASSERT_EFI_ERROR (Status);
Status = FdtSetProp (Fdt, UPLParaNode, "compatible", "upl", (UINT32)(AsciiStrLen ("upl")+1));
ASSERT_EFI_ERROR (Status);
GuidHob = GetFirstGuidHob (&gUniversalPayloadBaseGuid);
if (GuidHob != NULL) {
PayloadBase = (UNIVERSAL_PAYLOAD_BASE *)GET_GUID_HOB_DATA (GuidHob);
Fit = (VOID *)(UINTN)PayloadBase->Entry;
DEBUG ((DEBUG_INFO, "PayloadBase Entry = 0x%08x\n", PayloadBase->Entry));
Status = AsciiSPrint (TempStr, sizeof (TempStr), "upl-images@%lX", (UINTN)(Fit));
UPLImageNode = FdtAddSubnode (Fdt, ParentNode, TempStr);
Data64 = CpuToFdt64 ((UINTN)Fit);
Status = FdtSetProp (FdtBase, UPLImageNode, "addr", &Data64, sizeof (Data64));
}
CustomNode = FdtAddSubnode (Fdt, ParentNode, "upl-custom");
ASSERT (CustomNode > 0);
HobPtr = GetHobList ();
Data64 = CpuToFdt64 ((UINT64)(EFI_PHYSICAL_ADDRESS)HobPtr);
Status = FdtSetProp (Fdt, CustomNode, "hoblistptr", &Data64, sizeof (Data64));
ASSERT_EFI_ERROR (Status);
return Status;
}
/**
It will build FDT for UPL consumed.
@param[in] FdtBase Address of the Fdt data.
@retval EFI_SUCCESS If it completed successfully.
@retval Others If it failed to build required FDT.
**/
EFI_STATUS
BuildFdtForUPL (
IN VOID *FdtBase
)
{
EFI_STATUS Status;
//
// Build FDT for memory related
//
Status = BuildFdtForMemory (FdtBase);
ASSERT_EFI_ERROR (Status);
Status = BuildFdtForMemAlloc (FdtBase);
ASSERT_EFI_ERROR (Status);
Status = BuildFdtForPciRootBridge (FdtBase);
ASSERT_EFI_ERROR (Status);
Status = BuildFdtForFrameBuffer (FdtBase);
ASSERT_EFI_ERROR (Status);
Status = BuildFdtForUplRequired (FdtBase);
ASSERT_EFI_ERROR (Status);
return Status;
}

View File

@ -0,0 +1,164 @@
/** @file
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <PiPei.h>
#include <Pi/PiHob.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Library/IoLib.h>
#include <Library/PrintLib.h>
#include <Library/FdtLib.h>
#include <Library/HobLib.h>
#include <Library/PcdLib.h>
/**
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
);
/**
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
);
/**
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
EFIAPI
FitIsHobNeed (
EFI_PEI_HOB_POINTERS Hob
)
{
if (FixedPcdGetBool (PcdHandOffFdtEnable)) {
if (Hob.Header->HobType == EFI_HOB_TYPE_HANDOFF) {
return FALSE;
}
if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
if (CompareGuid (&Hob.MemoryAllocation->AllocDescriptor.Name, &gUniversalPayloadDeviceTreeGuid)) {
return FALSE;
}
if (CompareGuid (&Hob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) {
return FALSE;
}
if ((Hob.MemoryAllocation->AllocDescriptor.MemoryType == EfiReservedMemoryType) ||
(Hob.MemoryAllocation->AllocDescriptor.MemoryType == EfiBootServicesCode) ||
(Hob.MemoryAllocation->AllocDescriptor.MemoryType == EfiBootServicesData) ||
(Hob.MemoryAllocation->AllocDescriptor.MemoryType == EfiRuntimeServicesCode) ||
(Hob.MemoryAllocation->AllocDescriptor.MemoryType == EfiRuntimeServicesData) ||
(Hob.MemoryAllocation->AllocDescriptor.MemoryType == EfiACPIReclaimMemory) ||
(Hob.MemoryAllocation->AllocDescriptor.MemoryType == EfiACPIMemoryNVS))
{
return FALSE;
}
}
if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
return FALSE;
}
}
if (Hob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION) {
if (CompareGuid (&Hob.Guid->Name, &gUniversalPayloadSerialPortInfoGuid)) {
return FALSE;
}
if (CompareGuid (&Hob.Guid->Name, &gUniversalPayloadAcpiTableGuid)) {
return FALSE;
}
if (CompareGuid (&Hob.Guid->Name, &gUniversalPayloadPciRootBridgeInfoGuid)) {
return FALSE;
}
}
}
// Arrive here mean the HOB is need
return TRUE;
}
/**
It will Parse FDT -custom node based on information from bootloaders.
@param[in] FdtBase The starting memory address of FdtBase
@param[in] HobList The starting memory address of New Hob list.
**/
UINTN
EFIAPI
CustomFdtNodeParser (
IN VOID *FdtBase,
IN VOID *HobList
)
{
INT32 Node, CustomNode;
INT32 TempLen;
UINT64 *Data64;
UINTN CHobList;
CONST FDT_PROPERTY *PropertyPtr;
EFI_PEI_HOB_POINTERS Hob;
CHobList = (UINTN)HobList;
DEBUG ((DEBUG_INFO, "%a() #1 \n", __func__));
//
// Look for if exists hob list node
//
Node = FdtSubnodeOffsetNameLen (FdtBase, 0, "options", (INT32)AsciiStrLen ("options"));
if (Node > 0) {
DEBUG ((DEBUG_INFO, " Found options node (%08X)", Node));
CustomNode = FdtSubnodeOffsetNameLen (FdtBase, Node, "upl-custom", (INT32)AsciiStrLen ("upl-custom"));
if (CustomNode > 0) {
DEBUG ((DEBUG_INFO, " Found upl-custom node (%08X)", CustomNode));
PropertyPtr = FdtGetProperty (FdtBase, CustomNode, "hoblistptr", &TempLen);
Data64 = (UINT64 *)(PropertyPtr->Data);
CHobList = (UINTN)Fdt64ToCpu (*Data64);
DEBUG ((DEBUG_INFO, " Found hob list node (%08X)", CustomNode));
DEBUG ((DEBUG_INFO, " -pointer %016lX\n", CHobList));
}
}
Hob.Raw = (UINT8 *)CHobList;
//
// Since payload created new Hob, move all hobs except PHIT from boot loader hob list.
//
while (!END_OF_HOB_LIST (Hob)) {
if (FitIsHobNeed (Hob)) {
// Add this hob to payload HOB
AddNewHob (&Hob);
}
Hob.Raw = GET_NEXT_HOB (Hob);
}
return CHobList;
}

View File

@ -0,0 +1,46 @@
## @file
# Custom FDT Node Parse Library.
#
# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = CustomFdtNodeParserLib
FILE_GUID = 732B2B8F-65AD-4BF8-A98F-6E0D330F7A60
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = CustomFdtNodeParserLib
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64
#
[Sources]
CustomFdtNodeParserLib.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
UefiPayloadPkg/UefiPayloadPkg.dec
[LibraryClasses]
BaseMemoryLib
DebugLib
FdtLib
HobLib
PcdLib
[Guids]
gUniversalPayloadPciRootBridgeInfoGuid
gUniversalPayloadSerialPortInfoGuid
gUniversalPayloadDeviceTreeGuid
gUniversalPayloadAcpiTableGuid
gEfiHobMemoryAllocModuleGuid
[Pcd]
gUefiPayloadPkgTokenSpaceGuid.PcdHandOffFdtEnable

View File

@ -0,0 +1,46 @@
/** @file
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Uefi.h>
#include <PiPei.h>
#include <Pi/PiHob.h>
/**
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
FitIsHobNeed (
EFI_PEI_HOB_POINTERS Hob
)
{
return FALSE;
}
/**
It will Parse FDT -custom node based on information from bootloaders.
@param[in] FdtBase The starting memory address of FdtBase.
@param[in] HobList The starting memory address of New Hob list.
@retval HobList The base address of Hoblist.
**/
UINTN
CustomFdtNodeParser (
IN VOID *Fdt,
IN VOID *HobList
)
{
UINTN CHobList;
CHobList = 0;
if (HobList != NULL) {
CHobList = (UINTN)HobList;
}
return CHobList;
}

View File

@ -0,0 +1,27 @@
## @file
# Custom FDT Node Parse Library.
#
# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = CustomFdtNodeParserLibNull
FILE_GUID = 386496E4-37DB-4531-BA0C-16D126E63C55
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = CustomFdtNodeParserLib
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64
#
[Sources]
CustomFdtNodeParserNullLib.c
[Packages]
MdePkg/MdePkg.dec

View File

@ -0,0 +1,64 @@
## @file
# Coreboot Table Parse Library.
#
# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = FdtParseLib
FILE_GUID = 8956F72D-9626-4959-98B7-1BD4A3EA687E
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = FdtParseLib
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64
#
[Sources]
FdtParserLib.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
UefiPayloadPkg/UefiPayloadPkg.dec
[LibraryClasses]
DebugLib
PcdLib
HobLib
FdtLib
CustomFdtNodeParserLib
[Guids]
gUniversalPayloadDeviceTreeGuid
gEfiGraphicsInfoHobGuid
gEfiGraphicsDeviceInfoHobGuid
gUniversalPayloadAcpiTableGuid
gUniversalPayloadSerialPortInfoGuid
[Pcd.IA32,Pcd.X64]
gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize
gUefiPayloadPkgTokenSpaceGuid.PcdSystemMemoryUefiRegionSize
gUefiPayloadPkgTokenSpaceGuid.PcdHandOffFdtEnable
gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase
gUefiPayloadPkgTokenSpaceGuid.PcdPciReservedPMemBase
gUefiPayloadPkgTokenSpaceGuid.PcdPciReservedPMemLimit
gUefiPayloadPkgTokenSpaceGuid.PcdPciReservedPMemAbove4GBBase
gUefiPayloadPkgTokenSpaceGuid.PcdPciReservedPMemAbove4GBLimit
gUefiPayloadPkgTokenSpaceGuid.SizeOfIoSpace
[BuildOptions]
MSFT:*_*_*_CC_FLAGS = /wd4305
GCC:*_*_IA32_CC_FLAGS = -Wno-error=pointer-to-int-cast -Wno-error=int-to-pointer-cast
GCC:*_*_X64_CC_FLAGS = -Wno-error=pointer-to-int-cast -Wno-error=int-to-pointer-cast
GCC:*_*_ARM_CC_FLAGS = -Wno-error=pointer-to-int-cast -Wno-error=int-to-pointer-cast
GCC:*_*_AARCH64_CC_FLAGS = -Wno-error=pointer-to-int-cast -Wno-error=int-to-pointer-cast
GCC:*_*_RISCV64_CC_FLAGS = -Wno-error=pointer-to-int-cast -Wno-error=int-to-pointer-cast
GCC:*_*_LOONGARCH64_CC_FLAGS = -Wno-error=pointer-to-int-cast -Wno-error=int-to-pointer-cast

View File

@ -0,0 +1,944 @@
/** @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 <Library/IoLib.h>
#include <Guid/MemoryAllocationHob.h>
#include <Guid/DebugPrintErrorLevel.h>
#include <Guid/SerialPortInfoGuid.h>
#include <Guid/MemoryMapInfoGuid.h>
#include <Guid/AcpiBoardInfoGuid.h>
#include <Guid/GraphicsInfoHob.h>
#include <Guid/UniversalPayloadBase.h>
#include <UniversalPayload/SmbiosTable.h>
#include <UniversalPayload/AcpiTable.h>
#include <UniversalPayload/UniversalPayload.h>
#include <UniversalPayload/ExtraData.h>
#include <UniversalPayload/SerialPortInfo.h>
#include <UniversalPayload/DeviceTree.h>
#include <UniversalPayload/PciRootBridges.h>
#include <IndustryStandard/SmBios.h>
#include <Library/PrintLib.h>
#include <Library/FdtLib.h>
#include <Protocol/PciHostBridgeResourceAllocation.h>
#include <Protocol/PciIo.h>
typedef enum {
ReservedMemory = 1,
Memory,
FrameBuffer,
PciRootBridge,
Options,
DoNothing
} FDT_NODE_TYPE;
#define MEMORY_ATTRIBUTE_DEFAULT (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 )
#define ROOT_BRIDGE_SUPPORTS_DEFAULT (EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 | \
EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 | \
EFI_PCI_IO_ATTRIBUTE_ISA_IO_16 | \
EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | \
EFI_PCI_IO_ATTRIBUTE_VGA_IO | \
EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | \
EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | \
EFI_PCI_IO_ATTRIBUTE_ISA_IO | \
EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO )
extern VOID *mHobList;
UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES *mPciRootBridgeInfo = NULL;
INT32 mNode[0x500] = { 0 };
UINT32 mNodeIndex = 0;
/**
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
);
/**
It will record the memory node initialized.
@param[in] Node memory node is going to parsing..
**/
VOID
RecordMemoryNode (
INT32 Node
)
{
DEBUG ((DEBUG_INFO, "\n RecordMemoryNode %x , mNodeIndex :%x \n", Node, mNodeIndex));
mNode[mNodeIndex] = Node;
mNodeIndex++;
}
/**
Check the memory node if initialized.
@param[in] Node memory node is going to parsing..
@return TRUE memory node was initialized. don't parse it again.
@return FALSE memory node wasn't initialized , go to parse it.
**/
BOOLEAN
CheckMemoryNodeIfInit (
INT32 Node
)
{
UINT32 i;
for (i = 0; i < mNodeIndex; i++) {
if (mNode[i] == Node) {
return TRUE;
}
}
return FALSE;
}
/**
It will check device node from FDT.
@param[in] NodeString Device node name string.
@param[in] Depth Check layer of Device node , only parse the 1st layer
@return FDT_NODE_TYPE what type of the device node.
**/
FDT_NODE_TYPE
CheckNodeType (
CHAR8 *NodeString,
INT32 Depth
)
{
DEBUG ((DEBUG_INFO, "\n CheckNodeType %a \n", NodeString));
if (AsciiStrnCmp (NodeString, "reserved-memory", AsciiStrLen ("reserved-memory")) == 0 ) {
return ReservedMemory;
} else if (AsciiStrnCmp (NodeString, "memory@", AsciiStrLen ("memory@")) == 0 ) {
return Memory;
} else if (AsciiStrnCmp (NodeString, "framebuffer@", AsciiStrLen ("framebuffer@")) == 0) {
return FrameBuffer;
} else if (AsciiStrnCmp (NodeString, "pci-rb", AsciiStrLen ("pci-rb")) == 0 ) {
return PciRootBridge;
} else if (AsciiStrCmp (NodeString, "options") == 0) {
return Options;
} else {
return DoNothing;
}
}
/**
It will ParseMemory node from FDT.
@param[in] Fdt Address of the Fdt data.
@param[in] SubNode first node of the PCI root bridge node.
**/
VOID
ParseMemory (
IN VOID *Fdt,
IN INT32 Node
)
{
UINT32 Attribute;
UINT8 ECCAttribute;
UINT32 ECCData, ECCData2;
INT32 Property;
CONST FDT_PROPERTY *PropertyPtr;
INT32 TempLen;
CONST CHAR8 *TempStr;
UINT64 *Data64;
UINT32 *Data32;
UINT64 StartAddress;
UINT64 NumberOfBytes;
Attribute = MEMORY_ATTRIBUTE_DEFAULT;
ECCAttribute = 0;
ECCData = ECCData2 = 0;
for (Property = FdtFirstPropertyOffset (Fdt, Node); Property >= 0; Property = FdtNextPropertyOffset (Fdt, Property)) {
PropertyPtr = FdtGetPropertyByOffset (Fdt, Property, &TempLen);
TempStr = FdtGetString (Fdt, Fdt32ToCpu (PropertyPtr->NameOffset), NULL);
if (AsciiStrCmp (TempStr, "reg") == 0) {
Data64 = (UINT64 *)(PropertyPtr->Data);
StartAddress = Fdt64ToCpu (*Data64);
NumberOfBytes = Fdt64ToCpu (*(Data64 + 1));
} else if (AsciiStrCmp (TempStr, "ecc-detection-bits") == 0) {
Data32 = (UINT32 *)(PropertyPtr->Data);
ECCData = Fdt32ToCpu (*Data32);
} else if (AsciiStrCmp (TempStr, "ecc-correction-bits") == 0) {
Data32 = (UINT32 *)(PropertyPtr->Data);
ECCData2 = Fdt32ToCpu (*Data32);
}
}
if (ECCData == ECCData2) {
if (ECCData == 1) {
ECCAttribute = EFI_RESOURCE_ATTRIBUTE_SINGLE_BIT_ECC;
} else if (ECCData == 2) {
ECCAttribute = EFI_RESOURCE_ATTRIBUTE_MULTIPLE_BIT_ECC;
}
}
if (ECCAttribute != 0) {
Attribute |= ECCAttribute;
}
BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY, Attribute, StartAddress, NumberOfBytes);
}
/**
It will ParseReservedMemory node from FDT.
@param[in] Fdt Address of the Fdt data.
@param[in] SubNode first node of the PCI root bridge node.
**/
VOID
ParseReservedMemory (
IN VOID *Fdt,
IN INT32 Node
)
{
INT32 SubNode;
INT32 TempLen;
CONST CHAR8 *TempStr;
CONST FDT_PROPERTY *PropertyPtr;
UINT64 *Data64;
UINT64 StartAddress;
UINT64 NumberOfBytes;
UNIVERSAL_PAYLOAD_ACPI_TABLE *PlatformAcpiTable;
FDT_NODE_HEADER *NodePtr;
PlatformAcpiTable = NULL;
for (SubNode = FdtFirstSubnode (Fdt, Node); SubNode >= 0; SubNode = FdtNextSubnode (Fdt, SubNode)) {
NodePtr = (FDT_NODE_HEADER *)((CONST CHAR8 *)Fdt + SubNode + Fdt32ToCpu (((FDT_HEADER *)Fdt)->OffsetDtStruct));
DEBUG ((DEBUG_INFO, "\n SubNode(%08X) %a", SubNode, NodePtr->Name));
PropertyPtr = FdtGetProperty (Fdt, SubNode, "reg", &TempLen);
ASSERT (TempLen > 0);
TempStr = (CHAR8 *)(PropertyPtr->Data);
if (TempLen > 0) {
Data64 = (UINT64 *)(PropertyPtr->Data);
StartAddress = Fdt64ToCpu (*Data64);
NumberOfBytes = Fdt64ToCpu (*(Data64 + 1));
DEBUG ((DEBUG_INFO, "\n Property %a", TempStr));
DEBUG ((DEBUG_INFO, " %016lX %016lX", StartAddress, NumberOfBytes));
}
RecordMemoryNode (SubNode);
if (AsciiStrnCmp (NodePtr->Name, "mmio@", AsciiStrLen ("mmio@")) == 0) {
DEBUG ((DEBUG_INFO, " MemoryMappedIO"));
BuildMemoryAllocationHob (StartAddress, NumberOfBytes, EfiMemoryMappedIO);
} else {
PropertyPtr = FdtGetProperty (Fdt, SubNode, "compatible", &TempLen);
TempStr = (CHAR8 *)(PropertyPtr->Data);
if (AsciiStrnCmp (TempStr, "boot-code", AsciiStrLen ("boot-code")) == 0) {
DEBUG ((DEBUG_INFO, " boot-code"));
BuildMemoryAllocationHob (StartAddress, NumberOfBytes, EfiBootServicesCode);
} else if (AsciiStrnCmp (TempStr, "boot-data", AsciiStrLen ("boot-data")) == 0) {
DEBUG ((DEBUG_INFO, " boot-data"));
BuildMemoryAllocationHob (StartAddress, NumberOfBytes, EfiBootServicesData);
} else if (AsciiStrnCmp (TempStr, "runtime-code", AsciiStrLen ("runtime-code")) == 0) {
DEBUG ((DEBUG_INFO, " runtime-code"));
BuildMemoryAllocationHob (StartAddress, NumberOfBytes, EfiRuntimeServicesCode);
} else if (AsciiStrnCmp (TempStr, "runtime-data", AsciiStrLen ("runtime-data")) == 0) {
DEBUG ((DEBUG_INFO, " runtime-data"));
BuildMemoryAllocationHob (StartAddress, NumberOfBytes, EfiRuntimeServicesData);
} else if (AsciiStrnCmp (TempStr, "acpi", AsciiStrLen ("acpi")) == 0) {
DEBUG ((DEBUG_INFO, " acpi, StartAddress:%x, NumberOfBytes:%x", StartAddress, NumberOfBytes));
BuildMemoryAllocationHob (StartAddress, NumberOfBytes, EfiBootServicesData);
PlatformAcpiTable = BuildGuidHob (&gUniversalPayloadAcpiTableGuid, sizeof (UNIVERSAL_PAYLOAD_ACPI_TABLE));
if (PlatformAcpiTable != NULL) {
DEBUG ((DEBUG_INFO, " build gUniversalPayloadAcpiTableGuid , NumberOfBytes:%x", NumberOfBytes));
PlatformAcpiTable->Rsdp = (EFI_PHYSICAL_ADDRESS)(UINTN)StartAddress;
PlatformAcpiTable->Header.Revision = UNIVERSAL_PAYLOAD_ACPI_TABLE_REVISION;
PlatformAcpiTable->Header.Length = sizeof (UNIVERSAL_PAYLOAD_ACPI_TABLE);
}
} else if (AsciiStrnCmp (TempStr, "acpi-nvs", AsciiStrLen ("acpi-nvs")) == 0) {
DEBUG ((DEBUG_INFO, " acpi-nvs"));
BuildMemoryAllocationHob (StartAddress, NumberOfBytes, EfiACPIMemoryNVS);
} else {
BuildMemoryAllocationHob (StartAddress, NumberOfBytes, EfiReservedMemoryType);
}
}
}
}
/**
It will ParseFrameBuffer node from FDT.
@param[in] Fdt Address of the Fdt data.
@param[in] SubNode first Sub node of the PCI root bridge node.
@return GmaStr Graphic device node name string.
**/
CHAR8 *
ParseFrameBuffer (
IN VOID *Fdt,
IN INT32 Node
)
{
INT32 Property;
INT32 TempLen;
CONST FDT_PROPERTY *PropertyPtr;
CONST CHAR8 *TempStr;
UINT32 *Data32;
UINT64 FrameBufferBase;
UINT32 FrameBufferSize;
EFI_PEI_GRAPHICS_INFO_HOB *GraphicsInfo;
CHAR8 *GmaStr;
GmaStr = "Gma";
//
// Create GraphicInfo HOB.
//
GraphicsInfo = BuildGuidHob (&gEfiGraphicsInfoHobGuid, sizeof (EFI_PEI_GRAPHICS_INFO_HOB));
ASSERT (GraphicsInfo != NULL);
if (GraphicsInfo == NULL) {
return GmaStr;
}
ZeroMem (GraphicsInfo, sizeof (EFI_PEI_GRAPHICS_INFO_HOB));
for (Property = FdtFirstPropertyOffset (Fdt, Node); Property >= 0; Property = FdtNextPropertyOffset (Fdt, Property)) {
PropertyPtr = FdtGetPropertyByOffset (Fdt, Property, &TempLen);
TempStr = FdtGetString (Fdt, Fdt32ToCpu (PropertyPtr->NameOffset), NULL);
if (AsciiStrCmp (TempStr, "reg") == 0) {
Data32 = (UINT32 *)(PropertyPtr->Data);
FrameBufferBase = Fdt32ToCpu (*(Data32 + 0));
FrameBufferSize = Fdt32ToCpu (*(Data32 + 1));
GraphicsInfo->FrameBufferBase = FrameBufferBase;
GraphicsInfo->FrameBufferSize = (UINT32)FrameBufferSize;
} else if (AsciiStrCmp (TempStr, "width") == 0) {
Data32 = (UINT32 *)(PropertyPtr->Data);
GraphicsInfo->GraphicsMode.HorizontalResolution = Fdt32ToCpu (*Data32);
} else if (AsciiStrCmp (TempStr, "height") == 0) {
Data32 = (UINT32 *)(PropertyPtr->Data);
GraphicsInfo->GraphicsMode.VerticalResolution = Fdt32ToCpu (*Data32);
} else if (AsciiStrCmp (TempStr, "format") == 0) {
TempStr = (CHAR8 *)(PropertyPtr->Data);
if (AsciiStrCmp (TempStr, "a8r8g8b8") == 0) {
GraphicsInfo->GraphicsMode.PixelFormat = PixelRedGreenBlueReserved8BitPerColor;
} else if (AsciiStrCmp (TempStr, "a8b8g8r8") == 0) {
GraphicsInfo->GraphicsMode.PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
} else {
GraphicsInfo->GraphicsMode.PixelFormat = PixelFormatMax;
}
} else if (AsciiStrCmp (TempStr, "display") == 0) {
GmaStr = (CHAR8 *)(PropertyPtr->Data);
GmaStr++;
DEBUG ((DEBUG_INFO, " display (%s)", GmaStr));
}
}
return GmaStr;
}
/**
It will ParseOptions node from FDT.
@param[in] Fdt Address of the Fdt data.
@param[in] SubNode first Sub node of the PCI root bridge node.
@param[out] PciEnumDone Init ParsePciRootBridge node for ParsePciRootBridge.
@param[out] BootMode Init the system boot mode
**/
VOID
ParseOptions (
IN VOID *Fdt,
IN INT32 Node,
OUT UINT8 *PciEnumDone,
OUT EFI_BOOT_MODE *BootMode
)
{
INT32 SubNode;
FDT_NODE_HEADER *NodePtr;
UNIVERSAL_PAYLOAD_BASE *PayloadBase;
CONST FDT_PROPERTY *PropertyPtr;
CONST CHAR8 *TempStr;
INT32 TempLen;
UINT32 *Data32;
UINT64 *Data64;
UINT64 StartAddress;
UINT8 SizeOfMemorySpace;
for (SubNode = FdtFirstSubnode (Fdt, Node); SubNode >= 0; SubNode = FdtNextSubnode (Fdt, SubNode)) {
NodePtr = (FDT_NODE_HEADER *)((CONST CHAR8 *)Fdt + SubNode + Fdt32ToCpu (((FDT_HEADER *)Fdt)->OffsetDtStruct));
DEBUG ((DEBUG_INFO, "\n SubNode(%08X) %a", SubNode, NodePtr->Name));
if (AsciiStrnCmp (NodePtr->Name, "upl-images@", AsciiStrLen ("upl-images@")) == 0) {
DEBUG ((DEBUG_INFO, " Found image@ node \n"));
//
// Build PayloadBase HOB .
//
PayloadBase = BuildGuidHob (&gUniversalPayloadBaseGuid, sizeof (UNIVERSAL_PAYLOAD_BASE));
ASSERT (PayloadBase != NULL);
if (PayloadBase == NULL) {
return;
}
PayloadBase->Header.Revision = UNIVERSAL_PAYLOAD_BASE_REVISION;
PayloadBase->Header.Length = sizeof (UNIVERSAL_PAYLOAD_BASE);
PropertyPtr = FdtGetProperty (Fdt, SubNode, "addr", &TempLen);
ASSERT (TempLen > 0);
if (TempLen > 0) {
Data64 = (UINT64 *)(PropertyPtr->Data);
StartAddress = Fdt64ToCpu (*Data64);
DEBUG ((DEBUG_INFO, "\n Property(00000000) entry"));
DEBUG ((DEBUG_INFO, " %016lX\n", StartAddress));
PayloadBase->Entry = (EFI_PHYSICAL_ADDRESS)StartAddress;
}
}
if (AsciiStrnCmp (NodePtr->Name, "upl-params", AsciiStrLen ("upl-params")) == 0) {
PropertyPtr = FdtGetProperty (Fdt, SubNode, "addr-width", &TempLen);
if (TempLen > 0) {
Data32 = (UINT32 *)(PropertyPtr->Data);
DEBUG ((DEBUG_INFO, "\n Property(00000000) address_width"));
DEBUG ((DEBUG_INFO, " %X", Fdt32ToCpu (*Data32)));
SizeOfMemorySpace = (UINT8)Fdt32ToCpu (*Data32);
BuildCpuHob (SizeOfMemorySpace, PcdGet8 (SizeOfIoSpace));
}
PropertyPtr = FdtGetProperty (Fdt, SubNode, "pci-enum-done", &TempLen);
if (TempLen > 0) {
*PciEnumDone = 1;
DEBUG ((DEBUG_INFO, " Found PciEnumDone (%08X)\n", *PciEnumDone));
} else {
*PciEnumDone = 0;
DEBUG ((DEBUG_INFO, " Not Found PciEnumDone \n"));
}
PropertyPtr = FdtGetProperty (Fdt, SubNode, "boot-mode", &TempLen);
if (TempLen > 0) {
TempStr = (CHAR8 *)(PropertyPtr->Data);
if (AsciiStrCmp (TempStr, "normal") == 0) {
*BootMode = BOOT_WITH_FULL_CONFIGURATION;
} else if (AsciiStrCmp (TempStr, "fast") == 0) {
*BootMode = BOOT_WITH_MINIMAL_CONFIGURATION;
} else if (AsciiStrCmp (TempStr, "full") == 0) {
*BootMode = BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS;
} else if (AsciiStrCmp (TempStr, "default") == 0) {
*BootMode = BOOT_WITH_DEFAULT_SETTINGS;
} else if (AsciiStrCmp (TempStr, "s4") == 0) {
*BootMode = BOOT_ON_S4_RESUME;
} else if (AsciiStrCmp (TempStr, "s3") == 0) {
*BootMode = BOOT_ON_S3_RESUME;
}
}
}
}
}
/**
It will Parsegraphic node from FDT.
@param[in] Fdt Address of the Fdt data.
@param[in] SubNode first Sub node of the PCI root bridge node.
**/
VOID
ParsegraphicNode (
IN VOID *Fdt,
IN INT32 SubNode
)
{
EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *GraphicsDev;
CONST FDT_PROPERTY *PropertyPtr;
UINT16 GmaID;
UINT32 *Data32;
INT32 TempLen;
DEBUG ((DEBUG_INFO, " Found gma@ node \n"));
GraphicsDev = NULL;
//
// Build Graphic info HOB .
//
GraphicsDev = BuildGuidHob (&gEfiGraphicsDeviceInfoHobGuid, sizeof (EFI_PEI_GRAPHICS_DEVICE_INFO_HOB));
ASSERT (GraphicsDev != NULL);
if (GraphicsDev == NULL) {
return;
}
SetMem (GraphicsDev, sizeof (EFI_PEI_GRAPHICS_DEVICE_INFO_HOB), 0xFF);
PropertyPtr = FdtGetProperty (Fdt, SubNode, "vendor-id", &TempLen);
ASSERT (TempLen > 0);
if (TempLen > 0) {
Data32 = (UINT32 *)(PropertyPtr->Data);
GmaID = (UINT16)Fdt32ToCpu (*Data32);
DEBUG ((DEBUG_INFO, "\n vendor-id"));
DEBUG ((DEBUG_INFO, " %016lX\n", GmaID));
GraphicsDev->VendorId = GmaID;
}
PropertyPtr = FdtGetProperty (Fdt, SubNode, "device-id", &TempLen);
ASSERT (TempLen > 0);
if (TempLen > 0) {
Data32 = (UINT32 *)(PropertyPtr->Data);
GmaID = (UINT16)Fdt32ToCpu (*Data32);
DEBUG ((DEBUG_INFO, "\n device-id"));
DEBUG ((DEBUG_INFO, " %016lX\n", GmaID));
GraphicsDev->DeviceId = GmaID;
}
PropertyPtr = FdtGetProperty (Fdt, SubNode, "revision-id", &TempLen);
ASSERT (TempLen > 0);
if (TempLen > 0) {
Data32 = (UINT32 *)(PropertyPtr->Data);
GmaID = (UINT16)Fdt32ToCpu (*Data32);
DEBUG ((DEBUG_INFO, "\n revision-id"));
DEBUG ((DEBUG_INFO, " %016lX\n", GmaID));
GraphicsDev->RevisionId = (UINT8)GmaID;
}
PropertyPtr = FdtGetProperty (Fdt, SubNode, "subsystem-vendor-id", &TempLen);
ASSERT (TempLen > 0);
if (TempLen > 0) {
Data32 = (UINT32 *)(PropertyPtr->Data);
GmaID = (UINT16)Fdt32ToCpu (*Data32);
DEBUG ((DEBUG_INFO, "\n subsystem-vendor-id"));
DEBUG ((DEBUG_INFO, " %016lX\n", GmaID));
GraphicsDev->SubsystemVendorId = GmaID;
}
PropertyPtr = FdtGetProperty (Fdt, SubNode, "subsystem-id", &TempLen);
ASSERT (TempLen > 0);
if (TempLen > 0) {
Data32 = (UINT32 *)(PropertyPtr->Data);
GmaID = (UINT16)Fdt32ToCpu (*Data32);
DEBUG ((DEBUG_INFO, "\n subsystem-id"));
DEBUG ((DEBUG_INFO, " %016lX\n", GmaID));
GraphicsDev->SubsystemId = GmaID;
}
}
/**
It will ParseSerialPort node from FDT.
@param[in] Fdt Address of the Fdt data.
@param[in] SubNode first Sub node of the PCI root bridge node.
**/
VOID
ParseSerialPort (
IN VOID *Fdt,
IN INT32 SubNode
)
{
UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *Serial;
CONST FDT_PROPERTY *PropertyPtr;
INT32 TempLen;
CONST CHAR8 *TempStr;
UINT32 *Data32;
UINT32 Attribute;
//
// Create SerialPortInfo HOB.
//
Serial = BuildGuidHob (&gUniversalPayloadSerialPortInfoGuid, sizeof (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO));
ASSERT (Serial != NULL);
if (Serial == NULL) {
return;
}
Serial->Header.Revision = UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO_REVISION;
Serial->Header.Length = sizeof (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO);
Serial->RegisterStride = 1;
Serial->UseMmio = 1;
PropertyPtr = FdtGetProperty (Fdt, SubNode, "current-speed", &TempLen);
ASSERT (TempLen > 0);
if (TempLen > 0) {
Data32 = (UINT32 *)(PropertyPtr->Data);
DEBUG ((DEBUG_INFO, " %X", Fdt32ToCpu (*Data32)));
Serial->BaudRate = Fdt32ToCpu (*Data32);
}
PropertyPtr = FdtGetProperty (Fdt, SubNode, "compatible", &TempLen);
TempStr = (CHAR8 *)(PropertyPtr->Data);
if (AsciiStrnCmp (TempStr, "isa", AsciiStrLen ("isa")) == 0) {
DEBUG ((DEBUG_INFO, " find serial compatible isa \n"));
Serial->UseMmio = 0;
PropertyPtr = FdtGetProperty (Fdt, SubNode, "reg", &TempLen);
ASSERT (TempLen > 0);
if (TempLen > 0) {
Data32 = (UINT32 *)(PropertyPtr->Data);
Attribute = Fdt32ToCpu (*(Data32 + 0));
Serial->RegisterBase = Fdt32ToCpu (*(Data32 + 1));
Serial->UseMmio = Attribute == 1 ? FALSE : TRUE;
DEBUG ((DEBUG_INFO, "\n in espi serial Property() %a", TempStr));
DEBUG ((DEBUG_INFO, " StartAddress %016lX\n", Serial->RegisterBase));
DEBUG ((DEBUG_INFO, " Attribute %016lX\n", Attribute));
}
} else {
DEBUG ((DEBUG_INFO, " NOT serial compatible isa \n"));
PropertyPtr = FdtGetProperty (Fdt, SubNode, "reg", &TempLen);
ASSERT (TempLen > 0);
if (TempLen > 0) {
Data32 = (UINT32 *)(PropertyPtr->Data);
Serial->RegisterBase = Fdt32ToCpu (*Data32);
}
}
}
/**
It will ParsePciRootBridge node from FDT.
@param[in] Fdt Address of the Fdt data.
@param[in] Node first node of the Fdt data.
@param[in] PciEnumDone To use ParsePciRootBridge node.
@param[in] RootBridgeCount Number of pci RootBridge.
@param[in] GmaStr Graphic device node name string.
@param[in] index Index of ParsePciRootBridge node.
**/
VOID
ParsePciRootBridge (
IN VOID *Fdt,
IN INT32 Node,
IN UINT8 PciEnumDone,
IN UINT8 RootBridgeCount,
IN CHAR8 *GmaStr,
IN UINT8 *index
)
{
INT32 SubNode;
INT32 Property;
INT32 SSubNode;
FDT_NODE_HEADER *NodePtr;
CONST FDT_PROPERTY *PropertyPtr;
INT32 TempLen;
UINT32 *Data32;
UINT32 MemType;
CONST CHAR8 *TempStr;
UINT8 RbIndex;
UINTN HobDataSize;
UINT8 Base;
RbIndex = *index;
HobDataSize = sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES) + RootBridgeCount *sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE);
//
// Create PCI Root Bridge Info Hob.
//
if (mPciRootBridgeInfo == NULL) {
mPciRootBridgeInfo = BuildGuidHob (&gUniversalPayloadPciRootBridgeInfoGuid, HobDataSize);
ASSERT (mPciRootBridgeInfo != NULL);
if (mPciRootBridgeInfo == NULL) {
return;
}
ZeroMem (mPciRootBridgeInfo, HobDataSize);
mPciRootBridgeInfo->Header.Length = sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES);
mPciRootBridgeInfo->Header.Revision = UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES_REVISION;
mPciRootBridgeInfo->Count = RootBridgeCount;
mPciRootBridgeInfo->ResourceAssigned = (BOOLEAN)PciEnumDone;
}
for (SubNode = FdtFirstSubnode (Fdt, Node); SubNode >= 0; SubNode = FdtNextSubnode (Fdt, SubNode)) {
NodePtr = (FDT_NODE_HEADER *)((CONST CHAR8 *)Fdt + SubNode + Fdt32ToCpu (((FDT_HEADER *)Fdt)->OffsetDtStruct));
DEBUG ((DEBUG_INFO, "\n SubNode(%08X) %a", SubNode, NodePtr->Name));
if (AsciiStrnCmp (NodePtr->Name, GmaStr, AsciiStrLen (GmaStr)) == 0) {
DEBUG ((DEBUG_INFO, " Found gma@ node \n"));
ParsegraphicNode (Fdt, SubNode);
}
if (AsciiStrnCmp (NodePtr->Name, "isa", AsciiStrLen ("isa")) == 0) {
SSubNode = FdtFirstSubnode (Fdt, SubNode); // serial
ParseSerialPort (Fdt, SSubNode);
}
if (AsciiStrnCmp (NodePtr->Name, "serial@", AsciiStrLen ("serial@")) == 0) {
ParseSerialPort (Fdt, SubNode);
}
}
DEBUG ((DEBUG_INFO, " RbIndex :%x \n", RbIndex));
for (Property = FdtFirstPropertyOffset (Fdt, Node); Property >= 0; Property = FdtNextPropertyOffset (Fdt, Property)) {
PropertyPtr = FdtGetPropertyByOffset (Fdt, Property, &TempLen);
TempStr = FdtGetString (Fdt, Fdt32ToCpu (PropertyPtr->NameOffset), NULL);
if (AsciiStrCmp (TempStr, "ranges") == 0) {
DEBUG ((DEBUG_INFO, " Found ranges Property TempLen (%08X), limit %x\n", TempLen, TempLen/sizeof (UINT32)));
mPciRootBridgeInfo->RootBridge[RbIndex].AllocationAttributes = EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM | EFI_PCI_HOST_BRIDGE_MEM64_DECODE;
mPciRootBridgeInfo->RootBridge[RbIndex].Supports = ROOT_BRIDGE_SUPPORTS_DEFAULT;
mPciRootBridgeInfo->RootBridge[RbIndex].PMemAbove4G.Base = PcdGet64 (PcdPciReservedPMemAbove4GBBase);
mPciRootBridgeInfo->RootBridge[RbIndex].PMemAbove4G.Limit = PcdGet64 (PcdPciReservedPMemAbove4GBLimit);
mPciRootBridgeInfo->RootBridge[RbIndex].PMem.Base = PcdGet32 (PcdPciReservedPMemBase);
mPciRootBridgeInfo->RootBridge[RbIndex].PMem.Limit = PcdGet32 (PcdPciReservedPMemLimit);
mPciRootBridgeInfo->RootBridge[RbIndex].UID = RbIndex;
mPciRootBridgeInfo->RootBridge[RbIndex].HID = EISA_PNP_ID (0x0A03);
Data32 = (UINT32 *)(PropertyPtr->Data);
for (Base = 0; Base < TempLen/sizeof (UINT32); Base = Base + DWORDS_TO_NEXT_ADDR_TYPE) {
DEBUG ((DEBUG_INFO, " Base :%x \n", Base));
MemType = Fdt32ToCpu (*(Data32 + Base));
if (((MemType) & (SS_64BIT_MEMORY_SPACE)) == SS_64BIT_MEMORY_SPACE) {
DEBUG ((DEBUG_INFO, " To program 64 mm \n"));
mPciRootBridgeInfo->RootBridge[RbIndex].MemAbove4G.Base = Fdt32ToCpu (*(Data32 + Base + 2)) + LShiftU64 (Fdt32ToCpu (*(Data32 + Base + 1)), 32);
mPciRootBridgeInfo->RootBridge[RbIndex].MemAbove4G.Limit = mPciRootBridgeInfo->RootBridge[RbIndex].MemAbove4G.Base + LShiftU64 (Fdt32ToCpu (*(Data32 + Base + 5)), 32) + Fdt32ToCpu (*(Data32 + Base + 6)) -1;
} else if (((MemType) & (SS_32BIT_MEMORY_SPACE)) == SS_32BIT_MEMORY_SPACE) {
DEBUG ((DEBUG_INFO, " To program 32 mem \n"));
mPciRootBridgeInfo->RootBridge[RbIndex].Mem.Base = Fdt32ToCpu (*(Data32 + Base + 2));
mPciRootBridgeInfo->RootBridge[RbIndex].Mem.Limit = mPciRootBridgeInfo->RootBridge[RbIndex].Mem.Base + Fdt32ToCpu (*(Data32 + Base + 6)) -1;
} else if (((MemType) & (SS_IO_SPACE)) == SS_IO_SPACE) {
DEBUG ((DEBUG_INFO, " To program Io\n"));
mPciRootBridgeInfo->RootBridge[RbIndex].Io.Base = Fdt32ToCpu (*(Data32 + Base + 2));
mPciRootBridgeInfo->RootBridge[RbIndex].Io.Limit = mPciRootBridgeInfo->RootBridge[RbIndex].Io.Base + Fdt32ToCpu (*(Data32 + Base + 6)) -1;
}
}
DEBUG ((DEBUG_INFO, "RootBridgeCount %x, index :%x\n", RootBridgeCount, RbIndex));
DEBUG ((DEBUG_INFO, "PciRootBridge->Mem.Base %x, \n", mPciRootBridgeInfo->RootBridge[RbIndex].Mem.Base));
DEBUG ((DEBUG_INFO, "PciRootBridge->Mem.limit %x, \n", mPciRootBridgeInfo->RootBridge[RbIndex].Mem.Limit));
DEBUG ((DEBUG_INFO, "PciRootBridge->MemAbove4G.Base %llx, \n", mPciRootBridgeInfo->RootBridge[RbIndex].MemAbove4G.Base));
DEBUG ((DEBUG_INFO, "PciRootBridge->MemAbove4G.limit %llx, \n", mPciRootBridgeInfo->RootBridge[RbIndex].MemAbove4G.Limit));
DEBUG ((DEBUG_INFO, "PciRootBridge->Io.Base %llx, \n", mPciRootBridgeInfo->RootBridge[RbIndex].Io.Base));
DEBUG ((DEBUG_INFO, "PciRootBridge->Io.limit %llx, \n", mPciRootBridgeInfo->RootBridge[RbIndex].Io.Limit));
}
if (AsciiStrCmp (TempStr, "bus-range") == 0) {
DEBUG ((DEBUG_INFO, " Found bus-range Property TempLen (%08X)\n", TempLen));
Data32 = (UINT32 *)(PropertyPtr->Data);
mPciRootBridgeInfo->RootBridge[RbIndex].Bus.Base = Fdt32ToCpu (*Data32) & 0xFF;
mPciRootBridgeInfo->RootBridge[RbIndex].Bus.Limit = Fdt32ToCpu (*(Data32 + 1)) & 0xFF;
mPciRootBridgeInfo->RootBridge[RbIndex].Bus.Translation = 0;
DEBUG ((DEBUG_INFO, "PciRootBridge->Bus.Base %x, index %x\n", mPciRootBridgeInfo->RootBridge[RbIndex].Bus.Base, RbIndex));
DEBUG ((DEBUG_INFO, "PciRootBridge->Bus.limit %x, index %x\n", mPciRootBridgeInfo->RootBridge[RbIndex].Bus.Limit, RbIndex));
}
}
if (RbIndex > 0) {
RbIndex--;
}
DEBUG ((DEBUG_INFO, "After updated RbIndex :%x \n", RbIndex));
*index = RbIndex;
}
/**
It will parse FDT based on DTB from bootloaders.
@param[in] FdtBase Address of the Fdt data.
@return The address to the new hob list
**/
UINTN
EFIAPI
ParseDtb (
IN VOID *FdtBase
)
{
VOID *Fdt;
INT32 Node;
INT32 Property;
INT32 Depth;
FDT_NODE_HEADER *NodePtr;
CONST FDT_PROPERTY *PropertyPtr;
CONST CHAR8 *TempStr;
INT32 TempLen;
UINT64 *Data64;
UINT64 StartAddress;
UINT64 NumberOfBytes;
UINTN MinimalNeededSize;
EFI_PHYSICAL_ADDRESS FreeMemoryBottom;
EFI_PHYSICAL_ADDRESS FreeMemoryTop;
EFI_PHYSICAL_ADDRESS MemoryBottom;
EFI_PHYSICAL_ADDRESS MemoryTop;
BOOLEAN IsHobConstructed;
UINTN NewHobList;
UINT8 RootBridgeCount;
UINT8 index;
UINTN HobDataSize;
UINT8 PciEnumDone;
UINT8 NodeType;
EFI_BOOT_MODE BootMode;
CHAR8 *GmaStr;
Fdt = FdtBase;
Depth = 0;
MinimalNeededSize = FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
IsHobConstructed = FALSE;
NewHobList = 0;
RootBridgeCount = 0;
index = 0;
HobDataSize = 0;
PciEnumDone = 0;
BootMode = 0;
NodeType = 0;
DEBUG ((DEBUG_INFO, "FDT = 0x%x %x\n", Fdt, Fdt32ToCpu (*((UINT32 *)Fdt))));
DEBUG ((DEBUG_INFO, "Start parsing DTB data\n"));
DEBUG ((DEBUG_INFO, "MinimalNeededSize :%x\n", MinimalNeededSize));
for (Node = FdtNextNode (Fdt, 0, &Depth); Node >= 0; Node = FdtNextNode (Fdt, Node, &Depth)) {
NodePtr = (FDT_NODE_HEADER *)((CONST CHAR8 *)Fdt + Node + Fdt32ToCpu (((FDT_HEADER *)Fdt)->OffsetDtStruct));
DEBUG ((DEBUG_INFO, "\n Node(%08x) %a Depth %x", Node, NodePtr->Name, Depth));
// memory node
if (AsciiStrnCmp (NodePtr->Name, "memory@", AsciiStrLen ("memory@")) == 0) {
for (Property = FdtFirstPropertyOffset (Fdt, Node); Property >= 0; Property = FdtNextPropertyOffset (Fdt, Property)) {
PropertyPtr = FdtGetPropertyByOffset (Fdt, Property, &TempLen);
TempStr = FdtGetString (Fdt, Fdt32ToCpu (PropertyPtr->NameOffset), NULL);
if (AsciiStrCmp (TempStr, "reg") == 0) {
Data64 = (UINT64 *)(PropertyPtr->Data);
StartAddress = Fdt64ToCpu (*Data64);
NumberOfBytes = Fdt64ToCpu (*(Data64 + 1));
DEBUG ((DEBUG_INFO, "\n Property(%08X) %a", Property, TempStr));
DEBUG ((DEBUG_INFO, " %016lX %016lX", StartAddress, NumberOfBytes));
if (!IsHobConstructed) {
if ((NumberOfBytes > MinimalNeededSize) && (StartAddress < BASE_4GB)) {
MemoryBottom = StartAddress + NumberOfBytes - MinimalNeededSize;
FreeMemoryBottom = MemoryBottom;
FreeMemoryTop = StartAddress + NumberOfBytes;
MemoryTop = FreeMemoryTop;
DEBUG ((DEBUG_INFO, "MemoryBottom :0x%llx\n", MemoryBottom));
DEBUG ((DEBUG_INFO, "FreeMemoryBottom :0x%llx\n", FreeMemoryBottom));
DEBUG ((DEBUG_INFO, "FreeMemoryTop :0x%llx\n", FreeMemoryTop));
DEBUG ((DEBUG_INFO, "MemoryTop :0x%llx\n", MemoryTop));
mHobList = HobConstructor ((VOID *)(UINTN)MemoryBottom, (VOID *)(UINTN)MemoryTop, (VOID *)(UINTN)FreeMemoryBottom, (VOID *)(UINTN)FreeMemoryTop);
IsHobConstructed = TRUE;
NewHobList = (UINTN)mHobList;
break;
}
}
}
}
} // end of memory node
else {
PropertyPtr = FdtGetProperty (Fdt, Node, "compatible", &TempLen);
TempStr = (CHAR8 *)(PropertyPtr->Data);
if (AsciiStrnCmp (TempStr, "pci-rb", AsciiStrLen ("pci-rb")) == 0) {
RootBridgeCount++;
}
}
}
index = RootBridgeCount - 1;
Depth = 0;
for (Node = FdtNextNode (Fdt, 0, &Depth); Node >= 0; Node = FdtNextNode (Fdt, Node, &Depth)) {
NodePtr = (FDT_NODE_HEADER *)((CONST CHAR8 *)Fdt + Node + Fdt32ToCpu (((FDT_HEADER *)Fdt)->OffsetDtStruct));
DEBUG ((DEBUG_INFO, "\n Node(%08x) %a Depth %x", Node, NodePtr->Name, Depth));
NodeType = CheckNodeType (NodePtr->Name, Depth);
DEBUG ((DEBUG_INFO, "NodeType :0x%x\n", NodeType));
switch (NodeType) {
case ReservedMemory:
DEBUG ((DEBUG_INFO, "ParseReservedMemory\n"));
ParseReservedMemory (Fdt, Node);
break;
case Memory:
DEBUG ((DEBUG_INFO, "ParseMemory\n"));
if (!CheckMemoryNodeIfInit (Node)) {
ParseMemory (Fdt, Node);
} else {
DEBUG ((DEBUG_INFO, "Memory has initialized\n"));
}
break;
case FrameBuffer:
DEBUG ((DEBUG_INFO, "ParseFrameBuffer\n"));
GmaStr = ParseFrameBuffer (Fdt, Node);
break;
case PciRootBridge:
DEBUG ((DEBUG_INFO, "ParsePciRootBridge, index :%x\n", index));
ParsePciRootBridge (Fdt, Node, PciEnumDone, RootBridgeCount, GmaStr, &index);
DEBUG ((DEBUG_INFO, "After ParsePciRootBridge, index :%x\n", index));
break;
case Options:
DEBUG ((DEBUG_INFO, "ParseOptions\n"));
ParseOptions (Fdt, Node, &PciEnumDone, &BootMode);
break;
default:
DEBUG ((DEBUG_INFO, "ParseNothing\n"));
break;
}
}
((EFI_HOB_HANDOFF_INFO_TABLE *)(mHobList))->BootMode = BootMode;
DEBUG ((DEBUG_INFO, "\n"));
return NewHobList;
}
/**
It will Parse FDT -node based on information from bootloaders.
@param[in] FdtBase The starting memory address of FdtBase
@retval HobList The base address of Hoblist.
**/
UINTN
EFIAPI
FdtNodeParser (
IN VOID *FdtBase
)
{
return ParseDtb (FdtBase);
}
/**
It will initialize HOBs for UPL.
@param[in] FdtBase Address of the Fdt data.
@retval EFI_SUCCESS If it completed successfully.
@retval Others If it failed to initialize HOBs.
**/
UINTN
EFIAPI
UplInitHob (
IN VOID *FdtBase
)
{
UINTN NHobAddress;
NHobAddress = 0;
//
// Check parameter type(
//
if (FdtCheckHeader (FdtBase) == 0) {
DEBUG ((DEBUG_INFO, "%a() FDT blob\n", __func__));
NHobAddress = FdtNodeParser ((VOID *)FdtBase);
} else {
DEBUG ((DEBUG_INFO, "%a() HOb list\n", __func__));
mHobList = FdtBase;
return (UINTN)(mHobList);
}
return NHobAddress;
}

View File

@ -0,0 +1,280 @@
/** @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;
}

View File

@ -0,0 +1,40 @@
## @file
# UPL Hob Parse Library.
#
# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = HobParseLib
FILE_GUID = EFB05FE7-604B-40DA-9A59-E2F998528754
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = HobParseLib|DXE_DRIVER DXE_RUNTIME_DRIVER SMM_CORE DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64
#
[Sources]
HobParseLib.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
UefiPayloadPkg/UefiPayloadPkg.dec
[LibraryClasses]
BaseLib
BaseMemoryLib
IoLib
DebugLib
PcdLib
HobLib
[Pcd.IA32,Pcd.X64]
gUefiPayloadPkgTokenSpaceGuid.PcdSystemMemoryUefiRegionSize
gUefiPayloadPkgTokenSpaceGuid.PcdHandOffFdtEnable

View File

@ -318,6 +318,7 @@
FdtLib|MdePkg/Library/BaseFdtLib/BaseFdtLib.inf
SmmRelocationLib|UefiCpuPkg/Library/SmmRelocationLib/SmmRelocationLib.inf
HobPrintLib|MdeModulePkg/Library/HobPrintLib/HobPrintLib.inf
BuildFdtLib|UefiPayloadPkg/Library/BuildFdtLib/BuildFdtLib.inf
[LibraryClasses.common]
!if $(BOOTSPLASH_IMAGE)