Add FDTParser and CustomFdtNodePaser to retrive all FDT node and create the relate hobs.
Cc: Benny Lin <benny....@intel.com> Cc: Gua Guo <gua....@intel.com> Cc: Chasel Chiu <chasel.c...@intel.com> Cc: James Lu <james...@intel.com> Cc: Dhaval Sharma <dha...@rivosinc.com> Signed-off-by: Linus Liu <linus....@intel.com> --- UefiPayloadPkg/Library/CustomFdtNodeParserLib/CustomFdtNodeParserLib.c | 158 +++++ UefiPayloadPkg/Library/CustomFdtNodeParserNullLib/CustomFdtNodeParserNullLib.c | 51 ++ UefiPayloadPkg/Library/FdtParserLib/FdtParserLib.c | 622 ++++++++++++++++++++ UefiPayloadPkg/Library/HobParseLib/HobParseLib.c | 408 +++++++++++++ UefiPayloadPkg/Library/CustomFdtNodeParserLib/CustomFdtNodeParserLib.inf | 46 ++ UefiPayloadPkg/Library/CustomFdtNodeParserNullLib/CustomFdtNodeParserNullLib.inf | 33 ++ UefiPayloadPkg/Library/FdtParserLib/FdtParseLib.inf | 63 ++ UefiPayloadPkg/Library/HobParseLib/HobParseLib.inf | 40 ++ 8 files changed, 1421 insertions(+) diff --git a/UefiPayloadPkg/Library/CustomFdtNodeParserLib/CustomFdtNodeParserLib.c b/UefiPayloadPkg/Library/CustomFdtNodeParserLib/CustomFdtNodeParserLib.c new file mode 100644 index 000000000000..d1376d21c5dd --- /dev/null +++ b/UefiPayloadPkg/Library/CustomFdtNodeParserLib/CustomFdtNodeParserLib.c @@ -0,0 +1,158 @@ +/** @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_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/CustomFdtNodeParserNullLib/CustomFdtNodeParserNullLib.c b/UefiPayloadPkg/Library/CustomFdtNodeParserNullLib/CustomFdtNodeParserNullLib.c new file mode 100644 index 000000000000..0012162fa0d2 --- /dev/null +++ b/UefiPayloadPkg/Library/CustomFdtNodeParserNullLib/CustomFdtNodeParserNullLib.c @@ -0,0 +1,51 @@ +/** @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/IoLib.h> + +#include <Library/PrintLib.h> +#include <Library/FdtLib.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; + + if (HobList != NULL) { + CHobList = (UINTN)HobList; + } + + return CHobList; +} diff --git a/UefiPayloadPkg/Library/FdtParserLib/FdtParserLib.c b/UefiPayloadPkg/Library/FdtParserLib/FdtParserLib.c new file mode 100644 index 000000000000..c18e36661438 --- /dev/null +++ b/UefiPayloadPkg/Library/FdtParserLib/FdtParserLib.c @@ -0,0 +1,622 @@ +/** @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> + +#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; + +/** + 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 + ); + +/** + 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 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; + UINT32 *Data32; + UINT64 *Data64; + UINT64 StartAddress; + INT32 SubNode; + UINT64 NumberOfBytes; + UINT32 Attribute; + UINT8 ECCAttribute; + UINT32 ECCData, ECCData2; + UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *Serial; + UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES *PciRootBridgeInfo; + UNIVERSAL_PAYLOAD_ACPI_TABLE *PlatformAcpiTable; + UNIVERSAL_PAYLOAD_SMBIOS_TABLE *SmbiosTable; + UEFI_PAYLOAD_DEBUG_PRINT_ERROR_LEVEL *DebugPrintErrorLevelInfo; + UNIVERSAL_PAYLOAD_BASE *PayloadBase; + EFI_PEI_GRAPHICS_INFO_HOB *GraphicsInfo; + EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *GraphicsDev; + UINT8 SizeOfMemorySpace; + UINT64 FrameBufferBase; + UINT64 FrameBufferSize; + 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; + + Fdt = FdtBase; + Depth = 0; + FrameBufferBase = 0; + FrameBufferSize = 0; + MinimalNeededSize = FixedPcdGet32 (PcdSystemMemoryUefiRegionSize); + IsHobConstructed = FALSE; + NewHobList = 0; + PlatformAcpiTable = NULL; + SmbiosTable = NULL; + PciRootBridgeInfo = NULL; + RootBridgeCount = 0; + index = 1; + HobDataSize = 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)) { + if (Depth != 1) { + continue; + } + + 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 if (AsciiStrnCmp (NodePtr->Name, "pci-rb", AsciiStrLen ("pci-rb")) == 0) { + RootBridgeCount++; + } + } + + Depth = 0; + for (Node = FdtNextNode (Fdt, 0, &Depth); Node >= 0; Node = FdtNextNode (Fdt, Node, &Depth)) { + if (Depth != 1) { + continue; + } + + 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) { + 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); + } // end of memory node + // reserved-memory + else if (AsciiStrCmp (NodePtr->Name, "reserved-memory") == 0) { + 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); + if (TempLen > 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 (AsciiStrnCmp (NodePtr->Name, "mmio@", AsciiStrLen ("mmio@")) == 0) { + DEBUG ((DEBUG_INFO, " MemoryMappedIO")); + BuildMemoryAllocationHob (StartAddress, NumberOfBytes, EfiMemoryMappedIO); + } else { + PropertyPtr = FdtGetProperty (Fdt, SubNode, "compatible", &TempLen); + if (!(TempLen > 0)) { + BuildMemoryAllocationHob (StartAddress, NumberOfBytes, EfiReservedMemoryType); + continue; + } + + 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 if (AsciiStrnCmp (TempStr, "smbios", AsciiStrLen ("smbios")) == 0) { + DEBUG ((DEBUG_INFO, " build smbios, NumberOfBytes:%x", NumberOfBytes)); + SmbiosTable = BuildGuidHob (&gUniversalPayloadSmbios3TableGuid, sizeof (UNIVERSAL_PAYLOAD_SMBIOS_TABLE) + sizeof (SMBIOS_TABLE_3_0_ENTRY_POINT)); + if (SmbiosTable != NULL) { + SmbiosTable->Header.Revision = UNIVERSAL_PAYLOAD_SMBIOS_TABLE_REVISION; + SmbiosTable->Header.Length = sizeof (UNIVERSAL_PAYLOAD_SMBIOS_TABLE); + SmbiosTable->SmBiosEntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)(&StartAddress); + } + } + } + } + } // end of reserved-memory + + if (AsciiStrnCmp (NodePtr->Name, "serial@", AsciiStrLen ("serial@")) == 0) { + // + // Create SerialPortInfo HOB. + // + Serial = BuildGuidHob (&gUniversalPayloadSerialPortInfoGuid, sizeof (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO)); + ASSERT (Serial != NULL); + if (Serial == NULL) { + break; + } + + Serial->Header.Revision = UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO_REVISION; + Serial->Header.Length = sizeof (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO); + Serial->RegisterStride = 1; + + 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, "current-speed") == 0) { + Data32 = (UINT32 *)(PropertyPtr->Data); + DEBUG ((DEBUG_INFO, "\n Property(%08X) %a", Property, TempStr)); + DEBUG ((DEBUG_INFO, " %X", Fdt32ToCpu (*Data32))); + + Serial->BaudRate = Fdt32ToCpu (*Data32); + } else if (AsciiStrCmp (TempStr, "reg") == 0) { + Data64 = (UINT64 *)(PropertyPtr->Data); + StartAddress = Fdt64ToCpu (*(Data64 + 1)); + DEBUG ((DEBUG_INFO, "\n Property(%08X) %a", Property, TempStr)); + DEBUG ((DEBUG_INFO, " %016lX", StartAddress)); + + Serial->RegisterBase = StartAddress; + } else if (AsciiStrCmp (TempStr, "reg-io-width") == 0) { + Data32 = (UINT32 *)(PropertyPtr->Data); + DEBUG ((DEBUG_INFO, "\n Property(%08X) %a", Property, TempStr)); + DEBUG ((DEBUG_INFO, " %X", Fdt32ToCpu (*Data32))); + Serial->UseMmio = Fdt32ToCpu (*(Data32)) == 4 ? TRUE : FALSE; + } + } + } else if (AsciiStrCmp (NodePtr->Name, "graphic") == 0) { + // + // Create GraphicInfo HOB. + // + GraphicsInfo = BuildGuidHob (&gEfiGraphicsInfoHobGuid, sizeof (EFI_PEI_GRAPHICS_INFO_HOB)); + ASSERT (GraphicsInfo != NULL); + if (GraphicsInfo == NULL) { + break; + } + + GraphicsDev = BuildGuidHob (&gEfiGraphicsDeviceInfoHobGuid, sizeof (EFI_PEI_GRAPHICS_DEVICE_INFO_HOB)); + ASSERT (GraphicsDev != NULL); + if (GraphicsDev == NULL) { + break; + } + + if (FrameBufferBase != 0) { + GraphicsInfo->FrameBufferBase = FrameBufferBase; + } + + if (FrameBufferSize != 0) { + GraphicsInfo->FrameBufferSize = (UINT32)FrameBufferSize; + } + + 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, "resolution") == 0) { + Data32 = (UINT32 *)(PropertyPtr->Data); + GraphicsInfo->GraphicsMode.HorizontalResolution = Fdt32ToCpu (*Data32); + GraphicsInfo->GraphicsMode.VerticalResolution = Fdt32ToCpu (*(Data32 + 1)); + } else if (AsciiStrCmp (TempStr, "pixel-format") == 0) { + Data32 = (UINT32 *)(PropertyPtr->Data); + GraphicsInfo->GraphicsMode.PixelFormat = Fdt32ToCpu (*Data32); + } else if (AsciiStrCmp (TempStr, "pixel-mask") == 0) { + Data32 = (UINT32 *)(PropertyPtr->Data); + GraphicsInfo->GraphicsMode.PixelInformation.RedMask = Fdt32ToCpu (*Data32); + GraphicsInfo->GraphicsMode.PixelInformation.GreenMask = Fdt32ToCpu (*(Data32 + 1)); + GraphicsInfo->GraphicsMode.PixelInformation.BlueMask = Fdt32ToCpu (*(Data32 + 2)); + } else if (AsciiStrCmp (TempStr, "pixe-scanline") == 0) { + Data32 = (UINT32 *)(PropertyPtr->Data); + GraphicsInfo->GraphicsMode.PixelsPerScanLine = Fdt32ToCpu (*Data32); + } else if (AsciiStrCmp (TempStr, "id") == 0) { + Data32 = (UINT32 *)(PropertyPtr->Data); + GraphicsDev->VendorId = Fdt32ToCpu (*Data32) >> 16; + GraphicsDev->DeviceId = Fdt32ToCpu (*Data32) & 0xffff; + } else if (AsciiStrCmp (TempStr, "subsystem-id") == 0) { + Data32 = (UINT32 *)(PropertyPtr->Data); + GraphicsDev->SubsystemVendorId = Fdt32ToCpu (*Data32) >> 16; + GraphicsDev->SubsystemId = Fdt32ToCpu (*Data32) & 0xffff; + } else if (AsciiStrCmp (TempStr, "revision-id") == 0) { + Data32 = (UINT32 *)(PropertyPtr->Data); + GraphicsDev->RevisionId = (UINT8)Fdt32ToCpu (*Data32); + } else if (AsciiStrCmp (TempStr, "bar-index") == 0) { + Data32 = (UINT32 *)(PropertyPtr->Data); + GraphicsDev->BarIndex = (UINT8)Fdt32ToCpu (*Data32); + } + } + } else if (AsciiStrCmp (NodePtr->Name, "options") == 0) { + DEBUG ((DEBUG_INFO, " Found options node (%08X)", Node)); + + 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 EFI_OUT_OF_RESOURCES; + } + + 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, "address_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); + #if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64) + BuildCpuHob (SizeOfMemorySpace, 16); + #else + BuildCpuHob (SizeOfMemorySpace, 0); + #endif + } + } + } + } + // Optional + else if (AsciiStrnCmp (NodePtr->Name, "pci-rb", AsciiStrLen ("pci-rb")) == 0) { + DEBUG ((DEBUG_INFO, " Found pci-rb node (%08X)", Node)); + + HobDataSize = sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES) + RootBridgeCount *sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE); + // + // Create PCI Root Bridge Info Hob. + // + if (PciRootBridgeInfo == NULL) { + PciRootBridgeInfo = BuildGuidHob (&gUniversalPayloadPciRootBridgeInfoGuid, HobDataSize); + ASSERT (PciRootBridgeInfo != NULL); + if (PciRootBridgeInfo == NULL) { + break; + } + + ZeroMem (PciRootBridgeInfo, HobDataSize); + PciRootBridgeInfo->Header.Length = sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES); + PciRootBridgeInfo->Header.Revision = UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES_REVISION; + PciRootBridgeInfo->Count = RootBridgeCount; + PciRootBridgeInfo->ResourceAssigned = FALSE; + } + + 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)\n", TempLen)); + + PciRootBridgeInfo->RootBridge[index].AllocationAttributes = EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM | EFI_PCI_HOST_BRIDGE_MEM64_DECODE; + PciRootBridgeInfo->RootBridge[index].Supports = ROOT_BRIDGE_SUPPORTS_DEFAULT; + PciRootBridgeInfo->RootBridge[index].PMemAbove4G.Base = PcdGet64 (PcdPciReservedPMemAbove4GBBase); + PciRootBridgeInfo->RootBridge[index].PMemAbove4G.Limit = PcdGet64 (PcdPciReservedPMemAbove4GBLimit); + PciRootBridgeInfo->RootBridge[index].PMem.Base = PcdGet32 (PcdPciReservedPMemBase); + PciRootBridgeInfo->RootBridge[index].PMem.Limit = PcdGet32 (PcdPciReservedPMemLimit); + PciRootBridgeInfo->RootBridge[index].UID = index; + PciRootBridgeInfo->RootBridge[index].HID = EISA_PNP_ID (0x0A03); + + Data32 = (UINT32 *)(PropertyPtr->Data); + PciRootBridgeInfo->RootBridge[index].Mem.Base = Fdt32ToCpu (*(Data32 + 2)); + PciRootBridgeInfo->RootBridge[index].Mem.Limit = Fdt32ToCpu (*(Data32 + 6)) + Fdt32ToCpu (*(Data32 + 2)) -1; + PciRootBridgeInfo->RootBridge[index].MemAbove4G.Base = Fdt32ToCpu (*(Data32 + 9)) + LShiftU64 (Fdt32ToCpu (*(Data32 + 8)), 32); + PciRootBridgeInfo->RootBridge[index].MemAbove4G.Limit = PciRootBridgeInfo->RootBridge[index].MemAbove4G.Base + LShiftU64 (Fdt32ToCpu (*(Data32 + 12)), 32) + Fdt32ToCpu (*(Data32 + 13)) -1; + PciRootBridgeInfo->RootBridge[index].Io.Base = Fdt32ToCpu (*(Data32 + 16)); + PciRootBridgeInfo->RootBridge[index].Io.Limit = PciRootBridgeInfo->RootBridge[index].Io.Base + Fdt32ToCpu (*(Data32 + 20)) -1; + + DEBUG ((DEBUG_INFO, "RootBridgeCount %x, index :%x\n", RootBridgeCount, index)); + + DEBUG ((DEBUG_INFO, "PciRootBridge->Mem.Base %x, \n", PciRootBridgeInfo->RootBridge[index].Mem.Base)); + DEBUG ((DEBUG_INFO, "PciRootBridge->Mem.limit %x, \n", PciRootBridgeInfo->RootBridge[index].Mem.Limit)); + + DEBUG ((DEBUG_INFO, "PciRootBridge->MemAbove4G.Base %llx, \n", PciRootBridgeInfo->RootBridge[index].MemAbove4G.Base)); + DEBUG ((DEBUG_INFO, "PciRootBridge->MemAbove4G.limit %llx, \n", PciRootBridgeInfo->RootBridge[index].MemAbove4G.Limit)); + + DEBUG ((DEBUG_INFO, "PciRootBridge->Io.Base %llx, \n", PciRootBridgeInfo->RootBridge[index].Io.Base)); + DEBUG ((DEBUG_INFO, "PciRootBridge->Io.limit %llx, \n", PciRootBridgeInfo->RootBridge[index].Io.Limit)); + if (index > 0) { + index--; + } + } + + if (AsciiStrCmp (TempStr, "bus-range") == 0) { + UINT16 *Data16; + + DEBUG ((DEBUG_INFO, " Found bus-range Property TempLen (%08X)\n", TempLen)); + + if (RootBridgeCount == 1) { + index = 0; + } + + Data16 = (UINT16 *)(PropertyPtr->Data); + PciRootBridgeInfo->RootBridge[index].Bus.Base = Fdt16ToCpu (*Data16) & 0xFF; + PciRootBridgeInfo->RootBridge[index].Bus.Limit = Fdt16ToCpu (*(Data16 + 1)) & 0xFF; + PciRootBridgeInfo->RootBridge[index].Bus.Translation = 0; + + DEBUG ((DEBUG_INFO, "PciRootBridge->Bus.Base %x, \n", PciRootBridgeInfo->RootBridge[index].Bus.Base)); + DEBUG ((DEBUG_INFO, "PciRootBridge->Bus.limit %x, \n", PciRootBridgeInfo->RootBridge[index].Bus.Limit)); + } + } + } else if (AsciiStrCmp (NodePtr->Name, "DebugPrintErrorLevel") == 0) { + // + // Create DebugPrintErrorLevel Hob. + // + DebugPrintErrorLevelInfo = BuildGuidHob (&gEdkiiDebugPrintErrorLevelGuid, sizeof (UEFI_PAYLOAD_DEBUG_PRINT_ERROR_LEVEL)); + ASSERT (DebugPrintErrorLevelInfo != NULL); + if (DebugPrintErrorLevelInfo == NULL) { + break; + } + + DebugPrintErrorLevelInfo->Header.Revision = UEFI_PAYLOAD_DEBUG_PRINT_ERROR_LEVEL_REVISION; + DebugPrintErrorLevelInfo->Header.Length = sizeof (UEFI_PAYLOAD_DEBUG_PRINT_ERROR_LEVEL); + + PropertyPtr = FdtGetProperty (Fdt, Node, "errorlevel", &TempLen); + ASSERT (TempLen > 0); + if (TempLen > 0) { + Data32 = (UINT32 *)(PropertyPtr->Data); + DEBUG ((DEBUG_INFO, "\n Property(00000000) errorlevel")); + DEBUG ((DEBUG_INFO, " %X", Fdt32ToCpu (*Data32))); + DebugPrintErrorLevelInfo->ErrorLevel = Fdt32ToCpu (*Data32); + } + } + } + + 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 build a graphic device hob. + + @retval EFI_SUCCESS If it completed successfully. + @retval Others If it failed to parse DTB. +**/ +EFI_STATUS +BuildGraphicDevHob ( + VOID + ); + +/** + 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 000000000000..72da4fcaf74f --- /dev/null +++ b/UefiPayloadPkg/Library/HobParseLib/HobParseLib.c @@ -0,0 +1,408 @@ +/** @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; +} + +/** + It will build HOBs based on information from bootloaders. + + @param[in] BootloaderParameter The starting memory address of bootloader parameter block. + + @retval EFI_SUCCESS If it completed successfully. + @retval Others If it failed to build required HOBs. +**/ +EFI_STATUS +BuildHobs ( + IN UINTN BootloaderParameter + ) +{ + EFI_PEI_HOB_POINTERS Hob; + UINTN MinimalNeededSize; + EFI_PHYSICAL_ADDRESS FreeMemoryBottom; + EFI_PHYSICAL_ADDRESS FreeMemoryTop; + EFI_PHYSICAL_ADDRESS MemoryBottom; + EFI_PHYSICAL_ADDRESS MemoryTop; + EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob; + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; + + #if (!FixedPcdGetBool (PcdHandOffFdtEnable)) + UINT8 *GuidHob; + UNIVERSAL_PAYLOAD_ACPI_TABLE *AcpiTable; + ACPI_BOARD_INFO *AcpiBoardInfo; + #endif + EFI_HOB_HANDOFF_INFO_TABLE *HobInfo; + + Hob.Raw = (UINT8 *)BootloaderParameter; + MinimalNeededSize = FixedPcdGet32 (PcdSystemMemoryUefiRegionSize); + + ASSERT (Hob.Raw != NULL); + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryTop == Hob.HandoffInformationTable->EfiFreeMemoryTop); + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryTop == Hob.HandoffInformationTable->EfiMemoryTop); + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryBottom == Hob.HandoffInformationTable->EfiFreeMemoryBottom); + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryBottom == Hob.HandoffInformationTable->EfiMemoryBottom); + + // + // Try to find Resource Descriptor HOB that contains Hob range EfiMemoryBottom..EfiMemoryTop + // + PhitResourceHob = FindResourceDescriptorByRange (Hob.Raw, Hob.HandoffInformationTable->EfiMemoryBottom, Hob.HandoffInformationTable->EfiMemoryTop); + if (PhitResourceHob == NULL) { + // + // Boot loader's Phit Hob is not in an available Resource Descriptor, find another Resource Descriptor for new Phit Hob + // + ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, MinimalNeededSize, NULL); + if (ResourceHob == NULL) { + return EFI_NOT_FOUND; + } + + MemoryBottom = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize; + FreeMemoryBottom = MemoryBottom; + FreeMemoryTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength; + MemoryTop = FreeMemoryTop; + } else if (PhitResourceHob->PhysicalStart + PhitResourceHob->ResourceLength - Hob.HandoffInformationTable->EfiMemoryTop >= MinimalNeededSize) { + // + // New availiable Memory range in new hob is right above memory top in old hob. + // + MemoryBottom = Hob.HandoffInformationTable->EfiFreeMemoryTop; + FreeMemoryBottom = Hob.HandoffInformationTable->EfiMemoryTop; + FreeMemoryTop = FreeMemoryBottom + MinimalNeededSize; + MemoryTop = FreeMemoryTop; + } else if (Hob.HandoffInformationTable->EfiMemoryBottom - PhitResourceHob->PhysicalStart >= MinimalNeededSize) { + // + // New availiable Memory range in new hob is right below memory bottom in old hob. + // + MemoryBottom = Hob.HandoffInformationTable->EfiMemoryBottom - MinimalNeededSize; + FreeMemoryBottom = MemoryBottom; + FreeMemoryTop = Hob.HandoffInformationTable->EfiMemoryBottom; + MemoryTop = Hob.HandoffInformationTable->EfiMemoryTop; + } else { + // + // In the Resource Descriptor HOB contains boot loader Hob, there is no enough free memory size for payload hob + // Find another Resource Descriptor Hob + // + ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, MinimalNeededSize, PhitResourceHob); + if (ResourceHob == NULL) { + return EFI_NOT_FOUND; + } + + MemoryBottom = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize; + FreeMemoryBottom = MemoryBottom; + FreeMemoryTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength; + MemoryTop = FreeMemoryTop; + } + + HobInfo = HobConstructor ((VOID *)(UINTN)MemoryBottom, (VOID *)(UINTN)MemoryTop, (VOID *)(UINTN)FreeMemoryBottom, (VOID *)(UINTN)FreeMemoryTop); + HobInfo->BootMode = Hob.HandoffInformationTable->BootMode; + // + // From now on, mHobList will point to the new Hob range. + // + + // + // Create an empty FvHob for the DXE FV that contains DXE core. + // + BuildFvHob ((EFI_PHYSICAL_ADDRESS)0, 0); + // + // Since payload created new Hob, move all hobs except PHIT from boot loader hob list. + // + Hob.Raw = (UINT8 *)BootloaderParameter; + while (!END_OF_HOB_LIST (Hob)) { + if (IsHobNeed (Hob)) { + // Add this hob to payload HOB + AddNewHob (&Hob); + } + + Hob.Raw = GET_NEXT_HOB (Hob); + } + + #if (!FixedPcdGetBool (PcdHandOffFdtEnable)) + // + // Create guid hob for acpi board information + // + DEBUG ((DEBUG_INFO, "Create guid hob for acpi board information \n")); + + GuidHob = GetFirstGuidHob (&gUniversalPayloadAcpiTableGuid); + if (GuidHob != NULL) { + AcpiTable = (UNIVERSAL_PAYLOAD_ACPI_TABLE *)GET_GUID_HOB_DATA (GuidHob); + AcpiBoardInfo = BuildHobFromAcpi ((UINT64)AcpiTable->Rsdp); + ASSERT (AcpiBoardInfo != NULL); + } + + #endif + + return EFI_SUCCESS; +} diff --git a/UefiPayloadPkg/Library/CustomFdtNodeParserLib/CustomFdtNodeParserLib.inf b/UefiPayloadPkg/Library/CustomFdtNodeParserLib/CustomFdtNodeParserLib.inf new file mode 100644 index 000000000000..036ed4315dd0 --- /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.inf b/UefiPayloadPkg/Library/CustomFdtNodeParserNullLib/CustomFdtNodeParserNullLib.inf new file mode 100644 index 000000000000..62916dd00848 --- /dev/null +++ b/UefiPayloadPkg/Library/CustomFdtNodeParserNullLib/CustomFdtNodeParserNullLib.inf @@ -0,0 +1,33 @@ +## @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 + MdeModulePkg/MdeModulePkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[LibraryClasses] + DebugLib + FdtLib diff --git a/UefiPayloadPkg/Library/FdtParserLib/FdtParseLib.inf b/UefiPayloadPkg/Library/FdtParserLib/FdtParseLib.inf new file mode 100644 index 000000000000..91be56758db5 --- /dev/null +++ b/UefiPayloadPkg/Library/FdtParserLib/FdtParseLib.inf @@ -0,0 +1,63 @@ +## @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 + + +[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/HobParseLib/HobParseLib.inf b/UefiPayloadPkg/Library/HobParseLib/HobParseLib.inf new file mode 100644 index 000000000000..634c7ff56746 --- /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 -- 2.39.2.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#119197): https://edk2.groups.io/g/devel/message/119197 Mute This Topic: https://groups.io/mt/106275995/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-