public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Chiu, Chasel" <chasel.chiu@intel.com>
To: "Liu, Linus" <linus.liu@intel.com>,
	"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: "Lin, Benny" <benny.lin@intel.com>,
	"Guo, Gua" <gua.guo@intel.com>, "Lu, James" <james.lu@intel.com>,
	Dhaval Sharma <dhaval@rivosinc.com>,
	"Dong, Guo" <guo.dong@intel.com>
Subject: Re: [edk2-devel] [PATCH v3 5/6] UefiPayloadPkg: Add FDT Paser relative LIBs.
Date: Wed, 29 May 2024 20:25:20 +0000	[thread overview]
Message-ID: <BN9PR11MB548384DBB9CEC45C7C6F05CBE6F22@BN9PR11MB5483.namprd11.prod.outlook.com> (raw)
In-Reply-To: <20240524041400.1231-1-linus.liu@intel.com>


Hi Linus,

Some comments below inline.

Thanks,
Chasel


> -----Original Message-----
> From: Liu, Linus <linus.liu@intel.com>
> Sent: Thursday, May 23, 2024 9:14 PM
> To: devel@edk2.groups.io
> Cc: Lin, Benny <benny.lin@intel.com>; Guo, Gua <gua.guo@intel.com>; Chiu,
> Chasel <chasel.chiu@intel.com>; Lu, James <james.lu@intel.com>; Dhaval
> Sharma <dhaval@rivosinc.com>
> Subject: [PATCH v3 5/6] UefiPayloadPkg: Add FDT Paser relative LIBs.
> 
> Add FDTParser and CustomFdtNodePaser
> to retrive all FDT node and create the relate hobs.
> 
> 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/Library/CustomFdtNodeParserLib/CustomFdtNodeParserLib.c
> | 158 +++++
> 
> UefiPayloadPkg/Library/CustomFdtNodeParserNullLib/CustomFdtNodeParserNul
> lLib.c   |  51 ++
>  UefiPayloadPkg/Library/FdtParserLib/FdtParserLib.c                               | 622
> ++++++++++++++++++++
>  UefiPayloadPkg/Library/HobParseLib/HobParseLib.c                                 | 408
> +++++++++++++
>  UefiPayloadPkg/Library/CustomFdtNodeParserLib/CustomFdtNodeParserLib.inf
> |  46 ++
> 
> UefiPayloadPkg/Library/CustomFdtNodeParserNullLib/CustomFdtNodeParserNul
> lLib.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/CustomFdtNodeParserN
> ullLib.c
> b/UefiPayloadPkg/Library/CustomFdtNodeParserNullLib/CustomFdtNodeParserN
> ullLib.c
> new file mode 100644
> index 000000000000..0012162fa0d2
> --- /dev/null
> +++
> b/UefiPayloadPkg/Library/CustomFdtNodeParserNullLib/CustomFdtNodeParserN
> ullLib.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;





reg-io-width is reg data width, not reg base address width, so UPL has to rely on address-cells=3 to know base address type from the reg property.
Please help to correct this and we require address-cells=3 for those UPL consumed nodes which having reg or ranges properties.






> 
> +        }
> 
> +      }
> 
> +    } 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);
> 
> +        }
> 





Per UPL specification, 'graphic' node should be 'framebuffer' node, example as below:
1. Fill HOB frameBufferBase/Size by FDT framebuffer->reg

2. Fill HOB for X and Y:
  GraphicsInfo->GraphicsMode.HorizontalResolution = framebuffer->width 
  GraphicsInfo->GraphicsMode.VerticalResolution = framebuffer->height

3. use framebuffer->format property to fill PixelFormat:
  GraphicsInfo->GraphicsMode.PixelFormat : framebuffer->format:
    PixelRedGreenBlueReserved8BitPerColor : 'a8r8g8b8'
    PixelBlueGreenRedReserved8BitPerColor :  'a8b8g8r8'
    PixelFormatMax (Unsupported by current UefiPayload) : 'a16b16g16r16'

4. HOB PixelInformation (BitMask) currently is not used by UPL, you may keep them as 0.

5. Fill HOB PixelsPerScanLine
  GraphicsInfo->GraphicsMode.PixelsPerScanLine = framebuffer->stride

6. GraphicsDev HOB is for PCI GFX device only and all fields should be filled by "PCI GFX device node", which will be pointed by framebuffer->display. Below is example of PCI GFX node

rb@E0000000 {
      compatible = "pci-host-ecam-generic";
      reg = <...>
      ranges = <...>;
	gma@E0010000 {
                 /* gfx device 00:02:00 */
                vendor-id = <0x8086>
                device-id = <0x4680>
                revision-id = <0x4>
                subsystem-vendor-id = <0x8086>
                subsystem-id = <0x2212>
            };
      };
};

framebuffer@b0000000 {
    compatible = "simple-framebuffer";
    reg = <0x82000000, 0x0, 0xb0000000, 0x400, 0x500000>; //base 0xB0000000, size=0x4000500000
    width = <3840>;
    height = <2160>;
    format = "a8r8g8b8";
    display = <&gma>;
};

Note1: GraphicsDev HOB default is all 0xFF, please SetMem() of this buffer to 0xFF before parsing FDT nodes.
Note2: GraphicsDev->BarIndex is not part of standard DT PCI binding, so leave it as default 0xFF.








> +      }
> 
> +    } 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
> 
> +          }
> 





1. We also need to fill BootMode from FDT upl-params->BootMode:
  convert upl-params->boot-mode string to bootmode_enum
  (EFI_HOB_HANDOFF_INFO_TABLE) (UINTN) mHobList->BootMode = bootmode_enum;

2. UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES->ResourceAssigned HOB data should be filled by upl-params->pci-enum-done (when present, set to 1)








> +        }
> 
> +      }
> 
> +    }
> 
> +    // 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;
> 
> +      }
> 







DebugPrintErrorLevel node is not defined in UPL spec, please remove relevant code here.
If required gEdkiiDebugPrintErrorLevelGuid hob can be passed by CustomFdtNode as it is EDK2 specific implementation.








> +
> 
> +      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.in
> f
> b/UefiPayloadPkg/Library/CustomFdtNodeParserLib/CustomFdtNodeParserLib.in
> f
> new file mode 100644
> index 000000000000..036ed4315dd0
> --- /dev/null
> +++
> b/UefiPayloadPkg/Library/CustomFdtNodeParserLib/CustomFdtNodeParserLib.in
> f
> @@ -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/CustomFdtNodeParserN
> ullLib.inf
> b/UefiPayloadPkg/Library/CustomFdtNodeParserNullLib/CustomFdtNodeParserN
> ullLib.inf
> new file mode 100644
> index 000000000000..62916dd00848
> --- /dev/null
> +++
> b/UefiPayloadPkg/Library/CustomFdtNodeParserNullLib/CustomFdtNodeParserN
> ullLib.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 (#119366): https://edk2.groups.io/g/devel/message/119366
Mute This Topic: https://groups.io/mt/106275995/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



      reply	other threads:[~2024-05-29 20:25 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-24  4:14 [edk2-devel] [PATCH v3 5/6] UefiPayloadPkg: Add FDT Paser relative LIBs Linus Liu
2024-05-29 20:25 ` Chiu, Chasel [this message]

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=BN9PR11MB548384DBB9CEC45C7C6F05CBE6F22@BN9PR11MB5483.namprd11.prod.outlook.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