public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-devel] [PATCH v5 0/2] Add FIT support
@ 2023-09-25  2:15 brucex.wang
  2023-09-25  2:15 ` [edk2-devel] [PATCH v5 1/2] MdePkg/BaseFdtLib: Add Fdt function brucex.wang
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: brucex.wang @ 2023-09-25  2:15 UTC (permalink / raw)
  To: devel; +Cc: brucex.wang

From: "Brucex.Wang" <brucex.wang@intel.com>

V5: Fix Gcc build failure.
V4: Fix Benny comment in patch mail.
V3: Fix Lean Sheng comment in patch mail
V2: Fix Gua and Chasel comment in PR
V1: Initialize Version


Brucex.Wang (2):
  MdePkg/BaseFdtLib: Add Fdt function.
  UefiPayloadPkg: Add FIT support

 MdePkg/Include/Library/FdtLib.h               |  34 +
 MdePkg/Library/BaseFdtLib/FdtLib.c            |  40 ++
 .../Include/Guid/UniversalPayloadBase.h       |  19 +
 UefiPayloadPkg/PayloadLoaderPeim/FitLib.h     |  60 ++
 .../PayloadLoaderPeim/FitLib/FitLib.c         | 127 ++++
 .../PayloadLoaderPeim/FitPayloadLoaderPeim.c  | 150 ++++
 .../FitPayloadLoaderPeim.inf                  |  59 ++
 UefiPayloadPkg/Readme.md                      | 189 +++++
 UefiPayloadPkg/Tools/MkFitImage.py            | 272 ++++++++
 .../FitUniversalPayloadEntry.c                | 653 ++++++++++++++++++
 .../FitUniversalPayloadEntry.inf              |  98 +++
 UefiPayloadPkg/UefiPayloadPkg.dec             |   3 +
 UefiPayloadPkg/UefiPayloadPkg.dsc             |  27 +-
 UefiPayloadPkg/UniversalPayloadBuild.py       | 331 ++++++---
 14 files changed, 1966 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

-- 
2.39.1.windows.1



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



^ permalink raw reply	[flat|nested] 7+ messages in thread

* [edk2-devel] [PATCH v5 1/2] MdePkg/BaseFdtLib: Add Fdt function.
  2023-09-25  2:15 [edk2-devel] [PATCH v5 0/2] Add FIT support brucex.wang
@ 2023-09-25  2:15 ` brucex.wang
  2023-09-25  3:09   ` Guo, Gua
  2023-09-25  3:12   ` Benny Lin
  2023-09-25  2:15 ` [edk2-devel] [PATCH v5 2/2] UefiPayloadPkg: Add FIT support brucex.wang
  2023-09-25 23:28 ` [edk2-devel] [PATCH v5 0/2] " Guo, Gua
  2 siblings, 2 replies; 7+ messages in thread
From: brucex.wang @ 2023-09-25  2:15 UTC (permalink / raw)
  To: devel; +Cc: brucex.wang, Benny Lin, Gua Guo, Chasel Chiu, James Lu

From: "Brucex.Wang" <brucex.wang@intel.com>

Add FdtGetName() and FdtNodeDepth() function.

Cc: Benny Lin <benny.lin@intel.com>
Cc: Gua Guo <gua.guo@intel.com>
Cc: Chasel Chiu <chasel.chiu@intel.com>
Cc: James Lu <james.lu@intel.com>

Signed-off-by: BruceX Wang <brucex.wang@intel.com>
---
 MdePkg/Include/Library/FdtLib.h    | 34 +++++++++++++++++++++++++
 MdePkg/Library/BaseFdtLib/FdtLib.c | 40 ++++++++++++++++++++++++++++++
 2 files changed, 74 insertions(+)

diff --git a/MdePkg/Include/Library/FdtLib.h b/MdePkg/Include/Library/FdtLib.h
index cf5ceba9e9..d9300a18e3 100644
--- a/MdePkg/Include/Library/FdtLib.h
+++ b/MdePkg/Include/Library/FdtLib.h
@@ -398,4 +398,38 @@ FdtSetProp (
   IN UINT32       Length
   );
 
+/**
+  Returns the name of a given node.
+
+  @param[in] Fdt            The pointer to FDT blob.
+  @param[in] NodeOffse      Offset of node to check.
+  @param[in] Length         The pointer to an integer variable (will be overwritten) or NULL.
+
+  @return The pointer to the node's name.
+
+**/
+CONST CHAR8 *
+EFIAPI
+FdtGetName (
+  IN VOID    *Fdt,
+  IN INT32   NodeOffset,
+  IN UINT32  *Length
+  );
+
+/**
+  FdtNodeDepth() finds the depth of a given node.  The root node
+  has depth 0, its immediate subnodes depth 1 and so forth.
+
+  @param[in] Fdt            The pointer to FDT blob.
+  @param[in] NodeOffset     Offset of node to check.
+
+  @return Depth of the node at NodeOffset.
+**/
+INT32
+EFIAPI
+FdtNodeDepth (
+  IN CONST VOID  *Fdt,
+  IN INT32       NodeOffset
+  );
+
 #endif /* FDT_LIB_H_ */
diff --git a/MdePkg/Library/BaseFdtLib/FdtLib.c b/MdePkg/Library/BaseFdtLib/FdtLib.c
index 090b0b3fd4..1ef99ea882 100644
--- a/MdePkg/Library/BaseFdtLib/FdtLib.c
+++ b/MdePkg/Library/BaseFdtLib/FdtLib.c
@@ -402,3 +402,43 @@ FdtSetProp (
 {
   return fdt_setprop (Fdt, NodeOffset, Name, Value, (int)Length);
 }
+
+/**
+  Returns the name of a given node.
+
+  @param[in] Fdt            The pointer to FDT blob.
+  @param[in] NodeOffset     Offset of node to check.
+  @param[in] Length         The pointer to an integer variable (will be overwritten) or NULL.
+
+  @return The pointer to the node's name.
+
+**/
+CONST CHAR8 *
+EFIAPI
+FdtGetName (
+  IN VOID    *Fdt,
+  IN INT32   NodeOffset,
+  IN UINT32  *Length
+  )
+{
+  return fdt_get_name (Fdt, NodeOffset, (int *)Length);
+}
+
+/**
+  FdtNodeDepth() finds the depth of a given node.  The root node
+  has depth 0, its immediate subnodes depth 1 and so forth.
+
+  @param[in] Fdt            The pointer to FDT blob.
+  @param[in] NodeOffset     Offset of node to check.
+
+  @returns Depth of the node at NodeOffset.
+**/
+INT32
+EFIAPI
+FdtNodeDepth (
+  IN CONST VOID  *Fdt,
+  IN INT32       NodeOffset
+  )
+{
+  return fdt_node_depth (Fdt, NodeOffset);
+}
-- 
2.39.1.windows.1



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



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [edk2-devel] [PATCH v5 2/2] UefiPayloadPkg: Add FIT support
  2023-09-25  2:15 [edk2-devel] [PATCH v5 0/2] Add FIT support brucex.wang
  2023-09-25  2:15 ` [edk2-devel] [PATCH v5 1/2] MdePkg/BaseFdtLib: Add Fdt function brucex.wang
@ 2023-09-25  2:15 ` brucex.wang
  2023-09-25  3:09   ` Guo, Gua
  2023-09-25 23:28 ` [edk2-devel] [PATCH v5 0/2] " Guo, Gua
  2 siblings, 1 reply; 7+ messages in thread
From: brucex.wang @ 2023-09-25  2:15 UTC (permalink / raw)
  To: devel; +Cc: brucex.wang, Guo Dong, Sean Rhodes, James Lu, Gua Guo

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>
---
 MdePkg/Include/Library/FdtLib.h               |   6 +-
 MdePkg/Library/BaseFdtLib/FdtLib.c            |   8 +-
 .../Include/Guid/UniversalPayloadBase.h       |  19 +
 UefiPayloadPkg/PayloadLoaderPeim/FitLib.h     |  60 ++
 .../PayloadLoaderPeim/FitLib/FitLib.c         | 127 ++++
 .../PayloadLoaderPeim/FitPayloadLoaderPeim.c  | 150 ++++
 .../FitPayloadLoaderPeim.inf                  |  59 ++
 UefiPayloadPkg/Readme.md                      | 189 +++++
 UefiPayloadPkg/Tools/MkFitImage.py            | 272 ++++++++
 .../FitUniversalPayloadEntry.c                | 653 ++++++++++++++++++
 .../FitUniversalPayloadEntry.inf              |  98 +++
 UefiPayloadPkg/UefiPayloadPkg.dec             |   3 +
 UefiPayloadPkg/UefiPayloadPkg.dsc             |  27 +-
 UefiPayloadPkg/UniversalPayloadBuild.py       | 331 ++++++---
 14 files changed, 1899 insertions(+), 103 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/MdePkg/Include/Library/FdtLib.h b/MdePkg/Include/Library/FdtLib.h
index d9300a18e3..65d74609cd 100644
--- a/MdePkg/Include/Library/FdtLib.h
+++ b/MdePkg/Include/Library/FdtLib.h
@@ -411,9 +411,9 @@ FdtSetProp (
 CONST CHAR8 *
 EFIAPI
 FdtGetName (
-  IN VOID    *Fdt,
-  IN INT32   NodeOffset,
-  IN UINT32  *Length
+  IN VOID   *Fdt,
+  IN INT32  NodeOffset,
+  IN INT32  *Length
   );
 
 /**
diff --git a/MdePkg/Library/BaseFdtLib/FdtLib.c b/MdePkg/Library/BaseFdtLib/FdtLib.c
index 1ef99ea882..c9514af673 100644
--- a/MdePkg/Library/BaseFdtLib/FdtLib.c
+++ b/MdePkg/Library/BaseFdtLib/FdtLib.c
@@ -416,12 +416,12 @@ FdtSetProp (
 CONST CHAR8 *
 EFIAPI
 FdtGetName (
-  IN VOID    *Fdt,
-  IN INT32   NodeOffset,
-  IN UINT32  *Length
+  IN VOID   *Fdt,
+  IN INT32  NodeOffset,
+  IN INT32  *Length
   )
 {
-  return fdt_get_name (Fdt, NodeOffset, (int *)Length);
+  return fdt_get_name (Fdt, NodeOffset, Length);
 }
 
 /**
diff --git a/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
new file mode 100644
index 0000000000..60f2aa37dd
--- /dev/null
+++ b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
@@ -0,0 +1,19 @@
+/** @file
+  Universal Payload general definitions.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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..6a93b41590
--- /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 {
+  CHAR8     *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..de33d49bd1
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
@@ -0,0 +1,150 @@
+/** @file
+  FIT Load Image Support
+Copyright (c) 2023, 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..cd0cb186e1
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
@@ -0,0 +1,59 @@
+## @file
+#  Produce LoadFile PPI for payload loading.
+#
+#  Copyright (c) 2023, 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..cb7f39b3f7
--- /dev/null
+++ b/UefiPayloadPkg/Readme.md
@@ -0,0 +1,189 @@
+# UefiPayloadPkg
+Provide UEFI Universal Payload for different bootloader to generate EFI environment
+
+# Spec
+UniversalPayload URL: https://universalscalablefirmware.github.io/documentation/2_universal_payload.html
+UniversalPayload URL: https://universalpayload.github.io/spec/
+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..d2e7df4fbe
--- /dev/null
+++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
@@ -0,0 +1,653 @@
+/** @file
+  Copyright (c) 2023, 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
+      ));
+    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..01fb3aceb3
--- /dev/null
+++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
@@ -0,0 +1,98 @@
+## @file
+#  This is the first module for UEFI payload.
+#
+#  Copyright (c) 2023, 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..6f57fa6df6 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,139 @@ 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.PreBuildUplBinary is None:
+        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 +322,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 +341,26 @@ 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))
+            if (args.Fit == False):
+                status = ReplaceFv (UniversalPayloadBinary, SectionFvFile, SectionName)
+            else:
+                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 (#109045): https://edk2.groups.io/g/devel/message/109045
Mute This Topic: https://groups.io/mt/101576344/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH v5 2/2] UefiPayloadPkg: Add FIT support
  2023-09-25  2:15 ` [edk2-devel] [PATCH v5 2/2] UefiPayloadPkg: Add FIT support brucex.wang
@ 2023-09-25  3:09   ` Guo, Gua
  0 siblings, 0 replies; 7+ messages in thread
From: Guo, Gua @ 2023-09-25  3:09 UTC (permalink / raw)
  To: Wang, BruceX, devel@edk2.groups.io; +Cc: Dong, Guo, Rhodes, Sean, Lu, James

Reviewed-by: Gua Guo <gua.guo@intel.com>

-----Original Message-----
From: Wang, BruceX <brucex.wang@intel.com> 
Sent: Monday, September 25, 2023 10:15 AM
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 v5 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>
---
 MdePkg/Include/Library/FdtLib.h               |   6 +-
 MdePkg/Library/BaseFdtLib/FdtLib.c            |   8 +-
 .../Include/Guid/UniversalPayloadBase.h       |  19 +
 UefiPayloadPkg/PayloadLoaderPeim/FitLib.h     |  60 ++
 .../PayloadLoaderPeim/FitLib/FitLib.c         | 127 ++++
 .../PayloadLoaderPeim/FitPayloadLoaderPeim.c  | 150 ++++
 .../FitPayloadLoaderPeim.inf                  |  59 ++
 UefiPayloadPkg/Readme.md                      | 189 +++++
 UefiPayloadPkg/Tools/MkFitImage.py            | 272 ++++++++
 .../FitUniversalPayloadEntry.c                | 653 ++++++++++++++++++
 .../FitUniversalPayloadEntry.inf              |  98 +++
 UefiPayloadPkg/UefiPayloadPkg.dec             |   3 +
 UefiPayloadPkg/UefiPayloadPkg.dsc             |  27 +-
 UefiPayloadPkg/UniversalPayloadBuild.py       | 331 ++++++---
 14 files changed, 1899 insertions(+), 103 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/MdePkg/Include/Library/FdtLib.h b/MdePkg/Include/Library/FdtLib.h
index d9300a18e3..65d74609cd 100644
--- a/MdePkg/Include/Library/FdtLib.h
+++ b/MdePkg/Include/Library/FdtLib.h
@@ -411,9 +411,9 @@ FdtSetProp (
 CONST CHAR8 *

 EFIAPI

 FdtGetName (

-  IN VOID    *Fdt,

-  IN INT32   NodeOffset,

-  IN UINT32  *Length

+  IN VOID   *Fdt,

+  IN INT32  NodeOffset,

+  IN INT32  *Length

   );

 

 /**

diff --git a/MdePkg/Library/BaseFdtLib/FdtLib.c b/MdePkg/Library/BaseFdtLib/FdtLib.c
index 1ef99ea882..c9514af673 100644
--- a/MdePkg/Library/BaseFdtLib/FdtLib.c
+++ b/MdePkg/Library/BaseFdtLib/FdtLib.c
@@ -416,12 +416,12 @@ FdtSetProp (
 CONST CHAR8 *

 EFIAPI

 FdtGetName (

-  IN VOID    *Fdt,

-  IN INT32   NodeOffset,

-  IN UINT32  *Length

+  IN VOID   *Fdt,

+  IN INT32  NodeOffset,

+  IN INT32  *Length

   )

 {

-  return fdt_get_name (Fdt, NodeOffset, (int *)Length);

+  return fdt_get_name (Fdt, NodeOffset, Length);

 }

 

 /**

diff --git a/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
new file mode 100644
index 0000000000..60f2aa37dd
--- /dev/null
+++ b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
@@ -0,0 +1,19 @@
+/** @file

+  Universal Payload general definitions.

+

+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>

+SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#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..6a93b41590
--- /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 {

+  CHAR8     *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..de33d49bd1
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
@@ -0,0 +1,150 @@
+/** @file

+  FIT Load Image Support

+Copyright (c) 2023, 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..cd0cb186e1
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
@@ -0,0 +1,59 @@
+## @file

+#  Produce LoadFile PPI for payload loading.

+#

+#  Copyright (c) 2023, 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..cb7f39b3f7
--- /dev/null
+++ b/UefiPayloadPkg/Readme.md
@@ -0,0 +1,189 @@
+# UefiPayloadPkg

+Provide UEFI Universal Payload for different bootloader to generate EFI environment

+

+# Spec

+UniversalPayload URL: https://universalscalablefirmware.github.io/documentation/2_universal_payload.html

+UniversalPayload URL: https://universalpayload.github.io/spec/

+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..d2e7df4fbe
--- /dev/null
+++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
@@ -0,0 +1,653 @@
+/** @file

+  Copyright (c) 2023, 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

+      ));

+    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..01fb3aceb3
--- /dev/null
+++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
@@ -0,0 +1,98 @@
+## @file

+#  This is the first module for UEFI payload.

+#

+#  Copyright (c) 2023, 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..6f57fa6df6 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,139 @@ 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.PreBuildUplBinary is None:

+        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 +322,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 +341,26 @@ 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))

+            if (args.Fit == False):

+                status = ReplaceFv (UniversalPayloadBinary, SectionFvFile, SectionName)

+            else:

+                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 (#109032): https://edk2.groups.io/g/devel/message/109032
Mute This Topic: https://groups.io/mt/101568106/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH v5 1/2] MdePkg/BaseFdtLib: Add Fdt function.
  2023-09-25  2:15 ` [edk2-devel] [PATCH v5 1/2] MdePkg/BaseFdtLib: Add Fdt function brucex.wang
@ 2023-09-25  3:09   ` Guo, Gua
  2023-09-25  3:12   ` Benny Lin
  1 sibling, 0 replies; 7+ messages in thread
From: Guo, Gua @ 2023-09-25  3:09 UTC (permalink / raw)
  To: Wang, BruceX, devel@edk2.groups.io; +Cc: Lin, Benny, Chiu, Chasel, Lu, James

Reviewed-by: Gua Guo <gua.guo@intel.com>

-----Original Message-----
From: Wang, BruceX <brucex.wang@intel.com> 
Sent: Monday, September 25, 2023 10:15 AM
To: devel@edk2.groups.io
Cc: Wang, BruceX <brucex.wang@intel.com>; Lin, Benny <benny.lin@intel.com>; Guo, Gua <gua.guo@intel.com>; Chiu, Chasel <chasel.chiu@intel.com>; Lu, James <james.lu@intel.com>
Subject: [PATCH v5 1/2] MdePkg/BaseFdtLib: Add Fdt function.

From: "Brucex.Wang" <brucex.wang@intel.com>

Add FdtGetName() and FdtNodeDepth() function.

Cc: Benny Lin <benny.lin@intel.com>
Cc: Gua Guo <gua.guo@intel.com>
Cc: Chasel Chiu <chasel.chiu@intel.com>
Cc: James Lu <james.lu@intel.com>

Signed-off-by: BruceX Wang <brucex.wang@intel.com>
---
 MdePkg/Include/Library/FdtLib.h    | 34 +++++++++++++++++++++++++
 MdePkg/Library/BaseFdtLib/FdtLib.c | 40 ++++++++++++++++++++++++++++++
 2 files changed, 74 insertions(+)

diff --git a/MdePkg/Include/Library/FdtLib.h b/MdePkg/Include/Library/FdtLib.h index cf5ceba9e9..d9300a18e3 100644
--- a/MdePkg/Include/Library/FdtLib.h
+++ b/MdePkg/Include/Library/FdtLib.h
@@ -398,4 +398,38 @@ FdtSetProp (
   IN UINT32       Length   ); +/**+  Returns the name of a given node.++  @param[in] Fdt            The pointer to FDT blob.+  @param[in] NodeOffse      Offset of node to check.+  @param[in] Length         The pointer to an integer variable (will be overwritten) or NULL.++  @return The pointer to the node's name.++**/+CONST CHAR8 *+EFIAPI+FdtGetName (+  IN VOID    *Fdt,+  IN INT32   NodeOffset,+  IN UINT32  *Length+  );++/**+  FdtNodeDepth() finds the depth of a given node.  The root node+  has depth 0, its immediate subnodes depth 1 and so forth.++  @param[in] Fdt            The pointer to FDT blob.+  @param[in] NodeOffset     Offset of node to check.++  @return Depth of the node at NodeOffset.+**/+INT32+EFIAPI+FdtNodeDepth (+  IN CONST VOID  *Fdt,+  IN INT32       NodeOffset+  );+ #endif /* FDT_LIB_H_ */diff --git a/MdePkg/Library/BaseFdtLib/FdtLib.c b/MdePkg/Library/BaseFdtLib/FdtLib.c
index 090b0b3fd4..1ef99ea882 100644
--- a/MdePkg/Library/BaseFdtLib/FdtLib.c
+++ b/MdePkg/Library/BaseFdtLib/FdtLib.c
@@ -402,3 +402,43 @@ FdtSetProp (
 {   return fdt_setprop (Fdt, NodeOffset, Name, Value, (int)Length); }++/**+  Returns the name of a given node.++  @param[in] Fdt            The pointer to FDT blob.+  @param[in] NodeOffset     Offset of node to check.+  @param[in] Length         The pointer to an integer variable (will be overwritten) or NULL.++  @return The pointer to the node's name.++**/+CONST CHAR8 *+EFIAPI+FdtGetName (+  IN VOID    *Fdt,+  IN INT32   NodeOffset,+  IN UINT32  *Length+  )+{+  return fdt_get_name (Fdt, NodeOffset, (int *)Length);+}++/**+  FdtNodeDepth() finds the depth of a given node.  The root node+  has depth 0, its immediate subnodes depth 1 and so forth.++  @param[in] Fdt            The pointer to FDT blob.+  @param[in] NodeOffset     Offset of node to check.++  @returns Depth of the node at NodeOffset.+**/+INT32+EFIAPI+FdtNodeDepth (+  IN CONST VOID  *Fdt,+  IN INT32       NodeOffset+  )+{+  return fdt_node_depth (Fdt, NodeOffset);+}-- 
2.39.1.windows.1



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



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH v5 1/2] MdePkg/BaseFdtLib: Add Fdt function.
  2023-09-25  2:15 ` [edk2-devel] [PATCH v5 1/2] MdePkg/BaseFdtLib: Add Fdt function brucex.wang
  2023-09-25  3:09   ` Guo, Gua
@ 2023-09-25  3:12   ` Benny Lin
  1 sibling, 0 replies; 7+ messages in thread
From: Benny Lin @ 2023-09-25  3:12 UTC (permalink / raw)
  To: Wang, BruceX, devel@edk2.groups.io; +Cc: Guo, Gua, Chiu, Chasel, Lu, James

Reviewed-by: Benny Lin <benny.lin@intel.com>

-----Original Message-----
From: Wang, BruceX <brucex.wang@intel.com> 
Sent: Monday, September 25, 2023 10:15 AM
To: devel@edk2.groups.io
Cc: Wang, BruceX <brucex.wang@intel.com>; Lin, Benny <benny.lin@intel.com>; Guo, Gua <gua.guo@intel.com>; Chiu, Chasel <chasel.chiu@intel.com>; Lu, James <james.lu@intel.com>
Subject: [PATCH v5 1/2] MdePkg/BaseFdtLib: Add Fdt function.

From: "Brucex.Wang" <brucex.wang@intel.com>

Add FdtGetName() and FdtNodeDepth() function.

Cc: Benny Lin <benny.lin@intel.com>
Cc: Gua Guo <gua.guo@intel.com>
Cc: Chasel Chiu <chasel.chiu@intel.com>
Cc: James Lu <james.lu@intel.com>

Signed-off-by: BruceX Wang <brucex.wang@intel.com>
---
 MdePkg/Include/Library/FdtLib.h    | 34 +++++++++++++++++++++++++
 MdePkg/Library/BaseFdtLib/FdtLib.c | 40 ++++++++++++++++++++++++++++++
 2 files changed, 74 insertions(+)

diff --git a/MdePkg/Include/Library/FdtLib.h b/MdePkg/Include/Library/FdtLib.h index cf5ceba9e9..d9300a18e3 100644
--- a/MdePkg/Include/Library/FdtLib.h
+++ b/MdePkg/Include/Library/FdtLib.h
@@ -398,4 +398,38 @@ FdtSetProp (
   IN UINT32       Length   ); +/**+  Returns the name of a given node.++  @param[in] Fdt            The pointer to FDT blob.+  @param[in] NodeOffse      Offset of node to check.+  @param[in] Length         The pointer to an integer variable (will be overwritten) or NULL.++  @return The pointer to the node's name.++**/+CONST CHAR8 *+EFIAPI+FdtGetName (+  IN VOID    *Fdt,+  IN INT32   NodeOffset,+  IN UINT32  *Length+  );++/**+  FdtNodeDepth() finds the depth of a given node.  The root node+  has depth 0, its immediate subnodes depth 1 and so forth.++  @param[in] Fdt            The pointer to FDT blob.+  @param[in] NodeOffset     Offset of node to check.++  @return Depth of the node at NodeOffset.+**/+INT32+EFIAPI+FdtNodeDepth (+  IN CONST VOID  *Fdt,+  IN INT32       NodeOffset+  );+ #endif /* FDT_LIB_H_ */diff --git a/MdePkg/Library/BaseFdtLib/FdtLib.c b/MdePkg/Library/BaseFdtLib/FdtLib.c
index 090b0b3fd4..1ef99ea882 100644
--- a/MdePkg/Library/BaseFdtLib/FdtLib.c
+++ b/MdePkg/Library/BaseFdtLib/FdtLib.c
@@ -402,3 +402,43 @@ FdtSetProp (
 {   return fdt_setprop (Fdt, NodeOffset, Name, Value, (int)Length); }++/**+  Returns the name of a given node.++  @param[in] Fdt            The pointer to FDT blob.+  @param[in] NodeOffset     Offset of node to check.+  @param[in] Length         The pointer to an integer variable (will be overwritten) or NULL.++  @return The pointer to the node's name.++**/+CONST CHAR8 *+EFIAPI+FdtGetName (+  IN VOID    *Fdt,+  IN INT32   NodeOffset,+  IN UINT32  *Length+  )+{+  return fdt_get_name (Fdt, NodeOffset, (int *)Length);+}++/**+  FdtNodeDepth() finds the depth of a given node.  The root node+  has depth 0, its immediate subnodes depth 1 and so forth.++  @param[in] Fdt            The pointer to FDT blob.+  @param[in] NodeOffset     Offset of node to check.++  @returns Depth of the node at NodeOffset.+**/+INT32+EFIAPI+FdtNodeDepth (+  IN CONST VOID  *Fdt,+  IN INT32       NodeOffset+  )+{+  return fdt_node_depth (Fdt, NodeOffset);+}-- 
2.39.1.windows.1



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



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH v5 0/2] Add FIT support
  2023-09-25  2:15 [edk2-devel] [PATCH v5 0/2] Add FIT support brucex.wang
  2023-09-25  2:15 ` [edk2-devel] [PATCH v5 1/2] MdePkg/BaseFdtLib: Add Fdt function brucex.wang
  2023-09-25  2:15 ` [edk2-devel] [PATCH v5 2/2] UefiPayloadPkg: Add FIT support brucex.wang
@ 2023-09-25 23:28 ` Guo, Gua
  2 siblings, 0 replies; 7+ messages in thread
From: Guo, Gua @ 2023-09-25 23:28 UTC (permalink / raw)
  To: devel@edk2.groups.io, Wang, BruceX
  Cc: Chiu, Chasel, Lu, James, Lin, Benny, Dong, Guo

Series Reviewed-by: Gua Guo <gua.guo@intel.com>

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of brucex.wang@intel.com
Sent: Monday, September 25, 2023 10:15 AM
To: devel@edk2.groups.io
Cc: Wang, BruceX <brucex.wang@intel.com>
Subject: [edk2-devel] [PATCH v5 0/2] Add FIT support

From: "Brucex.Wang" <brucex.wang@intel.com>

V5: Fix Gcc build failure.
V4: Fix Benny comment in patch mail.
V3: Fix Lean Sheng comment in patch mail
V2: Fix Gua and Chasel comment in PR
V1: Initialize Version


Brucex.Wang (2):
  MdePkg/BaseFdtLib: Add Fdt function.
  UefiPayloadPkg: Add FIT support

 MdePkg/Include/Library/FdtLib.h               |  34 +
 MdePkg/Library/BaseFdtLib/FdtLib.c            |  40 ++
 .../Include/Guid/UniversalPayloadBase.h       |  19 +
 UefiPayloadPkg/PayloadLoaderPeim/FitLib.h     |  60 ++
 .../PayloadLoaderPeim/FitLib/FitLib.c         | 127 ++++
 .../PayloadLoaderPeim/FitPayloadLoaderPeim.c  | 150 ++++
 .../FitPayloadLoaderPeim.inf                  |  59 ++
 UefiPayloadPkg/Readme.md                      | 189 +++++
 UefiPayloadPkg/Tools/MkFitImage.py            | 272 ++++++++
 .../FitUniversalPayloadEntry.c                | 653 ++++++++++++++++++
 .../FitUniversalPayloadEntry.inf              |  98 +++
 UefiPayloadPkg/UefiPayloadPkg.dec             |   3 +
 UefiPayloadPkg/UefiPayloadPkg.dsc             |  27 +-
 UefiPayloadPkg/UniversalPayloadBuild.py       | 331 ++++++---
 14 files changed, 1966 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

--
2.39.1.windows.1








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



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-09-25 23:28 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-25  2:15 [edk2-devel] [PATCH v5 0/2] Add FIT support brucex.wang
2023-09-25  2:15 ` [edk2-devel] [PATCH v5 1/2] MdePkg/BaseFdtLib: Add Fdt function brucex.wang
2023-09-25  3:09   ` Guo, Gua
2023-09-25  3:12   ` Benny Lin
2023-09-25  2:15 ` [edk2-devel] [PATCH v5 2/2] UefiPayloadPkg: Add FIT support brucex.wang
2023-09-25  3:09   ` Guo, Gua
2023-09-25 23:28 ` [edk2-devel] [PATCH v5 0/2] " Guo, Gua

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox