diff options
author | Linus Liu <linus.liu@intel.com> | 2024-08-21 02:04:12 -0700 |
---|---|---|
committer | mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> | 2024-08-28 11:39:12 +0000 |
commit | b0c6b049c4b2ba5a63615b490e974771cd0a40a4 (patch) | |
tree | 7357a6ba2e8738ad194655de2860c7485f228cee /UefiPayloadPkg | |
parent | a297b81b623cc2c9a817a0a0c5b798353ea87064 (diff) | |
download | edk2-b0c6b049c4b2ba5a63615b490e974771cd0a40a4.tar.gz |
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>
Diffstat (limited to 'UefiPayloadPkg')
11 files changed, 2622 insertions, 0 deletions
diff --git a/UefiPayloadPkg/Library/BuildFdtLib/BuildFdtLib.inf b/UefiPayloadPkg/Library/BuildFdtLib/BuildFdtLib.inf new file mode 100644 index 0000000000..12461a9606 --- /dev/null +++ b/UefiPayloadPkg/Library/BuildFdtLib/BuildFdtLib.inf @@ -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
diff --git a/UefiPayloadPkg/Library/BuildFdtLib/X86_BuildFdtLib.c b/UefiPayloadPkg/Library/BuildFdtLib/X86_BuildFdtLib.c new file mode 100644 index 0000000000..8df78a0afc --- /dev/null +++ b/UefiPayloadPkg/Library/BuildFdtLib/X86_BuildFdtLib.c @@ -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;
+}
diff --git a/UefiPayloadPkg/Library/CustomFdtNodeParserLib/CustomFdtNodeParserLib.c b/UefiPayloadPkg/Library/CustomFdtNodeParserLib/CustomFdtNodeParserLib.c new file mode 100644 index 0000000000..0c454496dc --- /dev/null +++ b/UefiPayloadPkg/Library/CustomFdtNodeParserLib/CustomFdtNodeParserLib.c @@ -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;
+}
diff --git a/UefiPayloadPkg/Library/CustomFdtNodeParserLib/CustomFdtNodeParserLib.inf b/UefiPayloadPkg/Library/CustomFdtNodeParserLib/CustomFdtNodeParserLib.inf new file mode 100644 index 0000000000..036ed4315d --- /dev/null +++ b/UefiPayloadPkg/Library/CustomFdtNodeParserLib/CustomFdtNodeParserLib.inf @@ -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
diff --git a/UefiPayloadPkg/Library/CustomFdtNodeParserNullLib/CustomFdtNodeParserNullLib.c b/UefiPayloadPkg/Library/CustomFdtNodeParserNullLib/CustomFdtNodeParserNullLib.c new file mode 100644 index 0000000000..4b2a8b9238 --- /dev/null +++ b/UefiPayloadPkg/Library/CustomFdtNodeParserNullLib/CustomFdtNodeParserNullLib.c @@ -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;
+}
diff --git a/UefiPayloadPkg/Library/CustomFdtNodeParserNullLib/CustomFdtNodeParserNullLib.inf b/UefiPayloadPkg/Library/CustomFdtNodeParserNullLib/CustomFdtNodeParserNullLib.inf new file mode 100644 index 0000000000..8410f04c9d --- /dev/null +++ b/UefiPayloadPkg/Library/CustomFdtNodeParserNullLib/CustomFdtNodeParserNullLib.inf @@ -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
diff --git a/UefiPayloadPkg/Library/FdtParserLib/FdtParseLib.inf b/UefiPayloadPkg/Library/FdtParserLib/FdtParseLib.inf new file mode 100644 index 0000000000..b9b7e90edc --- /dev/null +++ b/UefiPayloadPkg/Library/FdtParserLib/FdtParseLib.inf @@ -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
diff --git a/UefiPayloadPkg/Library/FdtParserLib/FdtParserLib.c b/UefiPayloadPkg/Library/FdtParserLib/FdtParserLib.c new file mode 100644 index 0000000000..421b22904f --- /dev/null +++ b/UefiPayloadPkg/Library/FdtParserLib/FdtParserLib.c @@ -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;
+}
diff --git a/UefiPayloadPkg/Library/HobParseLib/HobParseLib.c b/UefiPayloadPkg/Library/HobParseLib/HobParseLib.c new file mode 100644 index 0000000000..98a5dcfeae --- /dev/null +++ b/UefiPayloadPkg/Library/HobParseLib/HobParseLib.c @@ -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;
+}
diff --git a/UefiPayloadPkg/Library/HobParseLib/HobParseLib.inf b/UefiPayloadPkg/Library/HobParseLib/HobParseLib.inf new file mode 100644 index 0000000000..634c7ff567 --- /dev/null +++ b/UefiPayloadPkg/Library/HobParseLib/HobParseLib.inf @@ -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
diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc b/UefiPayloadPkg/UefiPayloadPkg.dsc index e94a7db886..6199527a9a 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.dsc +++ b/UefiPayloadPkg/UefiPayloadPkg.dsc @@ -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)
|