public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Sheng Lean Tan" <sheng.tan@9elements.com>
To: devel@edk2.groups.io, gua.guo@intel.com
Cc: "Wang, BruceX" <brucex.wang@intel.com>,
	"Dong, Guo" <guo.dong@intel.com>,
	 "Rhodes, Sean" <sean@starlabs.systems>,
	"Lu, James" <james.lu@intel.com>
Subject: Re: [edk2-devel] [PATCH v2 2/2] UefiPayloadPkg: Add FIT support
Date: Fri, 15 Sep 2023 12:26:48 +0200	[thread overview]
Message-ID: <CAMWxwJ2u77rG2E8AYuq7StapDsDmFxfZeO_Nj_e8zE9265evLg@mail.gmail.com> (raw)
In-Reply-To: <BL1PR11MB54785FC13F4813D593230A28EFF6A@BL1PR11MB5478.namprd11.prod.outlook.com>

[-- Attachment #1: Type: text/plain, Size: 102196 bytes --]

Hi,
It looks good to me, but could you help to update these 2 parts:
1. the copyright year should be 2023 instead of 2021?
2. the correct UPL spec website should be universalpayload.github.io/spec

Thanks,
Sheng

On Fri, 15 Sept 2023 at 11:02, Guo, Gua <gua.guo@intel.com> wrote:

> Reviewed-by: Gua Guo <gua.guo@intel.com>
>
> -----Original Message-----
> From: Wang, BruceX <brucex.wang@intel.com>
> Sent: Friday, September 15, 2023 4:58 PM
> To: devel@edk2.groups.io
> Cc: Wang, BruceX <brucex.wang@intel.com>; Dong, Guo <guo.dong@intel.com>;
> Rhodes, Sean <sean@starlabs.systems>; Lu, James <james.lu@intel.com>;
> Guo, Gua <gua.guo@intel.com>
> Subject: [PATCH v2 2/2] UefiPayloadPkg: Add FIT support
>
> From: "Brucex.Wang" <brucex.wang@intel.com>
>
> Provide Fit format for UniversalPayload, developer can use argument
> "--Fit" to build UniversalPayload.fit
>
> Cc: Guo Dong <guo.dong@intel.com>
> Cc: Sean Rhodes <sean@starlabs.systems>
> Cc: James Lu <james.lu@intel.com>
> Cc: Gua Guo <gua.guo@intel.com>
>
> Signed-off-by: BruceX Wang <brucex.wang@intel.com>
> ---
>  .../Include/Guid/UniversalPayloadBase.h       |  21 +
>  UefiPayloadPkg/PayloadLoaderPeim/FitLib.h     |  60 ++
>  .../PayloadLoaderPeim/FitLib/FitLib.c         | 127 ++++
>  .../PayloadLoaderPeim/FitPayloadLoaderPeim.c  | 150 ++++
>  .../FitPayloadLoaderPeim.inf                  |  59 ++
>  UefiPayloadPkg/Readme.md                      | 191 +++++
>  UefiPayloadPkg/Tools/MkFitImage.py            | 272 ++++++++
>  .../FitUniversalPayloadEntry.c                | 654 ++++++++++++++++++
>  .../FitUniversalPayloadEntry.inf              |  98 +++
>  UefiPayloadPkg/UefiPayloadPkg.dec             |   3 +
>  UefiPayloadPkg/UefiPayloadPkg.dsc             |  27 +-
>  UefiPayloadPkg/UniversalPayloadBuild.py       | 328 ++++++---
>  12 files changed, 1894 insertions(+), 96 deletions(-)
>  create mode 100644 UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
>  create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
>  create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
>  create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
>  create mode 100644
> UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
>  create mode 100644 UefiPayloadPkg/Readme.md
>  create mode 100644 UefiPayloadPkg/Tools/MkFitImage.py
>  create mode 100644
> UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
>  create mode 100644
> UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
>
> diff --git a/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
> b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
> new file mode 100644
> index 0000000000..31c9ec0bfb
> --- /dev/null
> +++ b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
> @@ -0,0 +1,21 @@
> +/** @file
>
> +  Universal Payload general definitions.
>
> +
>
> +Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +  @par Revision Reference:
>
> +    - Universal Payload Specification 0.75 (
> https://universalpayload.github.io/documentation/)
>
> +**/
>
> +
>
> +#ifndef UNIVERSAL_PAYLOAD_BASE_H_
>
> +#define UNIVERSAL_PAYLOAD_BASE_H_
>
> +
>
> +extern GUID  gUniversalPayloadBaseGuid;
>
> +
>
> +typedef struct {
>
> +  UNIVERSAL_PAYLOAD_GENERIC_HEADER    Header;
>
> +  EFI_PHYSICAL_ADDRESS                Entry;
>
> +} UNIVERSAL_PAYLOAD_BASE;
>
> +
>
> +#endif // UNIVERSAL_PAYLOAD_BASE_H_
>
> diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
> b/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
> new file mode 100644
> index 0000000000..0514d675a6
> --- /dev/null
> +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
> @@ -0,0 +1,60 @@
> +/** @file
>
> +  FIT Load Image Support
>
> +Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +**/
>
> +
>
> +#ifndef FIT_LIB_H_
>
> +#define FIT_LIB_H_
>
> +
>
> +#include <PiPei.h>
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/FdtLib.h>
>
> +
>
> +typedef struct {
>
> +  UINT64    RelocateType;
>
> +  UINT64    Offset;
>
> +} FIT_RELOCATE_ITEM;
>
> +
>
> +typedef struct {
>
> +  EFI_PHYSICAL_ADDRESS    ImageBase;
>
> +  EFI_PHYSICAL_ADDRESS    PayloadBaseAddress;
>
> +  UINT64                  PayloadSize;
>
> +  UINTN                   PayloadEntryOffset;
>
> +  UINTN                   PayloadEntrySize;
>
> +  EFI_PHYSICAL_ADDRESS    PayloadEntryPoint;
>
> +  UINTN                   RelocateTableOffset;
>
> +  UINTN                   RelocateTableCount;
>
> +  EFI_PHYSICAL_ADDRESS    PayloadLoadAddress;
>
> +} FIT_IMAGE_CONTEXT;
>
> +
>
> +typedef struct {
>
> +  UINT8     *Name;
>
> +  UINT32    Offset;
>
> +} PROPERTY_DATA;
>
> +
>
> +#define IMAGE_BASE_OFFSET             OFFSET_OF (FIT_IMAGE_CONTEXT,
> ImageBase)
>
> +#define PAYLOAD_BASE_ADDR_OFFSET      OFFSET_OF (FIT_IMAGE_CONTEXT,
> PayloadBaseAddress)
>
> +#define PAYLOAD_BASE_SIZE_OFFSET      OFFSET_OF (FIT_IMAGE_CONTEXT,
> PayloadSize)
>
> +#define PAYLOAD_ENTRY_OFFSET_OFFSET   OFFSET_OF (FIT_IMAGE_CONTEXT,
> PayloadEntryOffset)
>
> +#define PAYLOAD_ENTRY_SIZE_OFFSET     OFFSET_OF (FIT_IMAGE_CONTEXT,
> PayloadEntrySize)
>
> +#define PAYLOAD_ENTRY_POINT_OFFSET    OFFSET_OF (FIT_IMAGE_CONTEXT,
> PayloadEntryPoint)
>
> +#define RELOCATE_TABLE_OFFSET_OFFSET  OFFSET_OF (FIT_IMAGE_CONTEXT,
> RelocateTableOffset)
>
> +#define RELOCATE_TABLE_COUNT_OFFSET   OFFSET_OF (FIT_IMAGE_CONTEXT,
> RelocateTableCount)
>
> +#define PAYLOAD_LOAD_ADDR_OFFSET      OFFSET_OF (FIT_IMAGE_CONTEXT,
> PayloadLoadAddress)
>
> +
>
> +/**
>
> +  Parse the FIT image info.
>
> +  @param[in]  ImageBase      Memory address of an image.
>
> +  @param[out] Context        The FIT image context pointer.
>
> +  @retval EFI_UNSUPPORTED         Unsupported binary type.
>
> +  @retval EFI_SUCCESS             FIT binary is loaded successfully.
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +ParseFitImage (
>
> +  IN   VOID               *ImageBase,
>
> +  OUT  FIT_IMAGE_CONTEXT  *Context
>
> +  );
>
> +
>
> +#endif
>
> diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
> b/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
> new file mode 100644
> index 0000000000..9d1d8a4f61
> --- /dev/null
> +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
> @@ -0,0 +1,127 @@
> +/** @file
>
> +  FIT Load Image Support
>
> +Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +**/
>
> +
>
> +#include "FitLib.h"
>
> +
>
> +PROPERTY_DATA  PropertyData32List[] = {
>
> +  { "data-offset", PAYLOAD_ENTRY_OFFSET_OFFSET  },
>
> +  { "data-size",   PAYLOAD_ENTRY_SIZE_OFFSET    },
>
> +  { "reloc-start", RELOCATE_TABLE_OFFSET_OFFSET }
>
> +};
>
> +
>
> +PROPERTY_DATA  PropertyData64List[] = {
>
> +  { "entry-start", PAYLOAD_ENTRY_POINT_OFFSET },
>
> +  { "load",        PAYLOAD_LOAD_ADDR_OFFSET   }
>
> +};
>
> +
>
> +/**
>
> +  Parse the target firmware image info in FIT.
>
> +  @param[in]  Fdt            Memory address of a fdt.
>
> +  @param[in]  Firmware       Target name of an image.
>
> +  @param[out] Context        The FIT image context pointer.
>
> +  @retval EFI_NOT_FOUND      FIT node dose not find.
>
> +  @retval EFI_SUCCESS        FIT binary is loaded successfully.
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +FitParseFirmwarePropertyData (
>
> +  IN   VOID               *Fdt,
>
> +  IN   CHAR8              *Firmware,
>
> +  OUT  FIT_IMAGE_CONTEXT  *Context
>
> +  )
>
> +{
>
> +  CONST FDT_PROPERTY  *PropertyPtr;
>
> +  INT32               ImageNode;
>
> +  INT32               TianoNode;
>
> +  INT32               TempLen;
>
> +  UINT32              *Data32;
>
> +  UINT64              *Data64;
>
> +  UINT32              *ContextOffset32;
>
> +  UINT64              *ContextOffset64;
>
> +  INT32               Index;
>
> +
>
> +  ImageNode = FdtSubnodeOffsetNameLen (Fdt, 0, "images",
> (INT32)AsciiStrLen ("images"));
>
> +  if (ImageNode <= 0) {
>
> +    return EFI_NOT_FOUND;
>
> +  }
>
> +
>
> +  TianoNode = FdtSubnodeOffsetNameLen (Fdt, ImageNode, Firmware,
> (INT32)AsciiStrLen (Firmware));
>
> +  if (TianoNode <= 0) {
>
> +    return EFI_NOT_FOUND;
>
> +  }
>
> +
>
> +  for (Index = 0; Index < sizeof (PropertyData32List) / sizeof
> (PROPERTY_DATA); Index++) {
>
> +    PropertyPtr      = FdtGetProperty (Fdt, TianoNode,
> PropertyData32List[Index].Name, &TempLen);
>
> +    Data32           = (UINT32 *)(PropertyPtr->Data);
>
> +    ContextOffset32  = (UINT32 *)((UINTN)Context +
> PropertyData32List[Index].Offset);
>
> +    *ContextOffset32 = Fdt32ToCpu (*Data32);
>
> +  }
>
> +
>
> +  for (Index = 0; Index < sizeof (PropertyData64List)/sizeof
> (PROPERTY_DATA); Index++) {
>
> +    PropertyPtr      = FdtGetProperty (Fdt, TianoNode,
> PropertyData64List[Index].Name, &TempLen);
>
> +    Data64           = (UINT64 *)(PropertyPtr->Data);
>
> +    ContextOffset64  = (UINT64 *)((UINTN)Context +
> PropertyData64List[Index].Offset);
>
> +    *ContextOffset64 = Fdt64ToCpu (*Data64);
>
> +  }
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Parse the FIT image info.
>
> +  @param[in]  ImageBase      Memory address of an image.
>
> +  @param[out] Context        The FIT image context pointer.
>
> +  @retval EFI_UNSUPPORTED         Unsupported binary type.
>
> +  @retval EFI_SUCCESS             FIT binary is loaded successfully.
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +ParseFitImage (
>
> +  IN   VOID               *ImageBase,
>
> +  OUT  FIT_IMAGE_CONTEXT  *Context
>
> +  )
>
> +{
>
> +  VOID                *Fdt;
>
> +  INT32               ConfigNode;
>
> +  INT32               Config1Node;
>
> +  CONST FDT_PROPERTY  *PropertyPtr;
>
> +  INT32               TempLen;
>
> +  UINT32              *Data32;
>
> +  UINT64              Value;
>
> +  EFI_STATUS          Status;
>
> +  UINTN               UplSize;
>
> +  CHAR8               *Firmware;
>
> +
>
> +  Status = FdtCheckHeader (ImageBase);
>
> +  if (EFI_ERROR (Status)) {
>
> +    return EFI_UNSUPPORTED;
>
> +  }
>
> +
>
> +  Fdt         = ImageBase;
>
> +  PropertyPtr = FdtGetProperty (Fdt, 0, "size", &TempLen);
>
> +  Data32      = (UINT32 *)(PropertyPtr->Data);
>
> +  UplSize     = Value = Fdt32ToCpu (*Data32);
>
> +  ConfigNode  = FdtSubnodeOffsetNameLen (Fdt, 0, "configurations",
> (INT32)AsciiStrLen ("configurations"));
>
> +  if (ConfigNode <= 0) {
>
> +    return EFI_NOT_FOUND;
>
> +  }
>
> +
>
> +  Config1Node = FdtSubnodeOffsetNameLen (Fdt, ConfigNode, "conf-1",
> (INT32)AsciiStrLen ("conf-1"));
>
> +  if (Config1Node <= 0) {
>
> +    return EFI_NOT_FOUND;
>
> +  }
>
> +
>
> +  PropertyPtr = FdtGetProperty (Fdt, Config1Node, "firmware", &TempLen);
>
> +  Firmware    = (CHAR8 *)(PropertyPtr->Data);
>
> +
>
> +  FitParseFirmwarePropertyData (Fdt, Firmware, Context);
>
> +
>
> +  Context->ImageBase          = (EFI_PHYSICAL_ADDRESS)ImageBase;
>
> +  Context->PayloadSize        = UplSize;
>
> +  Context->RelocateTableCount = (Context->PayloadEntrySize -
> (Context->RelocateTableOffset - Context->PayloadEntryOffset)) / sizeof
> (FIT_RELOCATE_ITEM);
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
> b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
> new file mode 100644
> index 0000000000..3c5dacbb65
> --- /dev/null
> +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
> @@ -0,0 +1,150 @@
> +/** @file
>
> +  ELF Load Image Support
>
> +Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +**/
>
> +
>
> +#include <PiPei.h>
>
> +#include <UniversalPayload/UniversalPayload.h>
>
> +#include <Guid/UniversalPayloadBase.h>
>
> +#include <UniversalPayload/ExtraData.h>
>
> +
>
> +#include <Ppi/LoadFile.h>
>
> +
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/HobLib.h>
>
> +#include <Library/PeiServicesLib.h>
>
> +#include <Library/MemoryAllocationLib.h>
>
> +#include <Library/BaseMemoryLib.h>
>
> +
>
> +#include "FitLib.h"
>
> +
>
> +/**
>
> +  The wrapper function of PeiLoadImageLoadImage().
>
> +  @param This            - Pointer to EFI_PEI_LOAD_FILE_PPI.
>
> +  @param FileHandle      - Pointer to the FFS file header of the image.
>
> +  @param ImageAddressArg - Pointer to PE/TE image.
>
> +  @param ImageSizeArg    - Size of PE/TE image.
>
> +  @param EntryPoint      - Pointer to entry point of specified image file
> for output.
>
> +  @param AuthenticationState - Pointer to attestation authentication
> state of image.
>
> +  @return Status of PeiLoadImageLoadImage().
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +PeiLoadFileLoadPayload (
>
> +  IN     CONST EFI_PEI_LOAD_FILE_PPI  *This,
>
> +  IN     EFI_PEI_FILE_HANDLE          FileHandle,
>
> +  OUT    EFI_PHYSICAL_ADDRESS         *ImageAddressArg   OPTIONAL,
>
> +  OUT    UINT64                       *ImageSizeArg      OPTIONAL,
>
> +  OUT    EFI_PHYSICAL_ADDRESS         *EntryPoint,
>
> +  OUT    UINT32                       *AuthenticationState
>
> +  )
>
> +{
>
> +  EFI_STATUS              Status;
>
> +  FIT_IMAGE_CONTEXT       Context;
>
> +  UINTN                   Instance;
>
> +  VOID                    *Binary;
>
> +  FIT_RELOCATE_ITEM       *RelocateTable;
>
> +  UNIVERSAL_PAYLOAD_BASE  *PayloadBase;
>
> +  UINTN                   Length;
>
> +  UINTN                   Delta;
>
> +  UINTN                   Index;
>
> +
>
> +  Instance = 0;
>
> +  do {
>
> +    Status = PeiServicesFfsFindSectionData3 (EFI_SECTION_RAW, Instance++,
> FileHandle, &Binary, AuthenticationState);
>
> +    if (EFI_ERROR (Status)) {
>
> +      return Status;
>
> +    }
>
> +
>
> +    ZeroMem (&Context, sizeof (Context));
>
> +    Status = ParseFitImage (Binary, &Context);
>
> +  } while (EFI_ERROR (Status));
>
> +
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    return Status;
>
> +  }
>
> +
>
> +  DEBUG ((
>
> +    DEBUG_INFO,
>
> +    "Before Rebase Payload File Base: 0x%08x, File Size: 0x%08X,
> EntryPoint: 0x%08x\n",
>
> +    Context.PayloadBaseAddress,
>
> +    Context.PayloadSize,
>
> +    Context.PayloadEntryPoint
>
> +    ));
>
> +  Context.PayloadBaseAddress = (EFI_PHYSICAL_ADDRESS)AllocatePages
> (EFI_SIZE_TO_PAGES (Context.PayloadSize));
>
> +
>
> +  RelocateTable = (FIT_RELOCATE_ITEM *)(UINTN)(Context.PayloadBaseAddress
> + Context.RelocateTableOffset);
>
> +  CopyMem ((VOID *)Context.PayloadBaseAddress, Binary,
> Context.PayloadSize);
>
> +
>
> +  if (Context.PayloadBaseAddress > Context.PayloadLoadAddress) {
>
> +    Delta                      = Context.PayloadBaseAddress -
> Context.PayloadLoadAddress;
>
> +    Context.PayloadEntryPoint += Delta;
>
> +    for (Index = 0; Index < Context.RelocateTableCount; Index++) {
>
> +      if ((RelocateTable[Index].RelocateType == 10) ||
> (RelocateTable[Index].RelocateType == 3)) {
>
> +        *((UINT64 *)(Context.PayloadBaseAddress +
> RelocateTable[Index].Offset)) = *((UINT64 *)(Context.PayloadBaseAddress +
> RelocateTable[Index].Offset)) + Delta;
>
> +      }
>
> +    }
>
> +  } else {
>
> +    Delta                      = Context.PayloadLoadAddress -
> Context.PayloadBaseAddress;
>
> +    Context.PayloadEntryPoint -= Delta;
>
> +    for (Index = 0; Index < Context.RelocateTableCount; Index++) {
>
> +      if ((RelocateTable[Index].RelocateType == 10) ||
> (RelocateTable[Index].RelocateType == 3)) {
>
> +        *((UINT64 *)(Context.PayloadBaseAddress +
> RelocateTable[Index].Offset)) = *((UINT64 *)(Context.PayloadBaseAddress +
> RelocateTable[Index].Offset)) - Delta;
>
> +      }
>
> +    }
>
> +  }
>
> +
>
> +  DEBUG ((
>
> +    DEBUG_INFO,
>
> +    "After Rebase Payload File Base: 0x%08x, File Size: 0x%08X,
> EntryPoint: 0x%08x\n",
>
> +    Context.PayloadBaseAddress,
>
> +    Context.PayloadSize,
>
> +    Context.PayloadEntryPoint
>
> +    ));
>
> +
>
> +  Length      = sizeof (UNIVERSAL_PAYLOAD_BASE);
>
> +  PayloadBase = BuildGuidHob (
>
> +                  &gUniversalPayloadBaseGuid,
>
> +                  Length
>
> +                  );
>
> +  PayloadBase->Entry = (EFI_PHYSICAL_ADDRESS)Context.ImageBase;
>
> +
>
> +  *ImageAddressArg = Context.PayloadBaseAddress;
>
> +  *ImageSizeArg    = Context.PayloadSize;
>
> +  *EntryPoint      = Context.PayloadEntryPoint;
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +EFI_PEI_LOAD_FILE_PPI  mPeiLoadFilePpi = {
>
> +  PeiLoadFileLoadPayload
>
> +};
>
> +
>
> +EFI_PEI_PPI_DESCRIPTOR  gPpiLoadFilePpiList = {
>
> +  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
>
> +  &gEfiPeiLoadFilePpiGuid,
>
> +  &mPeiLoadFilePpi
>
> +};
>
> +
>
> +/**
>
> +  Install Pei Load File PPI.
>
> +  @param  FileHandle  Handle of the file being invoked.
>
> +  @param  PeiServices Describes the list of possible PEI Services.
>
> +  @retval EFI_SUCESS  The entry point executes successfully.
>
> +  @retval Others      Some error occurs during the execution of this
> function.
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +InitializeFitPayloadLoaderPeim (
>
> +  IN       EFI_PEI_FILE_HANDLE  FileHandle,
>
> +  IN CONST EFI_PEI_SERVICES     **PeiServices
>
> +  )
>
> +{
>
> +  EFI_STATUS  Status;
>
> +
>
> +  Status = PeiServicesInstallPpi (&gPpiLoadFilePpiList);
>
> +
>
> +  return Status;
>
> +}
>
> diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
> b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
> new file mode 100644
> index 0000000000..acb0e09f68
> --- /dev/null
> +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
> @@ -0,0 +1,59 @@
> +## @file
>
> +#  Produce LoadFile PPI for payload loading.
>
> +#
>
> +#  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
>
> +#
>
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +#
>
> +##
>
> +
>
> +[Defines]
>
> +  INF_VERSION                    = 0x00010005
>
> +  BASE_NAME                      = FitPayloadLoaderPeim
>
> +  FILE_GUID                      = 55AC82C8-FC17-4C56-BCDA-990BB0A73E41
>
> +  MODULE_TYPE                    = PEIM
>
> +  VERSION_STRING                 = 1.0
>
> +
>
> +  ENTRY_POINT                    = InitializeFitPayloadLoaderPeim
>
> +
>
> +#
>
> +# The following information is for reference only and not required by the
> build tools.
>
> +#
>
> +#  VALID_ARCHITECTURES           = IA32 X64
>
> +#
>
> +
>
> +[Sources]
>
> +  FitPayloadLoaderPeim.c
>
> +  FitLib.h
>
> +  FitLib/FitLib.c
>
> +
>
> +[Packages]
>
> +  MdePkg/MdePkg.dec
>
> +  MdeModulePkg/MdeModulePkg.dec
>
> +  PcAtChipsetPkg/PcAtChipsetPkg.dec
>
> +  UefiPayloadPkg/UefiPayloadPkg.dec
>
> +
>
> +[LibraryClasses]
>
> +  PcdLib
>
> +  MemoryAllocationLib
>
> +  BaseMemoryLib
>
> +  PeiServicesLib
>
> +  HobLib
>
> +  BaseLib
>
> +  PeimEntryPoint
>
> +  DebugLib
>
> +  FdtLib
>
> +
>
> +[Ppis]
>
> +  gEfiPeiLoadFilePpiGuid                 ## PRODUCES
>
> +
>
> +[Pcd]
>
> +  gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister
>
> +  gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister
>
> +
>
> +[Guids]
>
> +  gUniversalPayloadExtraDataGuid         ## PRODUCES
>
> +  gUniversalPayloadBaseGuid              ## PRODUCES
>
> +
>
> +[Depex]
>
> +  TRUE
>
> diff --git a/UefiPayloadPkg/Readme.md b/UefiPayloadPkg/Readme.md
> new file mode 100644
> index 0000000000..616a5dd467
> --- /dev/null
> +++ b/UefiPayloadPkg/Readme.md
> @@ -0,0 +1,191 @@
> +# UefiPayloadPkg
>
> +Provide UEFI Universal Payload for different bootloader to generate EFI
> environment
>
> +
>
> +# Spec
>
> +
>
> +UniversalPayload URL:
> https://universalscalablefirmware.github.io/documentation/2_universal_payload.html
>
> +
>
> +ELF Format URL: https://refspecs.linuxfoundation.org/elf/elf.pdf
>
> +
>
> +FIT Format URL:
> https://universalpayload.github.io/spec/chapter2-payload-image-format.html
>
> +
>
> +# Uefi UniversalPayload Format
>
> +  | Binary Format | HandOffPayload - HOB |
>
> +  |---------------|----------------------|
>
> +  | ELF           | V (Default)          |
>
> +  | FIT           | V                    |
>
> +
>
> +# Binary Format
>
> +  - ELF
>
> +    ```
>
> +                  +  +-----------------------+
>
> +                  |  | UniversalPayloadEntry | <-----------
> UefiPayloadPkg\UefiPayloadEntry\UniversalPayloadEntry.c:_ModuleEntryPoint
> (HOB)
>
> +                  |  +-----------------------+
>
> +                  |  | .upld_info            | patch it directly
>
> +    ELF Format    |  +-----------------------+
>
> +                  |  | .upld.uefi_fv         | patch it directly
>
> +                  |  +-----------------------+
>
> +                  |  | .upld.bds_fv          | patch it directly
>
> +                  |  +-----------------------+
>
> +                  |  | .upld.<afpx>_fv       | patch it directly
>
> +                  +  +-----------------------+
>
> +    ```
>
> +
>
> +  - FIT
>
> +    ```
>
> +                  +  +-----------------------+
>
> +    FIT Data      |  | FIT Header            | <----------- Generate by
> pylibfdt
>
> +                  +  +-----------------------+
>
> +    PECOFF Format |  | UniversalPayloadEntry | <-----------
> UefiPayloadPkg\UefiPayloadEntry\FitUniversalPayloadEntry.c:_ModuleEntryPoint
> (HOB)
>
> +                  +  +-----------------------+
>
> +    Relocate Data |  | reloc-start           |
>
> +                  +  +-----------------------+
>
> +                  |  | uefi_fv               | patch it directly
>
> +                  |  +-----------------------+
>
> +    Multi Binary  |  | bds_fv                | patch it directly
>
> +                  |  +-----------------------+
>
> +                  |  | afp_xxx_fv            | patch it directly
>
> +                  |  +-----------------------+
>
> +                  |  | afp_xxx_fv            | patch it directly
>
> +                  +  +-----------------------+
>
> +    ```
>
> +
>
> +# Environment
>
> +  - ELF
>
> +    ```
>
> +    Download and install
> https://github.com/llvm/llvm-project/releases/tag/llvmorg-10.0.1
>
> +    ```
>
> +  - FIT
>
> +    - Windows
>
> +      ```powershell
>
> +      Set-ExecutionPolicy Bypass -Scope Process -Force;
> [System.Net.ServicePointManager]::SecurityProtocol =
> [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex
> ((New-Object System.Net.WebClient).DownloadString('
> https://chocolatey.org/install.ps1'))
>
> +      choco install dtc-msys2
>
> +      pip3 install pefile
>
> +      pip3 install swig
>
> +      pip3 install pylibfdt
>
> +      ```
>
> +    - Ubuntu
>
> +      ```bash
>
> +      sudo apt install -y u-boot-tools
>
> +      pip3 install pefile
>
> +      pip3 install swig
>
> +      pip3 install pylibfdt
>
> +      ```
>
> +# How to build UEFI UniversalPayload
>
> +  - Windows
>
> +    - edksetup Rebuild
>
> +  - Linux
>
> +    - make -C BaseTools
>
> +    - source edksetup.sh
>
> +
>
> +  - UniversalPayload.elf
>
> +    - python UefiPayloadPkg/UniversalPayloadBuild.py -t <TOOL_CHAIN_TAG>
>
> +    - llvm-objdump -h Build/UefiPayloadPkgX64/UniversalPayload.elf
>
> +
>
> +  - UniversalPayload.fit
>
> +    - python UefiPayloadPkg/UniversalPayloadBuild.py -t <TOOL_CHAIN_TAG>
> --Fit
>
> +    - fdtdump Build/UefiPayloadPkgX64/UniversalPayload.fit
>
> +
>
> +# Edk2boot + UefiUniversalPayload
>
> +ELF Edk2boot use below way to support compress and sign.
>
> +
>
> +- ELF Behavior - Edk2boot + UefiUniversalPayload.elf
>
> +  ```
>
> +  Boot Flow
>
> +
> +-------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+-------------------+
>
> +  | Platform Init
>                | Universal Loader Interface
>                                                 | OS                |
>
> +
> +-------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+-------------------+
>
> +
>
>                HOBs
>
> +  SEC -> PEI -> DXE -> DXE IPL ->
> UefiPayloadPkg\PayloadLoaderPeim\PayloadLoaderPeim.c
> ------------------------------------------------------------------------------------>
> Load UniversalPayload.elf -> Operation System
>
> +
>
> +
>
> +  | Platform Initialize - Edk2
>
>                                               | UniversalPayload - Edk2
>     |
>
> +
> +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
>
> +
>
> +  Binary Format
>
> +
>
> +  +-------------------+
>
> +  | BIOS.rom          |
>
> +  +-------------------+
>
> +  | Other Firmware    |
>
> +  +-------------------+
>
> +  | ...               |  FMMT
>
>                                                 UniversalPayloadBuild.py
>
> +  +-------------------+<----------------+-----------------------+
> GenFfs    +-----------------------+  Rsa2048Sha256 Sign
> +-----------------------+  LzmaCompress +----------------------+  GenSec
> +--------------------------------+
>
> +  |                   |                 | EDK2 FFS Header
>  |<-----------| Rsa2048Sha256 Hash    |<--------------------|
> UniversalPayload.lzma |<--------------| EDK2 SEC Header      |<--------|
> UniversalPayload.elf           |
>
> +  | RAW Data          |                 +-----------------------+
>     +-----------------------+
>  +-----------------------+               +----------------------+
>  +--------------------------------+
>
> +  |                   |                 | Rsa2048Sha256 Hash    |
>     | UniversalPayload.lzma |
>                | UniversalPayload.elf |         | upld_info
>       |
>
> +  |                   |                 +-----------------------+
>     +-----------------------+
>                +----------------------+
>  +--------------------------------+
>
> +  |                   |                 | UniversalPayload.lzma |
>
>               | upld_info            |         | upld.uefi_fv
>      |
>
> +  +-------------------+<----------------+-----------------------+
>
>               +----------------------+
>  +--------------------------------+
>
> +  | ...               |
>
>               | upld.uefi_fv         |         | upld.bds_fv
>     |
>
> +  +-------------------+
>
>               +----------------------+
>  +--------------------------------+
>
> +  | Other Firmware    |
>
>               | upld.bds_fv          |         | upld.AFP1
>     |
>
> +  +-------------------+
>
>               +----------------------+
>  +--------------------------------+
>
> +
>
>              | upld.AFP1            |         | upld.AFP2
>     |
>
> +
>
>              +----------------------+
>  +--------------------------------+
>
> +
>
>              | upld.AFP2            |         | ...
>     |
>
> +
>
>              +----------------------+
>  +--------------------------------+
>
> +
>
>              | ...                  |         | upld.AFPn
>     |
>
> +
>
>              +----------------------+
>  +--------------------------------+
>
> +
>
>              | upld.AFPn            |
>
> +
>
>              +----------------------+
>
> +  ```
>
> +
>
> +FIT Edk2boot use below way to support compress and sign
>
> +- FIT Behavior - Edk2boot + UefiUniversalPayload.fit
>
> +  ```
>
> +  Boot Flow
>
> +
> +-------------------------------------------------------------------------------------+------------------------------------------------------------------------+-------------------+
>
> +  | Platform Init
>                | Universal Loader Interface
>              | OS                |
>
> +
> +-------------------------------------------------------------------------------------+------------------------------------------------------------------------+-------------------+
>
> +
>                             HOBs
>
> +  SEC -> PEI -> DXE -> DXE IPL ->
> *UefiPayloadPkg\PayloadLoaderPeim\PayloadLoaderPeim.c
> ----------------------------------------------> Load UniversalPayload.fit
> -> Operation System
>
> +
>
> +  Binary Format
>
> +
>
> +  | Platform Initialize - Edk2
>                                                     | UniversalPayload -
> Edk2 (UniversalPayloadBuild.py --Fit)                                |
>
> +
> +---------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
>
> +
>
> +  +-------------------+
>
> +  | BIOS.rom          |
>
> +  +-------------------+
>
> +  | Other Firmware    |
>
> +  +-------------------+
>
> +  | ...               |  FMMT
>
> UniversalPayloadBuild.py --Fit    tianocore -> data-offset
>
> +
> +-------------------+<----------------+--------------------------------+
> GenFfs +--------------------------------+  GenSec
> +--------------------------------+ tianocore -> reloc-start
> +--------------------------+
>
> +  |                   |                 | EDK2 FFS Header
> |<--------| EDK2 SEC Header                |<--------| FIT Header
>            |<-------------------------| UniversalPayload.pecoff  |
>
> +  |                   |
>  +--------------------------------+
>  +--------------------------------+         | description = "Uefi
> Payload";  |                          +--------------------------+
>
> +  |                   |                 | EDK2 SEC Header
> |         | FIT Header                     |         | ...
>           |
>
> +  | RAW Data          |
>  +--------------------------------+         |
>   |         | images {                       | uefi-fv -> data-offset
>  +--------------------------+
>
> +  |                   |                 | FIT Header
>  |         |                                |         |   tianocore {...};
>            |<-------------------------| uefi_fv                  |
>
> +  |                   |                 |
> |         +--------------------------------+         |   uefi-fv {...};
>            | bds-fv -> data-offset    +--------------------------+
>
> +  |                   |                 |
> |         | tianocore -> data              |         |   bds-fv {...};
>           |<-------------------------| bds_fv                   |
>
> +  |                   |
>  +--------------------------------+
>  +--------------------------------+         |   afp1-fv {...};
>  | AFP1 -> data-offset      +--------------------------+
>
> +  |                   |                 | tianocore -> data
> |         | tianocore -> reloc-start       |         |   ...
>           |<-------------------------| AFP1                     |
>
> +  |                   |
>  +--------------------------------+
>  +--------------------------------+         |   afpn-fv {...};
>  | AFP2 -> data-offset      +--------------------------+
>
> +  |                   |                 | tianocore -> reloc-start
>  |         | uefi-fv -> data                |         | }
>             |<-------------------------| AFP2                     |
>
> +  |                   |
>  +--------------------------------+
>  +--------------------------------+         | configurations {
>  | ...                      +--------------------------+
>
> +  |                   |                 | uefi-fv -> data
> |         | bds-fv -> data                 |         |   conf-1 {...}
>            |<-------------------------| ...                      |
>
> +  |                   |
>  +--------------------------------+
>  +--------------------------------+         | }
>   | AFPn -> data-offset      +--------------------------+
>
> +  |                   |                 | bds-fv -> data
>  |         | AFP1-fv -> data                |         |
>             |<-------------------------| AFPn                     |
>
> +  |                   |
>  +--------------------------------+
>  +--------------------------------+         |
>   |                          +--------------------------+
>
> +  |                   |                 | AFP1-fv -> data
> |         | AFP2-fv -> data                |         |
>           |
>
> +  |                   |
>  +--------------------------------+
>  +--------------------------------+
>  +--------------------------------+
>
> +  |                   |                 | AFP2-fv -> data
> |         | ...                            |         | tianocore -> data
>           |
>
> +  |                   |
>  +--------------------------------+
>  +--------------------------------+
>  +--------------------------------+
>
> +  |                   |                 | ...
> |         | AFPn-fv -> data                |         | tianocore ->
> reloc-start       |
>
> +  |                   |
>  +--------------------------------+
>  +--------------------------------+
>  +--------------------------------+
>
> +  |                   |                 | AFPn-fv -> data
> |                                                    | uefi-fv -> data
>           |
>
> +
> +-------------------+<----------------+--------------------------------+
>
> +--------------------------------+
>
> +  | ...               |
>                                                      | bds-fv -> data
>            |
>
> +  +-------------------+
>
>  +--------------------------------+
>
> +  | Other Firmware    |
>                                                      | AFP1-fv -> data
>           |
>
> +  +-------------------+
>
>  +--------------------------------+
>
> +
>                                                     | AFP2-fv -> data
>           |
>
> +
>
> +--------------------------------+
>
> +
>                                                     | ...
>           |
>
> +
>
> +--------------------------------+
>
> +
>                                                     | AFPn-fv -> data
>           |
>
> +
>
> +--------------------------------+
>
> +
>
> +  ```
>
> diff --git a/UefiPayloadPkg/Tools/MkFitImage.py
> b/UefiPayloadPkg/Tools/MkFitImage.py
> new file mode 100644
> index 0000000000..82ab933d6d
> --- /dev/null
> +++ b/UefiPayloadPkg/Tools/MkFitImage.py
> @@ -0,0 +1,272 @@
> +## @file
>
> +# This file is a script to build fit image.
>
> +# It generate a dtb header and combine a binary file after this header.
>
> +#
>
> +# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +##
>
> +
>
> +from os.path import exists
>
> +import libfdt
>
> +from ctypes import *
>
> +import time
>
> +
>
> +class FIT_IMAGE_INFO_HEADER:
>
> +    """Class for user setting data to use MakeFitImage()
>
> +    """
>
> +    _pack_ = 1
>
> +    _fields_ = [
>
> +        ('Compatible',    str),
>
> +        ('UplVersion',    int),
>
> +        ('Description',   str),
>
> +        ('Type',          str),
>
> +        ('Arch',          str),
>
> +        ('Compression',   str),
>
> +        ('Revision',      int),
>
> +        ('BuildType',     str),
>
> +        ('Capabilities',  str),
>
> +        ('Producer',      str),
>
> +        ('ImageId',       str),
>
> +        ('DataOffset',    int),
>
> +        ('DataSize',      int),
>
> +        ('RelocStart',    int),
>
> +        ('LoadAddr',      int),
>
> +        ('Entry',         int),
>
> +        ('Binary',        str),
>
> +        ('TargetPath',    str),
>
> +        ('UefifvPath',    str),
>
> +        ('BdsfvPath',     str),
>
> +        ('NetworkfvPath', str),
>
> +        ('Project',       str),
>
> +        ]
>
> +
>
> +    def __init__(self):
>
> +        self.Compatible     = 'universal-payload'
>
> +        self.UplVersion     = 0x0100
>
> +        self.TargetPath     = 'mkimage.fit'
>
> +
>
> +def CreatFdt(Fdt):
>
> +    FdtEmptyTree = libfdt.fdt_create_empty_tree(Fdt, len(Fdt))
>
> +    if FdtEmptyTree != 0:
>
> +        print('\n- Failed - Create Fdt failed!')
>
> +        return False
>
> +    return True
>
> +
>
> +def BuildConfNode(Fdt, ParentNode, MultiImage):
>
> +    ConfNode1     = libfdt.fdt_add_subnode(Fdt, ParentNode, 'conf-1')
>
> +
>
> +    libfdt.fdt_setprop(Fdt, ConfNode1, 'require-fit', b'', 0)
>
> +    libfdt.fdt_setprop(Fdt, ConfNode1, 'firmware', bytes('tianocore',
> 'utf-8'), len('tianocore') + 1)
>
> +
>
> +def BuildFvImageNode(Fdt, InfoHeader, ParentNode, DataOffset, DataSize,
> Description):
>
> +    libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-size', DataSize)
>
> +    libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-offset', DataOffset)
>
> +    libfdt.fdt_setprop(Fdt, ParentNode, 'compression', bytes('none',
>           'utf-8'), len('none') + 1)
>
> +    libfdt.fdt_setprop(Fdt, ParentNode, 'project ',
> bytes('tianocore',           'utf-8'), len('tianocore') + 1)
>
> +    libfdt.fdt_setprop(Fdt, ParentNode, 'arch',        bytes('x86_64',
>           'utf-8'), len('x86_64') + 1)
>
> +    libfdt.fdt_setprop(Fdt, ParentNode, 'type',
> bytes('flat-binary',         'utf-8'), len('flat-binary') + 1)
>
> +    libfdt.fdt_setprop(Fdt, ParentNode, 'description',
> bytes(Description,           'utf-8'), len(Description) + 1)
>
> +
>
> +def BuildTianoImageNode(Fdt, InfoHeader, ParentNode, DataOffset,
> DataSize, Description):
>
> +    #
>
> +    # Set 'load' and 'data-offset' to reserve the memory first.
>
> +    # They would be set again when Fdt completes or this function parses
> target binary file.
>
> +    #
>
> +    if InfoHeader.LoadAddr is not None:
>
> +        libfdt.fdt_setprop_u64(Fdt, ParentNode, 'load',
> InfoHeader.LoadAddr)
>
> +    if InfoHeader.Entry is not None:
>
> +        libfdt.fdt_setprop_u64(Fdt, ParentNode, 'entry-start',
> InfoHeader.Entry)
>
> +    if InfoHeader.RelocStart is not None:
>
> +        libfdt.fdt_setprop_u32(Fdt, ParentNode, 'reloc-start',
> InfoHeader.RelocStart)
>
> +    if InfoHeader.DataSize is not None:
>
> +       libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-size', DataSize)
>
> +    if InfoHeader.DataOffset is not None:
>
> +        libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-offset', DataOffset)
>
> +    if InfoHeader.Producer is not None:
>
> +        libfdt.fdt_setprop(Fdt, ParentNode, 'producer ',
> bytes(InfoHeader.Producer, 'utf-8'), len(InfoHeader.Producer) + 1)
>
> +    if InfoHeader.Capabilities is not None:
>
> +        CapStrs = ','.join(InfoHeader.Capabilities)
>
> +        libfdt.fdt_setprop(Fdt, ParentNode, 'capabilities ',
> bytes(CapStrs, 'utf-8'), len(CapStrs) + 1)
>
> +    if InfoHeader.Type is not None:
>
> +        libfdt.fdt_setprop(Fdt, ParentNode, 'type ',
> bytes(InfoHeader.Type, 'utf-8'), len(InfoHeader.Type) + 1)
>
> +    if InfoHeader.Arch is not None:
>
> +        libfdt.fdt_setprop(Fdt, ParentNode, 'arch ',
> bytes(InfoHeader.Arch, 'utf-8'), len(InfoHeader.Arch) + 1)
>
> +    if InfoHeader.Project is not None:
>
> +        libfdt.fdt_setprop(Fdt, ParentNode, 'project ',
> bytes(InfoHeader.Project, 'utf-8'), len(InfoHeader.Project) + 1)
>
> +    if InfoHeader.Description is not None:
>
> +        libfdt.fdt_setprop(Fdt, ParentNode, 'description',
> bytes(Description, 'utf-8'), len(Description) + 1)
>
> +
>
> +#
>
> +# The subnode would be inserted from bottom to top of structure block.
>
> +#
>
> +def BuildFitImage(Fdt, InfoHeader):
>
> +    MultiImage = [
>
> +        ["tianocore",   InfoHeader.Binary,        BuildTianoImageNode ,
> InfoHeader.Description,     None, 0 ],
>
> +        ["uefi-fv",     InfoHeader.UefifvPath,    BuildFvImageNode,
>  "UEFI Firmware Volume",     None, 0 ],
>
> +        ["bds-fv",      InfoHeader.BdsfvPath,     BuildFvImageNode ,
> "BDS Firmware Volume",      None, 0 ],
>
> +        ["network-fv",  InfoHeader.NetworkfvPath, BuildFvImageNode ,
> "Network Firmware Volume",  None, 0 ],
>
> +    ]
>
> +
>
> +    #
>
> +    # Set basic information
>
> +    #
>
> +    libfdt.fdt_setprop_u32(Fdt, 0, 'build-revision ', InfoHeader.Revision)
>
> +    libfdt.fdt_setprop_u32(Fdt, 0, 'spec-version', InfoHeader.UplVersion)
>
> +
>
> +    #
>
> +    # Build configurations node
>
> +    #
>
> +    ConfNode  = libfdt.fdt_add_subnode(Fdt, 0, 'configurations')
>
> +    BuildConfNode(Fdt, ConfNode, MultiImage)
>
> +
>
> +    # Build image
>
> +    DataOffset = InfoHeader.DataOffset
>
> +    for Index in range (0, len (MultiImage)):
>
> +        _, Path, _, _, _, _ = MultiImage[Index]
>
> +        if exists(Path) == 1:
>
> +            TempBinary = open(Path, 'rb')
>
> +            BinaryData = TempBinary.read()
>
> +            TempBinary.close()
>
> +            MultiImage[Index][-2] = BinaryData
>
> +            MultiImage[Index][-1] = DataOffset
>
> +            DataOffset += len (BinaryData)
>
> +    libfdt.fdt_setprop_u32(Fdt, 0, 'size', DataOffset)
>
> +    posix_time = int(time.time())
>
> +    libfdt.fdt_setprop_u32(Fdt, 0, 'timestamp', posix_time)
>
> +    DescriptionFit = 'Uefi OS Loader'
>
> +    libfdt.fdt_setprop(Fdt, 0, 'description', bytes(DescriptionFit,
> 'utf-8'), len(DescriptionFit) + 1)
>
> +
>
> +    ImageNode = libfdt.fdt_add_subnode(Fdt, 0, 'images')
>
> +    for Item in reversed (MultiImage):
>
> +        Name, Path, BuildFvNode, Description, BinaryData, DataOffset =
> Item
>
> +        FvNode = libfdt.fdt_add_subnode(Fdt, ImageNode, Name)
>
> +        BuildFvNode (Fdt, InfoHeader, FvNode, DataOffset,
> len(BinaryData), Description)
>
> +
>
> +    #
>
> +    # Create new image file and combine all binary.
>
> +    #
>
> +    DtbFile = open(InfoHeader.TargetPath, "wb")
>
> +    DtbFile.truncate()
>
> +    DtbFile.write(Fdt)
>
> +    for Item in MultiImage:
>
> +        _, _, _, _, BinaryData, _ = Item
>
> +        DtbFile.write(BinaryData)
>
> +    DtbFile.close()
>
> +
>
> +    return True
>
> +
>
> +def MakeFitImage(InfoHeader):
>
> +    #
>
> +    # Allocate fdt byte array.
>
> +    #
>
> +    Fdt = bytearray(InfoHeader.DataOffset)
>
> +
>
> +    #
>
> +    # Create fdt empty tree.
>
> +    #
>
> +    if CreatFdt(Fdt) is False:
>
> +        return False
>
> +
>
> +    #
>
> +    # Parse args to build fit image.
>
> +    #
>
> +    return BuildFitImage(Fdt, InfoHeader)
>
> +
>
> +def ReplaceFv (UplBinary, SectionFvFile, SectionName):
>
> +    try:
>
> +        #
>
> +        # Get Original Multi Fv
>
> +        #
>
> +        with open (UplBinary, "rb") as File:
>
> +            Dtb = File.read ()
>
> +        Fit          = libfdt.Fdt (Dtb)
>
> +        NewFitHeader = bytearray(Dtb[0:Fit.totalsize()])
>
> +        FitSize      = len(Dtb)
>
> +
>
> +        LoadablesList = []
>
> +        ImagesNode    = libfdt.fdt_subnode_offset(NewFitHeader, 0,
> 'images')
>
> +        FvNode        = libfdt.fdt_subnode_offset(NewFitHeader,
> ImagesNode, 'uefi-fv')
>
> +        NodeDepth     = libfdt.fdt_node_depth (NewFitHeader, ImagesNode)
>
> +        node_name     = libfdt.fdt_get_name(NewFitHeader, FvNode)
>
> +        FvNode        = libfdt.fdt_next_node(NewFitHeader, FvNode,
> NodeDepth)
>
> +
>
> +        while node_name[0][-2:] == 'fv':
>
> +            LoadablesList.append (node_name[0])
>
> +            node_name = libfdt.fdt_get_name(NewFitHeader, FvNode[0])
>
> +            FvNode = libfdt.fdt_next_node(NewFitHeader, FvNode[0],
> NodeDepth)
>
> +        #
>
> +        # Get current Fit Binary FV data
>
> +        #
>
> +        MultiFvList = []
>
> +        for Item in LoadablesList:
>
> +            ImageNode    = libfdt.fdt_subnode_offset(NewFitHeader,
> ImagesNode, Item)
>
> +            ImageOffset  = int.from_bytes (libfdt.fdt_getprop
> (NewFitHeader, ImageNode, 'data-offset')[0], 'big')
>
> +            ImageSize    = int.from_bytes (libfdt.fdt_getprop
> (NewFitHeader, ImageNode, 'data-size')[0], 'big')
>
> +            MultiFvList.append ([Item, Dtb[ImageOffset:ImageOffset +
> ImageSize]])
>
> +
>
> +        IsFvExist = False
>
> +        for Index in range (0, len (MultiFvList)):
>
> +            if MultiFvList[Index][0] == SectionName:
>
> +                with open (SectionFvFile, 'rb') as File:
>
> +                    MultiFvList[Index][1] = File.read ()
>
> +                ImageNode     = libfdt.fdt_subnode_offset(NewFitHeader,
> ImagesNode, SectionName)
>
> +                ImageSize     = int.from_bytes (libfdt.fdt_getprop
> (NewFitHeader, ImageNode, 'data-size')[0], 'big')
>
> +                ReplaceOffset = int.from_bytes (libfdt.fdt_getprop
> (NewFitHeader, ImageNode, 'data-offset')[0], 'big')
>
> +                OffsetDelta   = len(MultiFvList[Index][1]) - ImageSize
>
> +                FitSize      += OffsetDelta
>
> +                IsFvExist     = True
>
> +                libfdt.fdt_setprop_u32(NewFitHeader, ImageNode,
> 'data-size', len(MultiFvList[Index][1]))
>
> +
>
> +        #
>
> +        # Update new fit header
>
> +        #
>
> +        ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'images')
>
> +        if (IsFvExist == False):
>
> +            with open (SectionFvFile, 'rb') as File:
>
> +                SectionFvFileBinary = File.read ()
>
> +            MultiFvList.append ([SectionName, SectionFvFileBinary])
>
> +            FvNode = libfdt.fdt_add_subnode(NewFitHeader, ImagesNode,
> SectionName)
>
> +            BuildFvImageNode (NewFitHeader, None, FvNode, FitSize,
> len(SectionFvFileBinary), SectionName + " Firmware Volume")
>
> +            FitSize += len(SectionFvFileBinary)
>
> +        else:
>
> +            for Index in range (0, len (MultiFvList)):
>
> +                ImageNode    = libfdt.fdt_subnode_offset(NewFitHeader,
> ImagesNode, MultiFvList[Index][0])
>
> +                ImageOffset  = int.from_bytes (libfdt.fdt_getprop
> (NewFitHeader, ImageNode, 'data-offset')[0], 'big')
>
> +                if ImageOffset > ReplaceOffset:
>
> +                    libfdt.fdt_setprop_u32(NewFitHeader, ImageNode,
> 'data-offset', ImageOffset + OffsetDelta)
>
> +
>
> +        ConfNodes     = libfdt.fdt_subnode_offset(NewFitHeader, 0,
> 'configurations')
>
> +        libfdt.fdt_setprop(NewFitHeader, ConfNodes, 'default ',
> bytes('conf-1', 'utf-8'), len('conf-1') + 1)
>
> +        ConfNode      = libfdt.fdt_subnode_offset(NewFitHeader,
> ConfNodes, 'conf-1')
>
> +
>
> +        libfdt.fdt_setprop_u32(NewFitHeader, 0, 'size', FitSize)
>
> +
>
> +        #
>
> +        # Generate new fit image
>
> +        #
>
> +        ImagesNode    = libfdt.fdt_subnode_offset(NewFitHeader, 0,
> 'images')
>
> +        TianoNode     = libfdt.fdt_subnode_offset(NewFitHeader,
> ImagesNode, 'tianocore')
>
> +        TianoOffset   = int.from_bytes (libfdt.fdt_getprop (NewFitHeader,
> TianoNode, 'data-offset')[0], 'big')
>
> +        TianoSize     = int.from_bytes (libfdt.fdt_getprop (NewFitHeader,
> TianoNode, 'data-size')[0], 'big')
>
> +        TianoBinary   = Dtb[TianoOffset:TianoOffset + TianoSize]
>
> +
>
> +        print("\nGenerate new fit image:")
>
> +        NewUplBinary = bytearray(FitSize)
>
> +        print("Update fit header\t to 0x0\t\t ~ " +
> str(hex(len(NewFitHeader))))
>
> +        NewUplBinary[:len(NewFitHeader)] = NewFitHeader
>
> +        print("Update tiano image\t to " + str(hex(len(NewFitHeader))) +
> "\t ~ " + str(hex(len(NewFitHeader) + len(TianoBinary))))
>
> +        NewUplBinary[len(NewFitHeader):len(NewFitHeader) +
> len(TianoBinary)] = TianoBinary
>
> +        for Index in range (0, len (MultiFvList)):
>
> +            ImageNode   = libfdt.fdt_subnode_offset(NewFitHeader,
> ImagesNode, MultiFvList[Index][0])
>
> +            ImageOffset = int.from_bytes (libfdt.fdt_getprop
> (NewFitHeader, ImageNode, 'data-offset')[0], 'big')
>
> +            ImageSize   = int.from_bytes (libfdt.fdt_getprop
> (NewFitHeader, ImageNode, 'data-size')[0], 'big')
>
> +            NewUplBinary[ImageOffset:ImageOffset + ImageSize] =
> MultiFvList[Index][1]
>
> +            print("Update " + MultiFvList[Index][0] + "\t\t to " +
> str(hex(ImageOffset)) + "\t ~ " + str(hex(ImageOffset + ImageSize)))
>
> +
>
> +        with open (UplBinary, "wb") as File:
>
> +            File.write (NewUplBinary)
>
> +
>
> +        return 0
>
> +    except Exception as Ex:
>
> +        print(Ex)
>
> +        return 1
>
> diff --git a/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
> b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
> new file mode 100644
> index 0000000000..a53d988627
> --- /dev/null
> +++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
> @@ -0,0 +1,654 @@
> +/** @file
>
> +  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +**/
>
> +
>
> +#include "UefiPayloadEntry.h"
>
> +#include <Library/FdtLib.h>
>
> +#include <Guid/UniversalPayloadBase.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;
>
> +
>
> +CHAR8  *mLineBuffer = NULL;
>
> +
>
> +/**
>
> +  Print all HOBs info from the HOB list.
>
> +  @return The pointer to the HOB list.
>
> +**/
>
> +VOID
>
> +PrintHob (
>
> +  IN CONST VOID  *HobStart
>
> +  );
>
> +
>
> +/**
>
> +  Find the first substring.
>
> +  @param  String    Point to the string where to find the substring.
>
> +  @param  CharSet   Point to the string to be found.
>
> +**/
>
> +UINTN
>
> +EFIAPI
>
> +AsciiStrSpn (
>
> +  IN CHAR8  *String,
>
> +  IN CHAR8  *CharSet
>
> +  )
>
> +{
>
> +  UINTN  Count;
>
> +  CHAR8  *Str1;
>
> +  CHAR8  *Str2;
>
> +
>
> +  Count = 0;
>
> +
>
> +  for (Str1 = String; *Str1 != L'\0'; Str1++) {
>
> +    for (Str2 = CharSet; *Str2 != L'\0'; Str2++) {
>
> +      if (*Str1 == *Str2) {
>
> +        break;
>
> +      }
>
> +    }
>
> +
>
> +    if (*Str2 == L'\0') {
>
> +      return Count;
>
> +    }
>
> +
>
> +    Count++;
>
> +  }
>
> +
>
> +  return Count;
>
> +}
>
> +
>
> +/**
>
> +  Searches a string for the first occurrence of a character contained in a
>
> +  specified buffer.
>
> +  @param  String    Point to the string where to find the substring.
>
> +  @param  CharSet   Point to the string to be found.
>
> +**/
>
> +CHAR8 *
>
> +EFIAPI
>
> +AsciiStrBrk (
>
> +  IN CHAR8  *String,
>
> +  IN CHAR8  *CharSet
>
> +  )
>
> +{
>
> +  CHAR8  *Str1;
>
> +  CHAR8  *Str2;
>
> +
>
> +  for (Str1 = String; *Str1 != L'\0'; Str1++) {
>
> +    for (Str2 = CharSet; *Str2 != L'\0'; Str2++) {
>
> +      if (*Str1 == *Str2) {
>
> +        return (CHAR8 *)Str1;
>
> +      }
>
> +    }
>
> +  }
>
> +
>
> +  return NULL;
>
> +}
>
> +
>
> +/**
>
> +  Find the next token after one or more specified characters.
>
> +  @param  String    Point to the string where to find the substring.
>
> +  @param  CharSet   Point to the string to be found.
>
> +**/
>
> +CHAR8 *
>
> +EFIAPI
>
> +AsciiStrTokenLine (
>
> +  IN CHAR8  *String OPTIONAL,
>
> +  IN CHAR8  *CharSet
>
> +  )
>
> +{
>
> +  CHAR8  *Begin;
>
> +  CHAR8  *End;
>
> +
>
> +  Begin = (String == NULL) ? mLineBuffer : String;
>
> +  if (Begin == NULL) {
>
> +    return NULL;
>
> +  }
>
> +
>
> +  Begin += AsciiStrSpn (Begin, CharSet);
>
> +  if (*Begin == L'\0') {
>
> +    mLineBuffer = NULL;
>
> +    return NULL;
>
> +  }
>
> +
>
> +  End = AsciiStrBrk (Begin, CharSet);
>
> +  if ((End != NULL) && (*End != L'\0')) {
>
> +    *End = L'\0';
>
> +    End++;
>
> +  }
>
> +
>
> +  mLineBuffer = End;
>
> +  return Begin;
>
> +}
>
> +
>
> +/**
>
> +  Some bootloader may pass a pcd database, and UPL also contain a PCD
> database.
>
> +  Dxe PCD driver has the assumption that the two PCD database can be
> catenated and
>
> +  the local token number should be successive.
>
> +  This function will fix up the UPL PCD database to meet that assumption.
>
> +  @param[in]   DxeFv         The FV where to find the Universal PCD
> database.
>
> +  @retval EFI_SUCCESS        If it completed successfully.
>
> +  @retval other              Failed to fix up.
>
> +**/
>
> +EFI_STATUS
>
> +FixUpPcdDatabase (
>
> +  IN  EFI_FIRMWARE_VOLUME_HEADER  *DxeFv
>
> +  )
>
> +{
>
> +  EFI_STATUS           Status;
>
> +  EFI_FFS_FILE_HEADER  *FileHeader;
>
> +  VOID                 *PcdRawData;
>
> +  PEI_PCD_DATABASE     *PeiDatabase;
>
> +  PEI_PCD_DATABASE     *UplDatabase;
>
> +  EFI_HOB_GUID_TYPE    *GuidHob;
>
> +  DYNAMICEX_MAPPING    *ExMapTable;
>
> +  UINTN                Index;
>
> +
>
> +  GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);
>
> +  if (GuidHob == NULL) {
>
> +    //
>
> +    // No fix-up is needed.
>
> +    //
>
> +    return EFI_SUCCESS;
>
> +  }
>
> +
>
> +  PeiDatabase = (PEI_PCD_DATABASE *)GET_GUID_HOB_DATA (GuidHob);
>
> +  DEBUG ((DEBUG_INFO, "Find the Pei PCD data base, the total local token
> number is %d\n", PeiDatabase->LocalTokenCount));
>
> +
>
> +  Status = FvFindFileByTypeGuid (DxeFv, EFI_FV_FILETYPE_DRIVER, PcdGetPtr
> (PcdPcdDriverFile), &FileHeader);
>
> +  ASSERT_EFI_ERROR (Status);
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = FileFindSection (FileHeader, EFI_SECTION_RAW, &PcdRawData);
>
> +  ASSERT_EFI_ERROR (Status);
>
> +  if (EFI_ERROR (Status)) {
>
> +    return Status;
>
> +  }
>
> +
>
> +  UplDatabase = (PEI_PCD_DATABASE *)PcdRawData;
>
> +  ExMapTable  = (DYNAMICEX_MAPPING *)(UINTN)((UINTN)PcdRawData +
> UplDatabase->ExMapTableOffset);
>
> +
>
> +  for (Index = 0; Index < UplDatabase->ExTokenCount; Index++) {
>
> +    ExMapTable[Index].TokenNumber += PeiDatabase->LocalTokenCount;
>
> +  }
>
> +
>
> +  DEBUG ((DEBUG_INFO, "Fix up UPL PCD database successfully\n"));
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  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 Fv HOBs based on information from bootloaders.
>
> +  @param[out] DxeFv          The pointer to the DXE FV in memory.
>
> +  @retval EFI_SUCCESS        If it completed successfully.
>
> +  @retval EFI_NOT_FOUND      If it failed to find node in fit image.
>
> +  @retval Others             If it failed to build required HOBs.
>
> +**/
>
> +EFI_STATUS
>
> +BuildFitLoadablesFvHob (
>
> +  OUT EFI_FIRMWARE_VOLUME_HEADER  **DxeFv
>
> +  )
>
> +{
>
> +  EFI_STATUS              Status;
>
> +  VOID                    *Fdt;
>
> +  UINT8                   *GuidHob;
>
> +  UNIVERSAL_PAYLOAD_BASE  *PayloadBase;
>
> +  INT32                   ConfigNode;
>
> +  INT32                   Config1Node;
>
> +  INT32                   ImageNode;
>
> +  INT32                   FvNode;
>
> +  INT32                   Depth;
>
> +  CONST FDT_PROPERTY      *PropertyPtr;
>
> +  INT32                   TempLen;
>
> +  CONST CHAR8             *Fvname;
>
> +  UINT32                  DataOffset;
>
> +  UINT32                  DataSize;
>
> +  UINT32                  *Data32;
>
> +
>
> +  GuidHob = GetFirstGuidHob (&gUniversalPayloadBaseGuid);
>
> +  if (GuidHob != NULL) {
>
> +    PayloadBase = (UNIVERSAL_PAYLOAD_BASE *)GET_GUID_HOB_DATA (GuidHob);
>
> +    Fdt         = (VOID *)(UINTN)PayloadBase->Entry;
>
> +    DEBUG ((DEBUG_INFO, "PayloadBase Entry = 0x%08x\n",
> PayloadBase->Entry));
>
> +  }
>
> +
>
> +  Status = FdtCheckHeader (Fdt);
>
> +  if (EFI_ERROR (Status)) {
>
> +    return EFI_UNSUPPORTED;
>
> +  }
>
> +
>
> +  ConfigNode = FdtSubnodeOffsetNameLen (Fdt, 0, "configurations",
> (INT32)AsciiStrLen ("configurations"));
>
> +  if (ConfigNode <= 0) {
>
> +    return EFI_NOT_FOUND;
>
> +  }
>
> +
>
> +  Config1Node = FdtSubnodeOffsetNameLen (Fdt, ConfigNode, "conf-1",
> (INT32)AsciiStrLen ("conf-1"));
>
> +  if (Config1Node <= 0) {
>
> +    return EFI_NOT_FOUND;
>
> +  }
>
> +
>
> +  ImageNode = FdtSubnodeOffsetNameLen (Fdt, 0, "images",
> (INT32)AsciiStrLen ("images"));
>
> +  if (ImageNode <= 0) {
>
> +    return EFI_NOT_FOUND;
>
> +  }
>
> +
>
> +  FvNode = FdtSubnodeOffsetNameLen (Fdt, ImageNode, "tianocore",
> (INT32)AsciiStrLen ("tianocore"));
>
> +  Depth  = FdtNodeDepth (Fdt, FvNode);
>
> +  FvNode = FdtNextNode (Fdt, FvNode, &Depth);
>
> +  Fvname = FdtGetName (Fdt, FvNode, &TempLen);
>
> +  while ((AsciiStrCmp ((Fvname + AsciiStrLen (Fvname) - 2), "fv") == 0)) {
>
> +    if (FvNode <= 0) {
>
> +      return EFI_NOT_FOUND;
>
> +    }
>
> +
>
> +    PropertyPtr = FdtGetProperty (Fdt, FvNode, "data-offset", &TempLen);
>
> +    Data32      = (UINT32 *)(PropertyPtr->Data);
>
> +    DataOffset  = SwapBytes32 (*Data32);
>
> +
>
> +    PropertyPtr = FdtGetProperty (Fdt, FvNode, "data-size", &TempLen);
>
> +    Data32      = (UINT32 *)(PropertyPtr->Data);
>
> +    DataSize    = SwapBytes32 (*Data32);
>
> +
>
> +    if (AsciiStrCmp (Fvname, "uefi-fv") == 0) {
>
> +      *DxeFv = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)PayloadBase->Entry +
> (UINTN)DataOffset);
>
> +      ASSERT ((*DxeFv)->FvLength == DataSize);
>
> +    } else {
>
> +      BuildFvHob (((UINTN)PayloadBase->Entry + (UINTN)DataOffset),
> DataSize);
>
> +    }
>
> +
>
> +    DEBUG ((
>
> +      DEBUG_INFO,
>
> +      "UPL Multiple fv[%a], Base=0x%08x, size=0x%08x\n",
>
> +      Fvname,
>
> +      ((UINTN)PayloadBase->Entry + (UINTN)DataOffset),
>
> +      DataSize,
>
> +      DataOffset
>
> +      ));
>
> +    Depth  = FdtNodeDepth (Fdt, FvNode);
>
> +    FvNode = FdtNextNode (Fdt, FvNode, &Depth);
>
> +    Fvname = FdtGetName (Fdt, FvNode, &TempLen);
>
> +  }
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  It will build HOBs based on information from bootloaders.
>
> +  @param[in]  BootloaderParameter   The starting memory address of
> bootloader parameter block.
>
> +  @param[out] DxeFv                 The pointer to the DXE FV in memory.
>
> +  @retval EFI_SUCCESS        If it completed successfully.
>
> +  @retval Others             If it failed to build required HOBs.
>
> +**/
>
> +EFI_STATUS
>
> +BuildHobs (
>
> +  IN  UINTN                       BootloaderParameter,
>
> +  OUT EFI_FIRMWARE_VOLUME_HEADER  **DxeFv
>
> +  )
>
> +{
>
> +  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;
>
> +  UINT8                         *GuidHob;
>
> +  EFI_HOB_FIRMWARE_VOLUME       *FvHob;
>
> +  UNIVERSAL_PAYLOAD_ACPI_TABLE  *AcpiTable;
>
> +  ACPI_BOARD_INFO               *AcpiBoardInfo;
>
> +  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.
>
> +  //
>
> +  while (!END_OF_HOB_LIST (Hob)) {
>
> +    if (IsHobNeed (Hob)) {
>
> +      // Add this hob to payload HOB
>
> +      AddNewHob (&Hob);
>
> +    }
>
> +
>
> +    Hob.Raw = GET_NEXT_HOB (Hob);
>
> +  }
>
> +
>
> +  BuildFitLoadablesFvHob (DxeFv);
>
> +
>
> +  //
>
> +  // Create guid hob for acpi board information
>
> +  //
>
> +  GuidHob = GetFirstGuidHob (&gUniversalPayloadAcpiTableGuid);
>
> +  if (GuidHob != NULL) {
>
> +    AcpiTable = (UNIVERSAL_PAYLOAD_ACPI_TABLE *)GET_GUID_HOB_DATA
> (GuidHob);
>
> +    GuidHob   = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid);
>
> +    if (GuidHob == NULL) {
>
> +      AcpiBoardInfo = BuildHobFromAcpi ((UINT64)AcpiTable->Rsdp);
>
> +      ASSERT (AcpiBoardInfo != NULL);
>
> +    }
>
> +  }
>
> +
>
> +  //
>
> +  // Update DXE FV information to first fv hob in the hob list, which
>
> +  // is the empty FvHob created before.
>
> +  //
>
> +  FvHob              = GetFirstHob (EFI_HOB_TYPE_FV);
>
> +  FvHob->BaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)*DxeFv;
>
> +  FvHob->Length      = (*DxeFv)->FvLength;
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Entry point to the C language phase of UEFI payload.
>
> +  @param[in]   BootloaderParameter    The starting address of bootloader
> parameter block.
>
> +  @retval      It will not return if SUCCESS, and return error when
> passing bootloader parameter.
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +_ModuleEntryPoint (
>
> +  IN UINTN  BootloaderParameter
>
> +  )
>
> +{
>
> +  EFI_STATUS                  Status;
>
> +  PHYSICAL_ADDRESS            DxeCoreEntryPoint;
>
> +  EFI_PEI_HOB_POINTERS        Hob;
>
> +  EFI_FIRMWARE_VOLUME_HEADER  *DxeFv;
>
> +
>
> +  mHobList = (VOID *)BootloaderParameter;
>
> +  DxeFv    = NULL;
>
> +  // Call constructor for all libraries
>
> +  ProcessLibraryConstructorList ();
>
> +
>
> +  DEBUG ((DEBUG_INFO, "Entering Universal Payload...\n"));
>
> +  DEBUG ((DEBUG_INFO, "sizeof(UINTN) = 0x%x\n", sizeof (UINTN)));
>
> +
>
> +  DEBUG_CODE (
>
> +    //
>
> +    // Dump the Hobs from boot loader
>
> +    //
>
> +    PrintHob (mHobList);
>
> +    );
>
> +
>
> +  // Initialize floating point operating environment to be compliant with
> UEFI spec.
>
> +  InitializeFloatingPointUnits ();
>
> +
>
> +  // Build HOB based on information from Bootloader
>
> +  Status = BuildHobs (BootloaderParameter, &DxeFv);
>
> +  ASSERT_EFI_ERROR (Status);
>
> +
>
> +  FixUpPcdDatabase (DxeFv);
>
> +  Status = UniversalLoadDxeCore (DxeFv, &DxeCoreEntryPoint);
>
> +  ASSERT_EFI_ERROR (Status);
>
> +
>
> +  //
>
> +  // Mask off all legacy 8259 interrupt sources
>
> +  //
>
> +  IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF);
>
> +  IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF);
>
> +
>
> +  Hob.HandoffInformationTable = (EFI_HOB_HANDOFF_INFO_TABLE *)GetFirstHob
> (EFI_HOB_TYPE_HANDOFF);
>
> +  HandOffToDxeCore (DxeCoreEntryPoint, Hob);
>
> +
>
> +  // Should not get here
>
> +  CpuDeadLoop ();
>
> +  return EFI_SUCCESS;
>
> +}
>
> diff --git a/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
> b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
> new file mode 100644
> index 0000000000..a7d1a8c9e5
> --- /dev/null
> +++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
> @@ -0,0 +1,98 @@
> +## @file
>
> +#  This is the first module for UEFI payload.
>
> +#
>
> +#  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
>
> +#
>
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +#
>
> +##
>
> +
>
> +[Defines]
>
> +  INF_VERSION                    = 0x00010005
>
> +  BASE_NAME                      = FitUniversalPayloadEntry
>
> +  FILE_GUID                      = CED5A8A9-B6EA-4D5A-8689-577EE88566CF
>
> +  MODULE_TYPE                    = SEC
>
> +  VERSION_STRING                 = 1.0
>
> +
>
> +#
>
> +# The following information is for reference only and not required by the
> build tools.
>
> +#
>
> +#  VALID_ARCHITECTURES           = IA32 X64
>
> +#
>
> +
>
> +[Sources]
>
> +  FitUniversalPayloadEntry.c
>
> +  LoadDxeCore.c
>
> +  MemoryAllocation.c
>
> +  PrintHob.c
>
> +  AcpiTable.c
>
> +
>
> +[Sources.Ia32]
>
> +  X64/VirtualMemory.h
>
> +  X64/VirtualMemory.c
>
> +  Ia32/DxeLoadFunc.c
>
> +  Ia32/IdtVectorAsm.nasm
>
> +
>
> +[Sources.X64]
>
> +  X64/VirtualMemory.h
>
> +  X64/VirtualMemory.c
>
> +  X64/DxeLoadFunc.c
>
> +
>
> +[Packages]
>
> +  MdePkg/MdePkg.dec
>
> +  MdeModulePkg/MdeModulePkg.dec
>
> +  UefiCpuPkg/UefiCpuPkg.dec
>
> +  UefiPayloadPkg/UefiPayloadPkg.dec
>
> +
>
> +[LibraryClasses]
>
> +  BaseMemoryLib
>
> +  DebugLib
>
> +  BaseLib
>
> +  SerialPortLib
>
> +  IoLib
>
> +  HobLib
>
> +  PeCoffLib
>
> +  CpuLib
>
> +  FdtLib
>
> +
>
> +[Guids]
>
> +  gEfiMemoryTypeInformationGuid
>
> +  gEfiFirmwareFileSystem2Guid
>
> +  gEfiGraphicsInfoHobGuid
>
> +  gEfiGraphicsDeviceInfoHobGuid
>
> +  gUefiAcpiBoardInfoGuid
>
> +  gEfiSmbiosTableGuid
>
> +  gUefiSerialPortInfoGuid
>
> +  gUniversalPayloadExtraDataGuid
>
> +  gUniversalPayloadBaseGuid
>
> +  gPcdDataBaseHobGuid
>
> +  gUniversalPayloadSmbiosTableGuid
>
> +  gEfiHobMemoryAllocBspStoreGuid
>
> +  gUniversalPayloadAcpiTableGuid
>
> +  gUniversalPayloadPciRootBridgeInfoGuid
>
> +  gUniversalPayloadSmbios3TableGuid
>
> +
>
> +[FeaturePcd.IA32]
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode      ##
> CONSUMES
>
> +
>
> +[FeaturePcd.X64]
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables       ##
> CONSUMES
>
> +
>
> +
>
> +[Pcd.IA32,Pcd.X64]
>
> +  gUefiPayloadPkgTokenSpaceGuid.PcdPcdDriverFile
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable
> ## SOMETIMES_CONSUMES
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask
> ## CONSUMES
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
> ## CONSUMES
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask
>  ## CONSUMES
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard
>  ## CONSUMES
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase
> ## CONSUMES
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize
> ## CONSUMES
>
> +
>
> +  gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase
>
> +  gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize
>
> +  gUefiPayloadPkgTokenSpaceGuid.PcdSystemMemoryUefiRegionSize
>
> +
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack               ##
> SOMETIMES_CONSUMES
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy ##
> SOMETIMES_CONSUMES
>
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy       ##
> SOMETIMES_CONSUMES
>
> diff --git a/UefiPayloadPkg/UefiPayloadPkg.dec
> b/UefiPayloadPkg/UefiPayloadPkg.dec
> index e2e4a79db3..2f1fd82487 100644
> --- a/UefiPayloadPkg/UefiPayloadPkg.dec
> +++ b/UefiPayloadPkg/UefiPayloadPkg.dec
> @@ -24,6 +24,9 @@
>    #
>
>    gUefiPayloadPkgTokenSpaceGuid  = {0x1d127ea, 0xf6f1, 0x4ef6, {0x94,
> 0x15, 0x8a, 0x0, 0x0, 0x93, 0xf8, 0x9d}}
>
>
>
> +  ## Include/Guid/UniversalPayloadBase.h
>
> +  gUniversalPayloadBaseGuid = { 0x03d4c61d, 0x2713, 0x4ec5, {0xa1, 0xcc,
> 0x88, 0x3b, 0xe9, 0xdc, 0x18, 0xe5 } }
>
> +
>
>    #
>
>    # Gop Temp
>
>    #
>
> diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc
> b/UefiPayloadPkg/UefiPayloadPkg.dsc
> index 47812048dd..af9308ef8e 100644
> --- a/UefiPayloadPkg/UefiPayloadPkg.dsc
> +++ b/UefiPayloadPkg/UefiPayloadPkg.dsc
> @@ -30,7 +30,6 @@
>    DEFINE PS2_KEYBOARD_ENABLE          = FALSE
>
>    DEFINE RAM_DISK_ENABLE              = FALSE
>
>    DEFINE SIO_BUS_ENABLE               = FALSE
>
> -  DEFINE UNIVERSAL_PAYLOAD            = FALSE
>
>    DEFINE SECURITY_STUB_ENABLE         = TRUE
>
>    DEFINE SMM_SUPPORT                  = FALSE
>
>    DEFINE PLATFORM_BOOT_TIMEOUT        = 3
>
> @@ -44,6 +43,14 @@
>    DEFINE BOOTSPLASH_IMAGE             = FALSE
>
>    DEFINE NVME_ENABLE                  = TRUE
>
>    DEFINE CAPSULE_SUPPORT              = FALSE
>
> +  #
>
> +  # Setup Universal Payload
>
> +  #
>
> +  # ELF: Build UniversalPayload file as UniversalPayload.elf
>
> +  # FIT: Build UniversalPayload file as UniversalPayload.fit
>
> +  #
>
> +  DEFINE UNIVERSAL_PAYLOAD            = FALSE
>
> +  DEFINE UNIVERSAL_PAYLOAD_FORMAT     = ELF
>
>
>
>    #
>
>    # NULL:    NullMemoryTestDxe
>
> @@ -311,7 +318,7 @@
>
>  VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf
>
>    CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
>
>
>  ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
>
> -
>
> +  FdtLib|MdePkg/Library/BaseFdtLib/BaseFdtLib.inf
>
>  [LibraryClasses.common]
>
>  !if $(BOOTSPLASH_IMAGE)
>
>    SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
>
> @@ -600,14 +607,26 @@
>  !if "IA32" in "$(ARCH)"
>
>    [Components.IA32]
>
>    !if $(UNIVERSAL_PAYLOAD) == TRUE
>
> -    UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
>
> +    !if $(UNIVERSAL_PAYLOAD_FORMAT) == "ELF"
>
> +      UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
>
> +    !elseif $(UNIVERSAL_PAYLOAD_FORMAT) == "FIT"
>
> +      UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
>
> +    !else
>
> +      UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
>
> +    !endif
>
>    !else
>
>      UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
>
>    !endif
>
>  !else
>
>    [Components.X64]
>
>    !if $(UNIVERSAL_PAYLOAD) == TRUE
>
> -    UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
>
> +    !if $(UNIVERSAL_PAYLOAD_FORMAT) == "ELF"
>
> +      UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
>
> +    !elseif $(UNIVERSAL_PAYLOAD_FORMAT) == "FIT"
>
> +      UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
>
> +    !else
>
> +      UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
>
> +    !endif
>
>    !else
>
>      UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
>
>    !endif
>
> diff --git a/UefiPayloadPkg/UniversalPayloadBuild.py
> b/UefiPayloadPkg/UniversalPayloadBuild.py
> index 47f37b3377..9a83fc9e44 100644
> --- a/UefiPayloadPkg/UniversalPayloadBuild.py
> +++ b/UefiPayloadPkg/UniversalPayloadBuild.py
> @@ -10,10 +10,22 @@ import subprocess
>  import os
>
>  import shutil
>
>  import sys
>
> +import pathlib
>
>  from   ctypes import *
>
> -from Tools.ElfFv import ReplaceFv
>
> +
>
>  sys.dont_write_bytecode = True
>
>
>
> +class bcolors:
>
> +    HEADER = '\033[95m'
>
> +    OKBLUE = '\033[94m'
>
> +    OKCYAN = '\033[96m'
>
> +    OKGREEN = '\033[92m'
>
> +    WARNING = '\033[93m'
>
> +    FAIL = '\033[91m'
>
> +    ENDC = '\033[0m'
>
> +    BOLD = '\033[1m'
>
> +    UNDERLINE = '\033[4m'
>
> +
>
>  class UPLD_INFO_HEADER(LittleEndianStructure):
>
>      _pack_ = 1
>
>      _fields_ = [
>
> @@ -36,40 +48,114 @@ class UPLD_INFO_HEADER(LittleEndianStructure):
>          self.ImageId        = b'UEFI'
>
>          self.ProducerId     = b'INTEL'
>
>
>
> -def BuildUniversalPayload(Args):
>
> -    def RunCommand(cmd):
>
> -        print(cmd)
>
> -        p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
> stderr=subprocess.STDOUT,cwd=os.environ['WORKSPACE'])
>
> -        while True:
>
> -            line = p.stdout.readline()
>
> -            if not line:
>
> -                break
>
> -            print(line.strip().decode(errors='ignore'))
>
> -
>
> -        p.communicate()
>
> -        if p.returncode != 0:
>
> -            print("- Failed - error happened when run command: %s"%cmd)
>
> -            raise Exception("ERROR: when run command: %s"%cmd)
>
> +def ValidateSpecRevision (Argument):
>
> +    try:
>
> +        (MajorStr, MinorStr) = Argument.split('.')
>
> +    except:
>
> +        raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision
> format (Major[8-bits].Minor[8-bits]).'.format (Argument))
>
> +    #
>
> +    # Spec Revision Bits 15 : 8 - Major Version. Bits 7 : 0 - Minor
> Version.
>
> +    #
>
> +    if len(MinorStr) > 0 and len(MinorStr) < 3:
>
> +        try:
>
> +            Minor = int(MinorStr, 16) if len(MinorStr) == 2 else
> (int(MinorStr, 16) << 4)
>
> +        except:
>
> +            raise argparse.ArgumentTypeError ('{} Minor version of
> SpecRevision is not a valid integer value.'.format (Argument))
>
> +    else:
>
> +        raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision
> format (Major[8-bits].Minor[8-bits]).'.format (Argument))
>
> +
>
> +    if len(MajorStr) > 0 and len(MajorStr) < 3:
>
> +        try:
>
> +            Major = int(MajorStr, 16)
>
> +        except:
>
> +            raise argparse.ArgumentTypeError ('{} Major version of
> SpecRevision is not a valid integer value.'.format (Argument))
>
> +    else:
>
> +        raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision
> format (Major[8-bits].Minor[8-bits]).'.format (Argument))
>
> +
>
> +    return int('0x{0:02x}{1:02x}'.format(Major, Minor), 0)
>
> +
>
> +def Validate32BitInteger (Argument):
>
> +    try:
>
> +        Value = int (Argument, 0)
>
> +    except:
>
> +        raise argparse.ArgumentTypeError ('{} is not a valid integer
> value.'.format (Argument))
>
> +    if Value < 0:
>
> +        raise argparse.ArgumentTypeError ('{} is a negative
> value.'.format (Argument))
>
> +    if Value > 0xffffffff:
>
> +        raise argparse.ArgumentTypeError ('{} is larger than
> 32-bits.'.format (Argument))
>
> +    return Value
>
>
>
> +def ValidateAddFv (Argument):
>
> +    Value = Argument.split ("=")
>
> +    if len (Value) != 2:
>
> +        raise argparse.ArgumentTypeError ('{} is incorrect format with
> "xxx_fv=xxx.fv"'.format (Argument))
>
> +    if Value[0][-3:] != "_fv":
>
> +        raise argparse.ArgumentTypeError ('{} is incorrect format with
> "xxx_fv=xxx.fv"'.format (Argument))
>
> +    if Value[1][-3:].lower () != ".fv":
>
> +        raise argparse.ArgumentTypeError ('{} is incorrect format with
> "xxx_fv=xxx.fv"'.format (Argument))
>
> +    if os.path.exists (Value[1]) == False:
>
> +        raise argparse.ArgumentTypeError ('File {} is not found.'.format
> (Value[1]))
>
> +    return Value
>
> +
>
> +def RunCommand(cmd):
>
> +    print(cmd)
>
> +    p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
> stderr=subprocess.STDOUT,cwd=os.environ['WORKSPACE'])
>
> +    while True:
>
> +        line = p.stdout.readline()
>
> +        if not line:
>
> +            break
>
> +        print(line.strip().decode(errors='ignore'))
>
> +
>
> +    p.communicate()
>
> +    if p.returncode != 0:
>
> +        print("- Failed - error happened when run command: %s"%cmd)
>
> +        raise Exception("ERROR: when run command: %s"%cmd)
>
> +
>
> +def BuildUniversalPayload(Args):
>
>      BuildTarget = Args.Target
>
>      ToolChain = Args.ToolChain
>
>      Quiet     = "--quiet"  if Args.Quiet else ""
>
> -    ElfToolChain = 'CLANGDWARF'
>
> -    BuildDir     = os.path.join(os.environ['WORKSPACE'],
> os.path.normpath("Build/UefiPayloadPkgX64"))
>
> -    BuildModule = ""
>
> -    BuildArch = ""
>
>
>
> +    if Args.Fit == True:
>
> +        PayloadEntryToolChain = ToolChain
>
> +        Args.Macro.append("UNIVERSAL_PAYLOAD_FORMAT=FIT")
>
> +        UpldEntryFile = "FitUniversalPayloadEntry"
>
> +    else:
>
> +        PayloadEntryToolChain = 'CLANGDWARF'
>
> +        Args.Macro.append("UNIVERSAL_PAYLOAD_FORMAT=ELF")
>
> +        UpldEntryFile = "UniversalPayloadEntry"
>
> +
>
> +    BuildDir     = os.path.join(os.environ['WORKSPACE'],
> os.path.normpath("Build/UefiPayloadPkgX64"))
>
>      if Args.Arch == 'X64':
>
>          BuildArch      = "X64"
>
> -        EntryOutputDir = os.path.join(BuildDir, "{}_{}".format
> (BuildTarget, ElfToolChain),
> os.path.normpath("X64/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll"))
>
> +        FitArch        = "x86_64"
>
> +        ObjCopyFlag    = "elf64-x86-64"
>
> +        EntryOutputDir = os.path.join(BuildDir, "{}_{}".format
> (BuildTarget, PayloadEntryToolChain),
> os.path.normpath("X64/UefiPayloadPkg/UefiPayloadEntry/{}/DEBUG/{}.dll".format
> (UpldEntryFile, UpldEntryFile)))
>
>      else:
>
>          BuildArch      = "IA32 -a X64"
>
> -        EntryOutputDir = os.path.join(BuildDir, "{}_{}".format
> (BuildTarget, ElfToolChain),
> os.path.normpath("IA32/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll"))
>
> +        FitArch        = "x86"
>
> +        ObjCopyFlag    = "elf32-i386"
>
> +        EntryOutputDir = os.path.join(BuildDir, "{}_{}".format
> (BuildTarget, PayloadEntryToolChain),
> os.path.normpath("IA32/UefiPayloadPkg/UefiPayloadEntry/{}/DEBUG/{}.dll".format
> (UpldEntryFile, UpldEntryFile)))
>
>
>
> +    EntryModuleInf =
> os.path.normpath("UefiPayloadPkg/UefiPayloadEntry/{}.inf".format
> (UpldEntryFile))
>
>      DscPath = os.path.normpath("UefiPayloadPkg/UefiPayloadPkg.dsc")
>
> +    DxeFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget,
> ToolChain), os.path.normpath("FV/DXEFV.Fv"))
>
> +    BdsFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget,
> ToolChain), os.path.normpath("FV/BDSFV.Fv"))
>
> +    NetworkFvOutputDir = os.path.join(BuildDir, "{}_{}".format
> (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv"))
>
> +    PayloadReportPath = os.path.join(BuildDir, "UefiUniversalPayload.txt")
>
>      ModuleReportPath = os.path.join(BuildDir,
> "UefiUniversalPayloadEntry.txt")
>
>      UpldInfoFile = os.path.join(BuildDir, "UniversalPayloadInfo.bin")
>
>
>
> +    if "CLANG_BIN" in os.environ:
>
> +        LlvmObjcopyPath = os.path.join(os.environ["CLANG_BIN"],
> "llvm-objcopy")
>
> +    else:
>
> +        LlvmObjcopyPath = "llvm-objcopy"
>
> +    try:
>
> +        RunCommand('"%s" --version'%LlvmObjcopyPath)
>
> +    except:
>
> +        print("- Failed - Please check if LLVM is installed or if
> CLANG_BIN is set correctly")
>
> +        sys.exit(1)
>
> +
>
>      Pcds = ""
>
>      if (Args.pcd != None):
>
>          for PcdItem in Args.pcd:
>
> @@ -84,7 +170,6 @@ def BuildUniversalPayload(Args):
>      # Building DXE core and DXE drivers as DXEFV.
>
>      #
>
>      if Args.BuildEntryOnly == False:
>
> -        PayloadReportPath = os.path.join(BuildDir,
> "UefiUniversalPayload.txt")
>
>          BuildPayload = "build -p {} -b {} -a X64 -t {} -y {} {}".format
> (DscPath, BuildTarget, ToolChain, PayloadReportPath, Quiet)
>
>          BuildPayload += Pcds
>
>          BuildPayload += Defines
>
> @@ -93,94 +178,138 @@ def BuildUniversalPayload(Args):
>      # Building Universal Payload entry.
>
>      #
>
>      if Args.PreBuildUplBinary is None:
>
> -        EntryModuleInf =
> os.path.normpath("UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf")
>
> -        BuildModule = "build -p {} -b {} -a {} -m {} -t {} -y {}
> {}".format (DscPath, BuildTarget, BuildArch, EntryModuleInf, ElfToolChain,
> ModuleReportPath, Quiet)
>
> +        BuildModule = "build -p {} -b {} -a {} -m {} -t {} -y {}
> {}".format (DscPath, BuildTarget, BuildArch, EntryModuleInf,
> PayloadEntryToolChain, ModuleReportPath, Quiet)
>
>          BuildModule += Pcds
>
>          BuildModule += Defines
>
>          RunCommand(BuildModule)
>
>
>
>      if Args.PreBuildUplBinary is not None:
>
> -        EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.elf")
>
> +        if Args.Fit == False:
>
> +            EntryOutputDir = os.path.join(BuildDir,
> "UniversalPayload.elf")
>
> +        else:
>
> +            EntryOutputDir = os.path.join(BuildDir,
> "UniversalPayload.fit")
>
>          shutil.copy (os.path.abspath(Args.PreBuildUplBinary),
> EntryOutputDir)
>
>
>
>      #
>
> -    # Buid Universal Payload Information Section ".upld_info"
>
> +    # Build Universal Payload Information Section ".upld_info"
>
>      #
>
> -    upld_info_hdr              = UPLD_INFO_HEADER()
>
> -    upld_info_hdr.SpecRevision = Args.SpecRevision
>
> -    upld_info_hdr.Revision     = Args.Revision
>
> -    upld_info_hdr.ProducerId   = Args.ProducerId.encode()[:16]
>
> -    upld_info_hdr.ImageId      = Args.ImageId.encode()[:16]
>
> -    upld_info_hdr.Attribute   |= 1 if BuildTarget == "DEBUG" else 0
>
> -    fp = open(UpldInfoFile, 'wb')
>
> -    fp.write(bytearray(upld_info_hdr))
>
> -    fp.close()
>
> +    if Args.Fit == False:
>
> +        upld_info_hdr = UPLD_INFO_HEADER()
>
> +        upld_info_hdr.SpecRevision = Args.SpecRevision
>
> +        upld_info_hdr.Revision = Args.Revision
>
> +        upld_info_hdr.ProducerId = Args.ProducerId.encode()[:16]
>
> +        upld_info_hdr.ImageId = Args.ImageId.encode()[:16]
>
> +        upld_info_hdr.Attribute |= 1 if BuildTarget == "DEBUG" else 0
>
> +        fp = open(UpldInfoFile, 'wb')
>
> +        fp.write(bytearray(upld_info_hdr))
>
> +        fp.close()
>
> +
>
> +        if Args.BuildEntryOnly == False:
>
> +            import Tools.ElfFv as ElfFv
>
> +            ElfFv.ReplaceFv (EntryOutputDir, UpldInfoFile, '.upld_info',
> Alignment = 4)
>
> +    if Args.Fit == False:
>
> +        shutil.copy (EntryOutputDir, os.path.join(BuildDir,
> 'UniversalPayload.elf'))
>
> +    else:
>
> +        shutil.copy (EntryOutputDir, os.path.join(BuildDir,
> 'UniversalPayload.fit'))
>
>
>
>      MultiFvList = []
>
>      if Args.BuildEntryOnly == False:
>
>          MultiFvList = [
>
> -            ['uefi_fv',    os.path.join(BuildDir, "{}_{}".format
> (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv"))    ],
>
> -            ['bds_fv',     os.path.join(BuildDir, "{}_{}".format
> (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv"))    ],
>
> -            ['network_fv', os.path.join(BuildDir, "{}_{}".format
> (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv"))    ],
>
> +            ['uefi_fv',        os.path.join(BuildDir, "{}_{}".format
> (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv"))    ],
>
> +            ['bds_fv',         os.path.join(BuildDir, "{}_{}".format
> (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv"))    ],
>
> +            ['network_fv',     os.path.join(BuildDir, "{}_{}".format
> (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv"))],
>
>          ]
>
> -        AddSectionName = '.upld_info'
>
> -        ReplaceFv (EntryOutputDir, UpldInfoFile, AddSectionName,
> Alignment = 4)
>
>
>
> -    if Args.PreBuildUplBinary is None:
>
> -        shutil.copy (EntryOutputDir, os.path.join(BuildDir,
> 'UniversalPayload.elf'))
>
>
>
> -    return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.elf')
>
> +    if Args.Fit == True:
>
> +        import Tools.MkFitImage as MkFitImage
>
> +        import pefile
>
> +        fit_image_info_header               =
> MkFitImage.FIT_IMAGE_INFO_HEADER()
>
> +        fit_image_info_header.Description   = 'Uefi Universal Payload'
>
> +        fit_image_info_header.UplVersion    = Args.SpecRevision
>
> +        fit_image_info_header.Type          = 'flat-binary'
>
> +        fit_image_info_header.Arch          = FitArch
>
> +        fit_image_info_header.Compression   = 'none'
>
> +        fit_image_info_header.Revision      = Args.Revision
>
> +        fit_image_info_header.BuildType     = Args.Target.lower()
>
> +        fit_image_info_header.Capabilities  = None
>
> +        fit_image_info_header.Producer      = Args.ProducerId.lower()
>
> +        fit_image_info_header.ImageId       = Args.ImageId.lower()
>
> +        fit_image_info_header.Binary        = os.path.join(BuildDir,
> 'UniversalPayload.fit')
>
> +        fit_image_info_header.TargetPath    = os.path.join(BuildDir,
> 'UniversalPayload.fit')
>
> +        fit_image_info_header.UefifvPath    = DxeFvOutputDir
>
> +        fit_image_info_header.BdsfvPath     = BdsFvOutputDir
>
> +        fit_image_info_header.NetworkfvPath = NetworkFvOutputDir
>
> +        fit_image_info_header.DataOffset    = 0x1000
>
> +        fit_image_info_header.LoadAddr      = Args.LoadAddress
>
> +        fit_image_info_header.Project       = 'tianocore'
>
> +
>
> +        TargetRebaseFile = fit_image_info_header.Binary.replace
> (pathlib.Path(fit_image_info_header.Binary).suffix, ".pecoff")
>
> +        TargetRebaseEntryFile = fit_image_info_header.Binary.replace
> (pathlib.Path(fit_image_info_header.Binary).suffix, ".entry")
>
> +
>
>
>
> -def main():
>
> -    def ValidateSpecRevision (Argument):
>
> -        try:
>
> -            (MajorStr, MinorStr) = Argument.split('.')
>
> -        except:
>
> -            raise argparse.ArgumentTypeError ('{} is not a valid
> SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
>
>          #
>
> -        # Spec Revision Bits 15 : 8 - Major Version. Bits 7 : 0 - Minor
> Version.
>
> +        # Rebase PECOFF to load address
>
>          #
>
> -        if len(MinorStr) > 0 and len(MinorStr) < 3:
>
> -            try:
>
> -                Minor = int(MinorStr, 16) if len(MinorStr) == 2 else
> (int(MinorStr, 16) << 4)
>
> -            except:
>
> -                raise argparse.ArgumentTypeError ('{} Minor version of
> SpecRevision is not a valid integer value.'.format (Argument))
>
> -        else:
>
> -            raise argparse.ArgumentTypeError ('{} is not a valid
> SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
>
> +        RunCommand (
>
> +            "GenFw -e SEC -o {} {}".format (
>
> +              TargetRebaseFile,
>
> +              fit_image_info_header.Binary
>
> +            ))
>
> +        RunCommand (
>
> +            "GenFw --rebase 0x{:02X} -o {} {} ".format (
>
> +              fit_image_info_header.LoadAddr +
> fit_image_info_header.DataOffset,
>
> +              TargetRebaseFile,
>
> +              TargetRebaseFile,
>
> +            ))
>
>
>
> -        if len(MajorStr) > 0 and len(MajorStr) < 3:
>
> -            try:
>
> -                Major = int(MajorStr, 16)
>
> -            except:
>
> -                raise argparse.ArgumentTypeError ('{} Major version of
> SpecRevision is not a valid integer value.'.format (Argument))
>
> -        else:
>
> -            raise argparse.ArgumentTypeError ('{} is not a valid
> SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
>
> +        #
>
> +        # Open PECOFF relocation table binary.
>
> +        #
>
> +        RelocBinary     = b''
>
> +        PeCoff = pefile.PE (TargetRebaseFile)
>
> +        for reloc in PeCoff.DIRECTORY_ENTRY_BASERELOC:
>
> +            for entry in reloc.entries:
>
> +                if (entry.type == 0):
>
> +                    continue
>
> +                Type = entry.type
>
> +                Offset = entry.rva + fit_image_info_header.DataOffset
>
> +                RelocBinary += Type.to_bytes (8, 'little') +
> Offset.to_bytes (8, 'little')
>
> +        RelocBinary += b'\x00' * (0x1000 - (len(RelocBinary) % 0x1000))
>
>
>
> -        return int('0x{0:02x}{1:02x}'.format(Major, Minor), 0)
>
> +        #
>
> +        # Output UniversalPayload.entry
>
> +        #
>
> +        TempBinary = open (TargetRebaseFile, 'rb')
>
> +        TianoBinary = TempBinary.read ()
>
> +        TempBinary.close ()
>
>
>
> -    def Validate32BitInteger (Argument):
>
> -        try:
>
> -            Value = int (Argument, 0)
>
> -        except:
>
> -            raise argparse.ArgumentTypeError ('{} is not a valid integer
> value.'.format (Argument))
>
> -        if Value < 0:
>
> -            raise argparse.ArgumentTypeError ('{} is a negative
> value.'.format (Argument))
>
> -        if Value > 0xffffffff:
>
> -            raise argparse.ArgumentTypeError ('{} is larger than
> 32-bits.'.format (Argument))
>
> -        return Value
>
> -
>
> -    def ValidateAddFv (Argument):
>
> -        Value = Argument.split ("=")
>
> -        if len (Value) != 2:
>
> -            raise argparse.ArgumentTypeError ('{} is incorrect format
> with "xxx_fv=xxx.fv"'.format (Argument))
>
> -        if Value[0][-3:] != "_fv":
>
> -            raise argparse.ArgumentTypeError ('{} is incorrect format
> with "xxx_fv=xxx.fv"'.format (Argument))
>
> -        if Value[1][-3:].lower () != ".fv":
>
> -            raise argparse.ArgumentTypeError ('{} is incorrect format
> with "xxx_fv=xxx.fv"'.format (Argument))
>
> -        if os.path.exists (Value[1]) == False:
>
> -            raise argparse.ArgumentTypeError ('File {} is not
> found.'.format (Value[1]))
>
> -        return Value
>
> +        TianoEntryBinary = TianoBinary + RelocBinary
>
> +        TianoEntryBinary += (b'\x00' * (0x1000 - (len(TianoBinary) %
> 0x1000)))
>
> +        TianoEntryBinarySize = len (TianoEntryBinary)
>
> +
>
> +        TempBinary = open(TargetRebaseEntryFile, "wb")
>
> +        TempBinary.truncate()
>
> +        TempBinary.write(TianoEntryBinary)
>
> +        TempBinary.close()
>
> +
>
> +        #
>
> +        # Calculate entry and update relocation table start address and
> data-size.
>
> +        #
>
> +        fit_image_info_header.Entry      =
> PeCoff.OPTIONAL_HEADER.ImageBase +
> PeCoff.OPTIONAL_HEADER.AddressOfEntryPoint
>
> +        fit_image_info_header.RelocStart =
> fit_image_info_header.DataOffset + len(TianoBinary)
>
> +        fit_image_info_header.DataSize   = TianoEntryBinarySize
>
> +        fit_image_info_header.Binary     = TargetRebaseEntryFile
>
> +
>
> +        if MkFitImage.MakeFitImage(fit_image_info_header) is True:
>
> +            print('\nSuccessfully build Fit Image')
>
> +        else:
>
> +            sys.exit(1)
>
> +        return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.fit')
>
> +    else:
>
> +        return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.elf')
>
>
>
> +def main():
>
>      parser = argparse.ArgumentParser(description='For building Universal
> Payload')
>
>      parser.add_argument('-t', '--ToolChain')
>
>      parser.add_argument('-b', '--Target', default='DEBUG')
>
> @@ -192,13 +321,16 @@ def main():
>      parser.add_argument("-s", "--SpecRevision",
> type=ValidateSpecRevision, default ='0.7', help='Indicates compliance with
> a revision of this specification in the BCD format.')
>
>      parser.add_argument("-r", "--Revision", type=Validate32BitInteger,
> default ='0x0000010105', help='Revision of the Payload binary.
> Major.Minor.Revision.Build')
>
>      parser.add_argument("-o", "--ProducerId", default ='INTEL', help='A
> null-terminated OEM-supplied string that identifies the payload producer
> (16 bytes maximal).')
>
> +    parser.add_argument("-e", "--BuildEntryOnly", action='store_true',
> help='Build UniversalPayload Entry file')
>
> +    parser.add_argument("-pb", "--PreBuildUplBinary", default=None,
> help='Specify the UniversalPayload file')
>
>      parser.add_argument("-sk", "--SkipBuild", action='store_true',
> help='Skip UniversalPayload build')
>
>      parser.add_argument("-af", "--AddFv", type=ValidateAddFv,
> action='append', help='Add or replace specific FV into payload, Ex:
> uefi_fv=XXX.fv')
>
> -    command_group = parser.add_mutually_exclusive_group()
>
> -    command_group.add_argument("-e", "--BuildEntryOnly",
> action='store_true', help='Build UniversalPayload Entry file')
>
> -    command_group.add_argument("-pb", "--PreBuildUplBinary",
> default=None, help='Specify the UniversalPayload file')
>
> +    parser.add_argument("-f", "--Fit", action='store_true', help='Build
> UniversalPayload file as UniversalPayload.fit', default=False)
>
> +    parser.add_argument('-l', "--LoadAddress", type=int, help='Specify
> payload load address', default =0x000800000)
>
> +
>
>      args = parser.parse_args()
>
>
>
> +
>
>      MultiFvList = []
>
>      UniversalPayloadBinary = args.PreBuildUplBinary
>
>      if (args.SkipBuild == False):
>
> @@ -208,12 +340,24 @@ def main():
>          for (SectionName, SectionFvFile) in args.AddFv:
>
>              MultiFvList.append ([SectionName, SectionFvFile])
>
>
>
> +    def ReplaceFv (UplBinary, SectionFvFile, SectionName):
>
> +        print (bcolors.OKGREEN + "Patch {}={} into {}".format
> (SectionName, SectionFvFile, UplBinary) + bcolors.ENDC)
>
> +        if (args.Fit == False):
>
> +            import Tools.ElfFv as ElfFv
>
> +            return ElfFv.ReplaceFv (UplBinary, SectionFvFile,
> '.upld.{}'.format (SectionName))
>
> +        else:
>
> +            import Tools.MkFitImage as MkFitImage
>
> +            return MkFitImage.ReplaceFv (UplBinary, SectionFvFile,
> SectionName)
>
> +
>
>      if (UniversalPayloadBinary != None):
>
>          for (SectionName, SectionFvFile) in MultiFvList:
>
>              if os.path.exists (SectionFvFile) == False:
>
>                  continue
>
> -            print ("Patch {}={} into {}".format (SectionName,
> SectionFvFile, UniversalPayloadBinary))
>
> -            ReplaceFv (UniversalPayloadBinary, SectionFvFile,
> '.upld.{}'.format (SectionName))
>
> +
>
> +            status = ReplaceFv (UniversalPayloadBinary, SectionFvFile,
> SectionName.replace ("_", "-"))
>
> +            if status != 0:
>
> +                print (bcolors.FAIL + "[Fail] Patch {}={}".format
> (SectionName, SectionFvFile) + bcolors.ENDC)
>
> +                return status
>
>
>
>      print ("\nSuccessfully build Universal Payload")
>
>
>
> --
> 2.39.1.windows.1
>
>
>
> 
>
>
>


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#108704): https://edk2.groups.io/g/devel/message/108704
Mute This Topic: https://groups.io/mt/101375948/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



[-- Attachment #2: Type: text/html, Size: 138720 bytes --]

  reply	other threads:[~2023-09-15 10:27 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-15  8:58 [edk2-devel] [PATCH v2 0/2] UefiPayloadPkg supports Fit brucex.wang
2023-09-15  8:58 ` [edk2-devel] [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function brucex.wang
2023-09-15  9:02   ` Guo, Gua
2023-09-15  9:06   ` Lu, James
2023-09-15  9:09   ` Benny Lin
2023-09-15  8:58 ` [edk2-devel] [PATCH v2 2/2] UefiPayloadPkg: Add FIT support brucex.wang
2023-09-15  9:02   ` Guo, Gua
2023-09-15 10:26     ` Sheng Lean Tan [this message]
2023-09-15 10:32       ` Sheng Lean Tan
2023-09-15  9:06   ` Lu, James

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=CAMWxwJ2u77rG2E8AYuq7StapDsDmFxfZeO_Nj_e8zE9265evLg@mail.gmail.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