From: "Linus Liu" <linus.liu@intel.com>
To: devel@edk2.groups.io
Cc: Benny Lin <benny.lin@intel.com>, Gua Guo <gua.guo@intel.com>,
Chasel Chiu <chasel.chiu@intel.com>,
James Lu <james.lu@intel.com>,
Dhaval Sharma <dhaval@rivosinc.com>
Subject: [edk2-devel] [PATCH v2 4/6] UefiPayloadPkg: Update PayloadLoader to suport FDT.
Date: Thu, 23 May 2024 20:24:22 -0700 [thread overview]
Message-ID: <20240524032422.1128-1-linus.liu@intel.com> (raw)
Create FDT nodes (reserved-memory, serial, pci-rb, options) in
FdtPpiNotifyCallback function right after gEfiEndOfPeiSignalPpiGuid.
Cc: Benny Lin <benny.lin@intel.com>
Cc: Gua Guo <gua.guo@intel.com>
Cc: Chasel Chiu <chasel.chiu@intel.com>
Cc: James Lu <james.lu@intel.com>
Cc: Dhaval Sharma <dhaval@rivosinc.com>
Signed-off-by: Linus Liu <linus.liu@intel.com>
---
UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c | 1004 +++++++++++++++++++-
UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.c | 71 +-
UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf | 16 +-
UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.inf | 12 +
4 files changed, 1077 insertions(+), 26 deletions(-)
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
index de33d49bd1c6..00016c7756c5 100644
--- a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
@@ -6,18 +6,74 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <PiPei.h>
#include <UniversalPayload/UniversalPayload.h>
+#include <UniversalPayload/DeviceTree.h>
#include <Guid/UniversalPayloadBase.h>
+#include <Guid/GraphicsInfoHob.h>
#include <UniversalPayload/ExtraData.h>
-
+#include <UniversalPayload/DeviceTree.h>
#include <Ppi/LoadFile.h>
+#include <Library/PciHostBridgeLib.h>
+#include <Protocol/DevicePath.h>
+#include <UniversalPayload/SerialPortInfo.h>
+#include <UniversalPayload/PciRootBridges.h>
+#include <UniversalPayload/AcpiTable.h>
+#include <UniversalPayload/SmbiosTable.h>
+#include <IndustryStandard/SmBios.h>
#include <Library/DebugLib.h>
#include <Library/HobLib.h>
#include <Library/PeiServicesLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/BaseMemoryLib.h>
-
+#include <Library/PciLib.h>
+#include <Library/FdtLib.h>
+#include <Library/PrintLib.h>
#include "FitLib.h"
+#define STACK_SIZE 0x20000
+#define N_NON_RELOCATABLE BIT31
+#define P_NON_PREFETCHABLE BIT30
+#define SS_CONFIGURATION_SPACE 0
+#define SS_IO_SPACE BIT24
+#define SS_32BIT_MEMORY_SPACE BIT25
+#define SS_64BIT_MEMORY_SPACE BIT24+BIT25
+
+CONST EFI_PEI_PPI_DESCRIPTOR gReadyToPayloadSignalPpi = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gUplReadyToPayloadPpiGuid,
+ NULL
+};
+
+EFI_PEI_PPI_DESCRIPTOR mEndOfPeiSignalPpi = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiEndOfPeiSignalPpiGuid,
+ NULL
+};
+
+#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 )
+
+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 PeiLoadImageLoadImage().
@@ -50,6 +106,15 @@ PeiLoadFileLoadPayload (
UINTN Delta;
UINTN Index;
+ #if (FixedPcdGetBool (PcdHandOffFdtEnable))
+ VOID *BaseOfStack;
+ VOID *TopOfStack;
+ UNIVERSAL_PAYLOAD_DEVICE_TREE *Fdt;
+ VOID *Hob;
+
+ Fdt = NULL;
+ #endif
+
Instance = 0;
do {
Status = PeiServicesFfsFindSectionData3 (EFI_SECTION_RAW, Instance++, FileHandle, &Binary, AuthenticationState);
@@ -66,13 +131,15 @@ PeiLoadFileLoadPayload (
return Status;
}
- DEBUG ((
- DEBUG_INFO,
- "Before Rebase Payload File Base: 0x%08x, File Size: 0x%08X, EntryPoint: 0x%08x\n",
- Context.PayloadBaseAddress,
- Context.PayloadSize,
- Context.PayloadEntryPoint
- ));
+ DEBUG (
+ (
+ DEBUG_INFO,
+ "Before Rebase Payload File Base: 0x%08x, File Size: 0x%08X, EntryPoint: 0x%08x\n",
+ Context.PayloadBaseAddress,
+ Context.PayloadSize,
+ Context.PayloadEntryPoint
+ )
+ );
Context.PayloadBaseAddress = (EFI_PHYSICAL_ADDRESS)AllocatePages (EFI_SIZE_TO_PAGES (Context.PayloadSize));
RelocateTable = (FIT_RELOCATE_ITEM *)(UINTN)(Context.PayloadBaseAddress + Context.RelocateTableOffset);
@@ -96,13 +163,15 @@ PeiLoadFileLoadPayload (
}
}
- DEBUG ((
- DEBUG_INFO,
- "After Rebase Payload File Base: 0x%08x, File Size: 0x%08X, EntryPoint: 0x%08x\n",
- Context.PayloadBaseAddress,
- Context.PayloadSize,
- Context.PayloadEntryPoint
- ));
+ DEBUG (
+ (
+ DEBUG_INFO,
+ "After Rebase Payload File Base: 0x%08x, File Size: 0x%08X, EntryPoint: 0x%08x\n",
+ Context.PayloadBaseAddress,
+ Context.PayloadSize,
+ Context.PayloadEntryPoint
+ )
+ );
Length = sizeof (UNIVERSAL_PAYLOAD_BASE);
PayloadBase = BuildGuidHob (
@@ -115,6 +184,42 @@ PeiLoadFileLoadPayload (
*ImageSizeArg = Context.PayloadSize;
*EntryPoint = Context.PayloadEntryPoint;
+ Status = PeiServicesInstallPpi (&mEndOfPeiSignalPpi);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PeiServicesInstallPpi (&gReadyToPayloadSignalPpi);
+ ASSERT_EFI_ERROR (Status);
+
+ #if (FixedPcdGetBool (PcdHandOffFdtEnable))
+ Hob = GetFirstGuidHob (&gUniversalPayloadDeviceTreeGuid);
+ if (Hob != NULL) {
+ Fdt = (UNIVERSAL_PAYLOAD_DEVICE_TREE *)GET_GUID_HOB_DATA (Hob);
+ }
+
+ //
+ // Allocate 128KB for the Stack
+ //
+ BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE));
+ ASSERT (BaseOfStack != NULL);
+
+ //
+ // Compute the top of the stack we were allocated. Pre-allocate a UINTN
+ // for safety.
+ //
+ TopOfStack = (VOID *)((UINTN)BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT);
+ TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
+
+ //
+ // Transfer the control to the entry point of UniveralPayloadEntry.
+ //
+ SwitchStack (
+ (SWITCH_STACK_ENTRY_POINT)(UINTN)Context.PayloadEntryPoint,
+ (VOID *)(Fdt->DeviceTreeAddress),
+ NULL,
+ TopOfStack
+ );
+ #endif
+
return EFI_SUCCESS;
}
@@ -128,6 +233,865 @@ EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = {
&mPeiLoadFilePpi
};
+#if (FixedPcdGetBool (PcdHandOffFdtEnable))
+
+/**
+ Discover Hobs data and report data into a FDT.
+ @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
+ @param[in] NotifyDescriptor Address of the notification descriptor data structure.
+ @param[in] Ppi Address of the PPI that was installed.
+ @retval EFI_SUCCESS Hobs data is discovered.
+ @return Others No Hobs data is discovered.
+**/
+EFI_STATUS
+EFIAPI
+FdtPpiNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+EFI_PEI_NOTIFY_DESCRIPTOR mReadyToPayloadNotifyList[] = {
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gUplReadyToPayloadPpiGuid,
+ FdtPpiNotifyCallback
+ }
+};
+#endif
+
+/**
+ Print FDT data.
+ @param[in] FdtBase Address of the Fdt data.
+**/
+VOID
+PrintFdt (
+ IN VOID *FdtBase
+ )
+{
+ UINT8 *Fdt;
+ UINT32 i;
+
+ Fdt = NULL;
+ i = 0;
+
+ DEBUG ((DEBUG_ERROR, "FDT DTB data:"));
+ for (Fdt = FdtBase, i = 0; i < Fdt32ToCpu (((FDT_HEADER *)FdtBase)->TotalSize); i++, Fdt++) {
+ if (i % 16 == 0) {
+ DEBUG ((DEBUG_ERROR, "\n"));
+ }
+
+ DEBUG ((DEBUG_ERROR, "%02x ", *Fdt));
+ }
+
+ DEBUG ((DEBUG_ERROR, "\n"));
+}
+
+/**
+ 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;
+ // UNIVERSAL_PAYLOAD_SMBIOS_TABLE *SmbiosTable;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ UNIVERSAL_PAYLOAD_ACPI_TABLE *AcpiTable;
+
+ 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], "acpi") == 0) {
+ GuidHob = GetFirstGuidHob (&gUniversalPayloadAcpiTableGuid);
+ if (GuidHob != NULL) {
+ AcpiTable = (UNIVERSAL_PAYLOAD_ACPI_TABLE *)GET_GUID_HOB_DATA (GuidHob);
+ RegTmp[0] = CpuToFdt64 ((UINTN)AcpiTable->Rsdp);
+ RegTmp[1] = CpuToFdt64 (Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress);
+ }
+
+ DEBUG ((DEBUG_INFO, "To build acpi memory FDT , Rsdp :%x, MemoryBaseAddress :%x\n", RegTmp[0], RegTmp[1]));
+ if (RegTmp[0] != RegTmp[1]) {
+ DEBUG ((DEBUG_INFO, "Not Match , skip \n"));
+ continue;
+ }
+
+ DEBUG ((DEBUG_INFO, "To build acpi memory FDT \n"));
+ }
+
+ 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);
+ // }
+
+ if (AllocMemName != NULL) {
+ AllocMemName->Data1 = CpuToFdt32 (AllocMemName->Data1);
+ AllocMemName->Data2 = CpuToFdt16 (AllocMemName->Data2);
+ AllocMemName->Data3 = CpuToFdt16 (AllocMemName->Data3);
+ Status = FdtSetProp (Fdt, TempNode, "guid", AllocMemName, sizeof (EFI_GUID));
+ }
+ }
+ }
+
+ // SmbiosTable = NULL;
+ // SmbiosTable = (UNIVERSAL_PAYLOAD_SMBIOS_TABLE *)GetFirstGuidHob (&gUniversalPayloadSmbios3TableGuid);
+ // if (SmbiosTable != NULL) {
+ // DEBUG ((DEBUG_INFO, "To build Smbios memory FDT\n"));
+ // Status = AsciiSPrint (TempStr, sizeof (TempStr), "memory@%lX", SmbiosTable->SmBiosEntryPoint);
+ // TempNode = FdtAddSubnode (Fdt, ParentNode, TempStr);
+ // DEBUG ((DEBUG_INFO, "FdtAddSubnode %x", TempNode));
+ // RegTmp[0] = CpuToFdt64 (SmbiosTable->SmBiosEntryPoint);
+ // RegTmp[1] = CpuToFdt64 (sizeof (UNIVERSAL_PAYLOAD_SMBIOS_TABLE) + sizeof (SMBIOS_TABLE_3_0_ENTRY_POINT));
+ // Status = FdtSetProp (Fdt, TempNode, "reg", &RegTmp, sizeof (RegTmp));
+ // ASSERT_EFI_ERROR (Status);
+
+ // Status = FdtSetProp (Fdt, TempNode, "compatible", "smbios", (UINT32)(AsciiStrLen ("smbios")+1));
+ // ASSERT_EFI_ERROR (Status);
+ // }
+ return Status;
+}
+
+/**
+ It will build FDT based on serial 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
+BuildFdtForSerial (
+ IN VOID *FdtBase
+ )
+{
+ EFI_STATUS Status;
+ VOID *Fdt;
+ INT32 TempNode;
+ UINT64 RegisterBase;
+ CHAR8 TempStr[32];
+ UINT64 RegData[3];
+ UINT32 Data32;
+
+ Fdt = FdtBase;
+ RegisterBase = 0;
+
+ //
+ // Create SerialPortInfo FDT node.
+ //
+ Status = AsciiSPrint (TempStr, sizeof (TempStr), "serial@%lX", (RegisterBase == 0) ? PcdGet64 (PcdSerialRegisterBase) : RegisterBase);
+ TempNode = FdtAddSubnode (Fdt, 0, TempStr);
+ ASSERT (TempNode > 0);
+
+ Data32 = CpuToFdt32 (PcdGet32 (PcdSerialBaudRate));
+ Status = FdtSetProp (Fdt, TempNode, "current-speed", &Data32, sizeof (Data32));
+ ASSERT_EFI_ERROR (Status);
+
+ // Data32 = CpuToFdt32 (PcdGet32 (PcdSerialRegisterStride));
+ // Status = FdtSetProp (Fdt, TempNode, "reg-shift", &Data32, sizeof (Data32));
+ // ASSERT_EFI_ERROR (Status);
+
+ // Data32 = CpuToFdt32 (8);
+ // Status = FdtSetProp (Fdt, TempNode, "reg-width", &Data32, sizeof (Data32));
+ // ASSERT_EFI_ERROR (Status);
+
+ if (PcdGetBool (PcdSerialUseMmio)) {
+ RegData[0] = CpuToFdt64 (0);
+ RegData[1] = CpuToFdt64 ((RegisterBase == 0) ? PcdGet64 (PcdSerialRegisterBase) : RegisterBase);
+ RegData[2] = CpuToFdt64 (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);
+ } else {
+ RegData[0] = CpuToFdt64 (1);
+ RegData[1] = CpuToFdt64 ((RegisterBase == 0) ? PcdGet64 (PcdSerialRegisterBase) : RegisterBase);
+ RegData[2] = CpuToFdt64 (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 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;
+ CHAR8 TempStr[32];
+ UINT16 RegTmp[2];
+ UINT32 RegData[21];
+ UINT32 DMARegData[8];
+ UINT32 Data32;
+ UINT64 Data64;
+ UINT8 BusNumber;
+ UINT8 BusLimit;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ UNIVERSAL_PAYLOAD_GENERIC_HEADER *GenericHeader;
+ UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES *PciRootBridgeInfo;
+ UINT8 Index;
+
+ Fdt = FdtBase;
+ BusNumber = 0;
+ BusLimit = 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);
+ }
+ }
+ }
+
+ 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;
+
+ 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 + P_NON_PREFETCHABLE + 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 + P_NON_PREFETCHABLE + 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 + P_NON_PREFETCHABLE + 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] = CpuToFdt16 (BusNumber);
+ BusLimit = PciRootBridgeInfo->RootBridge[Index].Bus.Limit & 0xFF;
+ RegTmp[1] = CpuToFdt16 (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", (UINT32)(AsciiStrLen ("pci")+1));
+ 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, "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, "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;
+ UINT16 Data16;
+ 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);
+
+ Data16 = CpuToFdt16 (0);
+ Status = FdtSetProp (Fdt, UPLParaNode, "pci-enum-done", &Data16, sizeof (Data16)/ sizeof (UINT16));
+ 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 = BuildFdtForReservedMemory (FdtBase);
+ // ASSERT_EFI_ERROR (Status);
+
+ Status = BuildFdtForMemAlloc (FdtBase);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = BuildFdtForSerial (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;
+}
+
+#if (FixedPcdGetBool (PcdHandOffFdtEnable))
+
+/**
+ Discover Hobs data and report data into a FDT.
+ @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
+ @param[in] NotifyDescriptor Address of the notification descriptor data structure.
+ @param[in] Ppi Address of the PPI that was installed.
+ @retval EFI_SUCCESS Hobs data is discovered.
+ @return Others No Hobs data is discovered.
+**/
+EFI_STATUS
+EFIAPI
+FdtPpiNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EFI_STATUS Status;
+ UNIVERSAL_PAYLOAD_DEVICE_TREE *Fdt;
+ UINT32 FdtSize;
+ UINTN FdtPages;
+ VOID *FdtBase;
+ UINT32 Data32;
+
+ Fdt = NULL;
+ FdtSize = 4 * EFI_PAGE_SIZE;
+ FdtPages = EFI_SIZE_TO_PAGES (FdtSize);
+ FdtBase = AllocatePages (FdtPages);
+ if (FdtBase == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: AllocatePages failed\n", __func__));
+ return EFI_NOT_FOUND;
+ }
+
+ Status = FdtCreateEmptyTree (FdtBase, (UINT32)FdtSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: cannot create FDT\n", __func__));
+ }
+
+ // Set cell property of root node
+ Data32 = CpuToFdt32 (2);
+ Status = FdtSetProp (FdtBase, 0, "#address-cells", &Data32, sizeof (UINT32));
+ Status = FdtSetProp (FdtBase, 0, "#size-cells", &Data32, sizeof (UINT32));
+
+ Status = BuildFdtForUPL (FdtBase);
+ ASSERT_EFI_ERROR (Status);
+
+ PrintFdt (FdtBase);
+
+ Fdt = BuildGuidHob (&gUniversalPayloadDeviceTreeGuid, sizeof (UNIVERSAL_PAYLOAD_DEVICE_TREE));
+ if (Fdt == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Build FDT Hob failed\n", __func__));
+ return EFI_NOT_FOUND;
+ }
+
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: fdt at 0x%x (size %d)\n",
+ __func__,
+ FdtBase,
+ Fdt32ToCpu (((FDT_HEADER *)FdtBase)->TotalSize)
+ ));
+
+ Fdt->Header.Revision = UNIVERSAL_PAYLOAD_DEVICE_TREE_REVISION;
+ Fdt->Header.Length = sizeof (UNIVERSAL_PAYLOAD_DEVICE_TREE);
+ Fdt->DeviceTreeAddress = (UINT64)FdtBase;
+
+ return Status;
+}
+
+#endif
+
/**
Install Pei Load File PPI.
@param FileHandle Handle of the file being invoked.
@@ -146,5 +1110,13 @@ InitializeFitPayloadLoaderPeim (
Status = PeiServicesInstallPpi (&gPpiLoadFilePpiList);
+ #if (FixedPcdGetBool (PcdHandOffFdtEnable))
+
+ //
+ // Build FDT in end of PEI notify callback.
+ //
+ Status = PeiServicesNotifyPpi (&mReadyToPayloadNotifyList[0]);
+ ASSERT_EFI_ERROR (Status);
+ #endif
return Status;
}
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.c b/UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.c
index 9f9d3c13e13d..fe7aa2682f4d 100644
--- a/UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.c
+++ b/UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.c
@@ -17,9 +17,49 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/PeiServicesLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/BaseMemoryLib.h>
-
+#include <Guid/UniversalPayloadBase.h>
#include "ElfLib.h"
+CONST EFI_PEI_PPI_DESCRIPTOR gReadyToPayloadSignalPpi = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gUplReadyToPayloadPpiGuid,
+ NULL
+};
+
+/**
+ Notify ReadyToPayLoad signal.
+ @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
+ @param[in] NotifyDescriptor Address of the notification descriptor data structure.
+ @param[in] Ppi Address of the PPI that was installed.
+ @retval EFI_SUCCESS Hobs data is discovered.
+ @return Others No Hobs data is discovered.
+**/
+EFI_STATUS
+EFIAPI
+EndOfPeiPpiNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Ready to Payload phase signal
+ //
+ Status = PeiServicesInstallPpi (&gReadyToPayloadSignalPpi);
+
+ return Status;
+}
+
+EFI_PEI_NOTIFY_DESCRIPTOR mEndOfPeiNotifyList[] = {
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiEndOfPeiSignalPpiGuid,
+ EndOfPeiPpiNotifyCallback
+ }
+};
+
/**
The wrapper function of PeiLoadImageLoadImage().
@@ -47,6 +87,7 @@ PeiLoadFileLoadPayload (
EFI_STATUS Status;
VOID *Elf;
UNIVERSAL_PAYLOAD_EXTRA_DATA *ExtraData;
+ UNIVERSAL_PAYLOAD_BASE *PayloadBase;
ELF_IMAGE_CONTEXT Context;
UINT32 Index;
UINT16 ExtraDataIndex;
@@ -73,13 +114,22 @@ PeiLoadFileLoadPayload (
Status = ParseElfImage (Elf, &Context);
} while (EFI_ERROR (Status));
- DEBUG ((
- DEBUG_INFO,
- "Payload File Size: 0x%08X, Mem Size: 0x%08x, Reload: %d\n",
- Context.FileSize,
- Context.ImageSize,
- Context.ReloadRequired
- ));
+ Length = sizeof (UNIVERSAL_PAYLOAD_BASE);
+ PayloadBase = BuildGuidHob (
+ &gUniversalPayloadBaseGuid,
+ Length
+ );
+ PayloadBase->Entry = (EFI_PHYSICAL_ADDRESS)Context.FileBase;
+
+ DEBUG (
+ (
+ DEBUG_INFO,
+ "Payload File Size: 0x%08X, Mem Size: 0x%08x, Reload: %d\n",
+ Context.FileSize,
+ Context.ImageSize,
+ Context.ReloadRequired
+ )
+ );
//
// Get UNIVERSAL_PAYLOAD_INFO_HEADER and number of additional PLD sections.
@@ -153,6 +203,11 @@ PeiLoadFileLoadPayload (
*ImageSizeArg = Context.ImageSize;
}
+ DEBUG ((DEBUG_INFO, "LoadElfImage :%r, EntryPoint :%x\n", Status, (UINTN)Context.EntryPoint));
+
+ Status = PeiServicesNotifyPpi (&mEndOfPeiNotifyList[0]);
+ ASSERT_EFI_ERROR (Status);
+
return Status;
}
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
index cd0cb186e138..c860c3da8dee 100644
--- a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
@@ -35,7 +35,6 @@
[LibraryClasses]
PcdLib
- MemoryAllocationLib
BaseMemoryLib
PeiServicesLib
HobLib
@@ -46,14 +45,27 @@
[Ppis]
gEfiPeiLoadFilePpiGuid ## PRODUCES
+ gUplReadyToPayloadPpiGuid ## PRODUCES
+ gEfiEndOfPeiSignalPpiGuid ## CONSUMES
[Pcd]
gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister
gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister
+ gUefiPayloadPkgTokenSpaceGuid.PcdHandOffFdtEnable
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialBaudRate
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterStride
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseMmio
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+ gEfiMdePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosVersion
[Guids]
- gUniversalPayloadExtraDataGuid ## PRODUCES
gUniversalPayloadBaseGuid ## PRODUCES
+ gUniversalPayloadDeviceTreeGuid ## CONSUMES
+ gEfiGraphicsInfoHobGuid ## CONSUMES
+ gUniversalPayloadPciRootBridgeInfoGuid ## CONSUMES
+ gUniversalPayloadAcpiTableGuid ## CONSUMES
[Depex]
TRUE
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.inf b/UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.inf
index 06e83dbadce0..8db026eaa1b8 100644
--- a/UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.inf
+++ b/UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.inf
@@ -52,6 +52,8 @@
[Ppis]
gEfiPeiLoadFilePpiGuid ## PRODUCES
+ gEfiEndOfPeiSignalPpiGuid ## CONSUMES
+ gUplReadyToPayloadPpiGuid ## PRODUCES
[Pcd]
gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister
@@ -59,6 +61,16 @@
[Guids]
gUniversalPayloadExtraDataGuid ## PRODUCES
+ gUniversalPayloadBaseGuid ## PRODUCES
[Depex]
TRUE
+
+[BuildOptions]
+ MSFT:*_*_*_CC_FLAGS = /wd4244
+ 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
--
2.39.2.windows.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#119189): https://edk2.groups.io/g/devel/message/119189
Mute This Topic: https://groups.io/mt/106275545/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
reply other threads:[~2024-05-24 3:24 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240524032422.1128-1-linus.liu@intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox