public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-devel] [PATCH v4 0/4] UefiPayloadPkg: Add FIT support
@ 2023-09-18  6:37 brucex.wang
  2023-09-18  6:37 ` [edk2-devel] [PATCH v4 1/4] OvmfPkg: Remove applicationProcessorEntryPoint brucex.wang
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: brucex.wang @ 2023-09-18  6:37 UTC (permalink / raw)
  To: devel; +Cc: brucex.wang

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

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

Zhiguang Liu (2):
  OvmfPkg: Remove applicationProcessorEntryPoint
  UefiCpuPkg/ResetVector: Remove AP waking vector from ResetVector

 MdePkg/Include/Library/FdtLib.h               |  34 +
 MdePkg/Library/BaseFdtLib/FdtLib.c            |  40 ++
 OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm  |  15 +-
 .../XenResetVector/Ia16/ResetVectorVtf0.asm   |  16 +-
 UefiCpuPkg/ResetVector/Vtf0/Ia16/Init16.asm   |   7 -
 .../ResetVector/Vtf0/Ia16/ResetVectorVtf0.asm |  15 +-
 .../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                | 654 ++++++++++++++++++
 .../FitUniversalPayloadEntry.inf              |  98 +++
 UefiPayloadPkg/UefiPayloadPkg.dec             |   3 +
 UefiPayloadPkg/UefiPayloadPkg.dsc             |  27 +-
 UefiPayloadPkg/UniversalPayloadBuild.py       | 328 ++++++---
 18 files changed, 1973 insertions(+), 140 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 (#108783): https://edk2.groups.io/g/devel/message/108783
Mute This Topic: https://groups.io/mt/101435612/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



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

* [edk2-devel] [PATCH v4 1/4] OvmfPkg: Remove applicationProcessorEntryPoint
  2023-09-18  6:37 [edk2-devel] [PATCH v4 0/4] UefiPayloadPkg: Add FIT support brucex.wang
@ 2023-09-18  6:37 ` brucex.wang
  2023-09-18  6:37 ` [edk2-devel] [PATCH v4 2/4] UefiCpuPkg/ResetVector: Remove AP waking vector from ResetVector brucex.wang
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: brucex.wang @ 2023-09-18  6:37 UTC (permalink / raw)
  To: devel
  Cc: brucex.wang, Zhiguang Liu, Ard Biesheuvel, Jiewen Yao,
	Jordan Justen, Gerd Hoffmann, Anthony Perard, Julien Grall,
	Ray Ni

From: Zhiguang Liu <zhiguang.liu@intel.com>

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4494

Current reset vector uses 0xffffffe0 as AP waking vector, and expects
GenFv generates code aligned on a 4k boundary which will jump to this
location. However, some issues are listed below
1. GenFV doesn't generate code as the comment expects, because GenFv
assumes no modifications are required to the VTF-0 'Volume Top File'.
2. Even if removing VFT0 signature and let GenFv to modify, Genfv is
hard-code using another flash address 0xffffffd0.
3. In the same patch series, AP waking vector code is removed from
GenFv, because no such usage anymore. The existing of first two issues
also approve the usage is not available for a long time.

Therefore, remove AP waking vector related code.

Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Julien Grall <julien@xen.org>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
Signed-off-by: Zhiguang Liu <zhiguang.liu@intel.com>
---
 OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm    | 15 +++------------
 OvmfPkg/XenResetVector/Ia16/ResetVectorVtf0.asm | 16 +++-------------
 2 files changed, 6 insertions(+), 25 deletions(-)

diff --git a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
index 12f2cedd67..8f94da89f7 100644
--- a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
+++ b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
@@ -160,22 +160,13 @@ guidedStructureEnd:
 
 ALIGN   16
 
-applicationProcessorEntryPoint:
 ;
-; Application Processors entry point
+; 0xffffffe0
 ;
-; GenFv generates code aligned on a 4k boundary which will jump to this
-; location.  (0xffffffe0)  This allows the Local APIC Startup IPI to be
-; used to wake up the application processors.
-;
-    jmp     EarlyApInitReal16
-
-ALIGN   8
-
-    DD      0
+    DD      0, 0, 0
 
 ;
-; The VTF signature
+; The VTF signature (0xffffffec)
 ;
 ; VTF-0 means that the VTF (Volume Top File) code does not require
 ; any fixups.
diff --git a/OvmfPkg/XenResetVector/Ia16/ResetVectorVtf0.asm b/OvmfPkg/XenResetVector/Ia16/ResetVectorVtf0.asm
index 56749bdbc9..67156d8252 100644
--- a/OvmfPkg/XenResetVector/Ia16/ResetVectorVtf0.asm
+++ b/OvmfPkg/XenResetVector/Ia16/ResetVectorVtf0.asm
@@ -39,23 +39,13 @@ xenPVHEntryPoint:
 
 BITS    16
 ALIGN   16
-
-applicationProcessorEntryPoint:
-;
-; Application Processors entry point
 ;
-; GenFv generates code aligned on a 4k boundary which will jump to this
-; location.  (0xffffffe0)  This allows the Local APIC Startup IPI to be
-; used to wake up the application processors.
+; 0xffffffe0
 ;
-    jmp     EarlyApInitReal16
-
-ALIGN   8
-
-    DD      0
+   DD      0, 0, 0
 
 ;
-; The VTF signature
+; The VTF signature (0xffffffec)
 ;
 ; VTF-0 means that the VTF (Volume Top File) code does not require
 ; any fixups.
-- 
2.39.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#108784): https://edk2.groups.io/g/devel/message/108784
Mute This Topic: https://groups.io/mt/101435613/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] 6+ messages in thread

* [edk2-devel] [PATCH v4 2/4] UefiCpuPkg/ResetVector: Remove AP waking vector from ResetVector
  2023-09-18  6:37 [edk2-devel] [PATCH v4 0/4] UefiPayloadPkg: Add FIT support brucex.wang
  2023-09-18  6:37 ` [edk2-devel] [PATCH v4 1/4] OvmfPkg: Remove applicationProcessorEntryPoint brucex.wang
@ 2023-09-18  6:37 ` brucex.wang
  2023-09-18  6:37 ` [edk2-devel] [PATCH v4 3/4] MdePkg/BaseFdtLib: Add Fdt function brucex.wang
  2023-09-18  6:37 ` [edk2-devel] [PATCH v4 4/4] UefiPayloadPkg: Add FIT support brucex.wang
  3 siblings, 0 replies; 6+ messages in thread
From: brucex.wang @ 2023-09-18  6:37 UTC (permalink / raw)
  To: devel
  Cc: brucex.wang, Zhiguang Liu, Eric Dong, Ray Ni, Rahul Kumar,
	Gerd Hoffmann

From: Zhiguang Liu <zhiguang.liu@intel.com>

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4494

Current reset vector uses 0xffffffe0 as AP waking vector, and expects
GenFv generates code aligned on a 4k boundary which will jump to this
location. However, some issues are listed below
1. GenFV doesn't generate code as the comment expects, because GenFv
assumes no modifications are required to the VTF-0 'Volume Top File'.
2. Even if removing VFT0 signature and let GenFv to modify, Genfv is
hard-code using another flash address 0xffffffd0.
3. In the same patch series, AP waking vector code is removed from
GenFv, because no such usage anymore. The existing of first two issues
also approve the usage is not available for a long time.

Therefore, remove AP waking vector related code.

Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Signed-off-by: Zhiguang Liu <zhiguang.liu@intel.com>
---
 UefiCpuPkg/ResetVector/Vtf0/Ia16/Init16.asm       |  7 -------
 .../ResetVector/Vtf0/Ia16/ResetVectorVtf0.asm     | 15 +++------------
 2 files changed, 3 insertions(+), 19 deletions(-)

diff --git a/UefiCpuPkg/ResetVector/Vtf0/Ia16/Init16.asm b/UefiCpuPkg/ResetVector/Vtf0/Ia16/Init16.asm
index cbdadee166..02b9a0303c 100644
--- a/UefiCpuPkg/ResetVector/Vtf0/Ia16/Init16.asm
+++ b/UefiCpuPkg/ResetVector/Vtf0/Ia16/Init16.asm
@@ -17,13 +17,6 @@ EarlyBspInitReal16:
     mov     di, 'BP'
     jmp     short Main16
 
-;
-; @param[out] DI    'AP' to indicate application processor
-;
-EarlyApInitReal16:
-    mov     di, 'AP'
-    jmp     short Main16
-
 ;
 ; Modified:  EAX
 ;
diff --git a/UefiCpuPkg/ResetVector/Vtf0/Ia16/ResetVectorVtf0.asm b/UefiCpuPkg/ResetVector/Vtf0/Ia16/ResetVectorVtf0.asm
index fe5bbea803..384b1d4d98 100644
--- a/UefiCpuPkg/ResetVector/Vtf0/Ia16/ResetVectorVtf0.asm
+++ b/UefiCpuPkg/ResetVector/Vtf0/Ia16/ResetVectorVtf0.asm
@@ -32,22 +32,13 @@ ALIGN   16
     TIMES (0x1000 - 0x20) DB 0
 %endif
 
-applicationProcessorEntryPoint:
 ;
-; Application Processors entry point
+; 0xffffffe0
 ;
-; GenFv generates code aligned on a 4k boundary which will jump to this
-; location.  (0xffffffe0)  This allows the Local APIC Startup IPI to be
-; used to wake up the application processors.
-;
-    jmp     EarlyApInitReal16
-
-ALIGN   8
-
-    DD      0
+    DD      0, 0, 0
 
 ;
-; The VTF signature
+; The VTF signature (0xffffffec)
 ;
 ; VTF-0 means that the VTF (Volume Top File) code does not require
 ; any fixups.
-- 
2.39.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#108785): https://edk2.groups.io/g/devel/message/108785
Mute This Topic: https://groups.io/mt/101435614/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] 6+ messages in thread

* [edk2-devel] [PATCH v4 3/4] MdePkg/BaseFdtLib: Add Fdt function.
  2023-09-18  6:37 [edk2-devel] [PATCH v4 0/4] UefiPayloadPkg: Add FIT support brucex.wang
  2023-09-18  6:37 ` [edk2-devel] [PATCH v4 1/4] OvmfPkg: Remove applicationProcessorEntryPoint brucex.wang
  2023-09-18  6:37 ` [edk2-devel] [PATCH v4 2/4] UefiCpuPkg/ResetVector: Remove AP waking vector from ResetVector brucex.wang
@ 2023-09-18  6:37 ` brucex.wang
  2023-09-18  6:37 ` [edk2-devel] [PATCH v4 4/4] UefiPayloadPkg: Add FIT support brucex.wang
  3 siblings, 0 replies; 6+ messages in thread
From: brucex.wang @ 2023-09-18  6:37 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 (#108786): https://edk2.groups.io/g/devel/message/108786
Mute This Topic: https://groups.io/mt/101435615/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] 6+ messages in thread

* [edk2-devel] [PATCH v4 4/4] UefiPayloadPkg: Add FIT support
  2023-09-18  6:37 [edk2-devel] [PATCH v4 0/4] UefiPayloadPkg: Add FIT support brucex.wang
                   ` (2 preceding siblings ...)
  2023-09-18  6:37 ` [edk2-devel] [PATCH v4 3/4] MdePkg/BaseFdtLib: Add Fdt function brucex.wang
@ 2023-09-18  6:37 ` brucex.wang
  3 siblings, 0 replies; 6+ messages in thread
From: brucex.wang @ 2023-09-18  6:37 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>
---
 .../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                | 654 ++++++++++++++++++
 .../FitUniversalPayloadEntry.inf              |  98 +++
 UefiPayloadPkg/UefiPayloadPkg.dec             |   3 +
 UefiPayloadPkg/UefiPayloadPkg.dsc             |  27 +-
 UefiPayloadPkg/UniversalPayloadBuild.py       | 328 ++++++---
 12 files changed, 1890 insertions(+), 96 deletions(-)
 create mode 100644 UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
 create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
 create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
 create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
 create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
 create mode 100644 UefiPayloadPkg/Readme.md
 create mode 100644 UefiPayloadPkg/Tools/MkFitImage.py
 create mode 100644 UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
 create mode 100644 UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf

diff --git a/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
new file mode 100644
index 0000000000..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..0514d675a6
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
@@ -0,0 +1,60 @@
+/** @file
+  FIT Load Image Support
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef FIT_LIB_H_
+#define FIT_LIB_H_
+
+#include <PiPei.h>
+#include <Library/DebugLib.h>
+#include <Library/FdtLib.h>
+
+typedef struct {
+  UINT64    RelocateType;
+  UINT64    Offset;
+} FIT_RELOCATE_ITEM;
+
+typedef struct {
+  EFI_PHYSICAL_ADDRESS    ImageBase;
+  EFI_PHYSICAL_ADDRESS    PayloadBaseAddress;
+  UINT64                  PayloadSize;
+  UINTN                   PayloadEntryOffset;
+  UINTN                   PayloadEntrySize;
+  EFI_PHYSICAL_ADDRESS    PayloadEntryPoint;
+  UINTN                   RelocateTableOffset;
+  UINTN                   RelocateTableCount;
+  EFI_PHYSICAL_ADDRESS    PayloadLoadAddress;
+} FIT_IMAGE_CONTEXT;
+
+typedef struct {
+  UINT8     *Name;
+  UINT32    Offset;
+} PROPERTY_DATA;
+
+#define IMAGE_BASE_OFFSET             OFFSET_OF (FIT_IMAGE_CONTEXT, ImageBase)
+#define PAYLOAD_BASE_ADDR_OFFSET      OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadBaseAddress)
+#define PAYLOAD_BASE_SIZE_OFFSET      OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadSize)
+#define PAYLOAD_ENTRY_OFFSET_OFFSET   OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntryOffset)
+#define PAYLOAD_ENTRY_SIZE_OFFSET     OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntrySize)
+#define PAYLOAD_ENTRY_POINT_OFFSET    OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntryPoint)
+#define RELOCATE_TABLE_OFFSET_OFFSET  OFFSET_OF (FIT_IMAGE_CONTEXT, RelocateTableOffset)
+#define RELOCATE_TABLE_COUNT_OFFSET   OFFSET_OF (FIT_IMAGE_CONTEXT, RelocateTableCount)
+#define PAYLOAD_LOAD_ADDR_OFFSET      OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadLoadAddress)
+
+/**
+  Parse the FIT image info.
+  @param[in]  ImageBase      Memory address of an image.
+  @param[out] Context        The FIT image context pointer.
+  @retval EFI_UNSUPPORTED         Unsupported binary type.
+  @retval EFI_SUCCESS             FIT binary is loaded successfully.
+**/
+EFI_STATUS
+EFIAPI
+ParseFitImage (
+  IN   VOID               *ImageBase,
+  OUT  FIT_IMAGE_CONTEXT  *Context
+  );
+
+#endif
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c b/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
new file mode 100644
index 0000000000..9d1d8a4f61
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
@@ -0,0 +1,127 @@
+/** @file
+  FIT Load Image Support
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "FitLib.h"
+
+PROPERTY_DATA  PropertyData32List[] = {
+  { "data-offset", PAYLOAD_ENTRY_OFFSET_OFFSET  },
+  { "data-size",   PAYLOAD_ENTRY_SIZE_OFFSET    },
+  { "reloc-start", RELOCATE_TABLE_OFFSET_OFFSET }
+};
+
+PROPERTY_DATA  PropertyData64List[] = {
+  { "entry-start", PAYLOAD_ENTRY_POINT_OFFSET },
+  { "load",        PAYLOAD_LOAD_ADDR_OFFSET   }
+};
+
+/**
+  Parse the target firmware image info in FIT.
+  @param[in]  Fdt            Memory address of a fdt.
+  @param[in]  Firmware       Target name of an image.
+  @param[out] Context        The FIT image context pointer.
+  @retval EFI_NOT_FOUND      FIT node dose not find.
+  @retval EFI_SUCCESS        FIT binary is loaded successfully.
+**/
+EFI_STATUS
+EFIAPI
+FitParseFirmwarePropertyData (
+  IN   VOID               *Fdt,
+  IN   CHAR8              *Firmware,
+  OUT  FIT_IMAGE_CONTEXT  *Context
+  )
+{
+  CONST FDT_PROPERTY  *PropertyPtr;
+  INT32               ImageNode;
+  INT32               TianoNode;
+  INT32               TempLen;
+  UINT32              *Data32;
+  UINT64              *Data64;
+  UINT32              *ContextOffset32;
+  UINT64              *ContextOffset64;
+  INT32               Index;
+
+  ImageNode = FdtSubnodeOffsetNameLen (Fdt, 0, "images", (INT32)AsciiStrLen ("images"));
+  if (ImageNode <= 0) {
+    return EFI_NOT_FOUND;
+  }
+
+  TianoNode = FdtSubnodeOffsetNameLen (Fdt, ImageNode, Firmware, (INT32)AsciiStrLen (Firmware));
+  if (TianoNode <= 0) {
+    return EFI_NOT_FOUND;
+  }
+
+  for (Index = 0; Index < sizeof (PropertyData32List) / sizeof (PROPERTY_DATA); Index++) {
+    PropertyPtr      = FdtGetProperty (Fdt, TianoNode, PropertyData32List[Index].Name, &TempLen);
+    Data32           = (UINT32 *)(PropertyPtr->Data);
+    ContextOffset32  = (UINT32 *)((UINTN)Context + PropertyData32List[Index].Offset);
+    *ContextOffset32 = Fdt32ToCpu (*Data32);
+  }
+
+  for (Index = 0; Index < sizeof (PropertyData64List)/sizeof (PROPERTY_DATA); Index++) {
+    PropertyPtr      = FdtGetProperty (Fdt, TianoNode, PropertyData64List[Index].Name, &TempLen);
+    Data64           = (UINT64 *)(PropertyPtr->Data);
+    ContextOffset64  = (UINT64 *)((UINTN)Context + PropertyData64List[Index].Offset);
+    *ContextOffset64 = Fdt64ToCpu (*Data64);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Parse the FIT image info.
+  @param[in]  ImageBase      Memory address of an image.
+  @param[out] Context        The FIT image context pointer.
+  @retval EFI_UNSUPPORTED         Unsupported binary type.
+  @retval EFI_SUCCESS             FIT binary is loaded successfully.
+**/
+EFI_STATUS
+EFIAPI
+ParseFitImage (
+  IN   VOID               *ImageBase,
+  OUT  FIT_IMAGE_CONTEXT  *Context
+  )
+{
+  VOID                *Fdt;
+  INT32               ConfigNode;
+  INT32               Config1Node;
+  CONST FDT_PROPERTY  *PropertyPtr;
+  INT32               TempLen;
+  UINT32              *Data32;
+  UINT64              Value;
+  EFI_STATUS          Status;
+  UINTN               UplSize;
+  CHAR8               *Firmware;
+
+  Status = FdtCheckHeader (ImageBase);
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Fdt         = ImageBase;
+  PropertyPtr = FdtGetProperty (Fdt, 0, "size", &TempLen);
+  Data32      = (UINT32 *)(PropertyPtr->Data);
+  UplSize     = Value = Fdt32ToCpu (*Data32);
+  ConfigNode  = FdtSubnodeOffsetNameLen (Fdt, 0, "configurations", (INT32)AsciiStrLen ("configurations"));
+  if (ConfigNode <= 0) {
+    return EFI_NOT_FOUND;
+  }
+
+  Config1Node = FdtSubnodeOffsetNameLen (Fdt, ConfigNode, "conf-1", (INT32)AsciiStrLen ("conf-1"));
+  if (Config1Node <= 0) {
+    return EFI_NOT_FOUND;
+  }
+
+  PropertyPtr = FdtGetProperty (Fdt, Config1Node, "firmware", &TempLen);
+  Firmware    = (CHAR8 *)(PropertyPtr->Data);
+
+  FitParseFirmwarePropertyData (Fdt, Firmware, Context);
+
+  Context->ImageBase          = (EFI_PHYSICAL_ADDRESS)ImageBase;
+  Context->PayloadSize        = UplSize;
+  Context->RelocateTableCount = (Context->PayloadEntrySize - (Context->RelocateTableOffset - Context->PayloadEntryOffset)) / sizeof (FIT_RELOCATE_ITEM);
+
+  return EFI_SUCCESS;
+}
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
new file mode 100644
index 0000000000..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..ad04ad7eb9
--- /dev/null
+++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
@@ -0,0 +1,654 @@
+/** @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,
+      DataOffset
+      ));
+    Depth  = FdtNodeDepth (Fdt, FvNode);
+    FvNode = FdtNextNode (Fdt, FvNode, &Depth);
+    Fvname = FdtGetName (Fdt, FvNode, &TempLen);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  It will build HOBs based on information from bootloaders.
+  @param[in]  BootloaderParameter   The starting memory address of bootloader parameter block.
+  @param[out] DxeFv                 The pointer to the DXE FV in memory.
+  @retval EFI_SUCCESS        If it completed successfully.
+  @retval Others             If it failed to build required HOBs.
+**/
+EFI_STATUS
+BuildHobs (
+  IN  UINTN                       BootloaderParameter,
+  OUT EFI_FIRMWARE_VOLUME_HEADER  **DxeFv
+  )
+{
+  EFI_PEI_HOB_POINTERS          Hob;
+  UINTN                         MinimalNeededSize;
+  EFI_PHYSICAL_ADDRESS          FreeMemoryBottom;
+  EFI_PHYSICAL_ADDRESS          FreeMemoryTop;
+  EFI_PHYSICAL_ADDRESS          MemoryBottom;
+  EFI_PHYSICAL_ADDRESS          MemoryTop;
+  EFI_HOB_RESOURCE_DESCRIPTOR   *PhitResourceHob;
+  EFI_HOB_RESOURCE_DESCRIPTOR   *ResourceHob;
+  UINT8                         *GuidHob;
+  EFI_HOB_FIRMWARE_VOLUME       *FvHob;
+  UNIVERSAL_PAYLOAD_ACPI_TABLE  *AcpiTable;
+  ACPI_BOARD_INFO               *AcpiBoardInfo;
+  EFI_HOB_HANDOFF_INFO_TABLE    *HobInfo;
+
+  Hob.Raw           = (UINT8 *)BootloaderParameter;
+  MinimalNeededSize = FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
+
+  ASSERT (Hob.Raw != NULL);
+  ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryTop == Hob.HandoffInformationTable->EfiFreeMemoryTop);
+  ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryTop == Hob.HandoffInformationTable->EfiMemoryTop);
+  ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryBottom == Hob.HandoffInformationTable->EfiFreeMemoryBottom);
+  ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryBottom == Hob.HandoffInformationTable->EfiMemoryBottom);
+
+  //
+  // Try to find Resource Descriptor HOB that contains Hob range EfiMemoryBottom..EfiMemoryTop
+  //
+  PhitResourceHob = FindResourceDescriptorByRange (Hob.Raw, Hob.HandoffInformationTable->EfiMemoryBottom, Hob.HandoffInformationTable->EfiMemoryTop);
+  if (PhitResourceHob == NULL) {
+    //
+    // Boot loader's Phit Hob is not in an available Resource Descriptor, find another Resource Descriptor for new Phit Hob
+    //
+    ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, MinimalNeededSize, NULL);
+    if (ResourceHob == NULL) {
+      return EFI_NOT_FOUND;
+    }
+
+    MemoryBottom     = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize;
+    FreeMemoryBottom = MemoryBottom;
+    FreeMemoryTop    = ResourceHob->PhysicalStart + ResourceHob->ResourceLength;
+    MemoryTop        = FreeMemoryTop;
+  } else if (PhitResourceHob->PhysicalStart + PhitResourceHob->ResourceLength - Hob.HandoffInformationTable->EfiMemoryTop >= MinimalNeededSize) {
+    //
+    // New availiable Memory range in new hob is right above memory top in old hob.
+    //
+    MemoryBottom     = Hob.HandoffInformationTable->EfiFreeMemoryTop;
+    FreeMemoryBottom = Hob.HandoffInformationTable->EfiMemoryTop;
+    FreeMemoryTop    = FreeMemoryBottom + MinimalNeededSize;
+    MemoryTop        = FreeMemoryTop;
+  } else if (Hob.HandoffInformationTable->EfiMemoryBottom - PhitResourceHob->PhysicalStart >= MinimalNeededSize) {
+    //
+    // New availiable Memory range in new hob is right below memory bottom in old hob.
+    //
+    MemoryBottom     = Hob.HandoffInformationTable->EfiMemoryBottom - MinimalNeededSize;
+    FreeMemoryBottom = MemoryBottom;
+    FreeMemoryTop    = Hob.HandoffInformationTable->EfiMemoryBottom;
+    MemoryTop        = Hob.HandoffInformationTable->EfiMemoryTop;
+  } else {
+    //
+    // In the Resource Descriptor HOB contains boot loader Hob, there is no enough free memory size for payload hob
+    // Find another Resource Descriptor Hob
+    //
+    ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, MinimalNeededSize, PhitResourceHob);
+    if (ResourceHob == NULL) {
+      return EFI_NOT_FOUND;
+    }
+
+    MemoryBottom     = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize;
+    FreeMemoryBottom = MemoryBottom;
+    FreeMemoryTop    = ResourceHob->PhysicalStart + ResourceHob->ResourceLength;
+    MemoryTop        = FreeMemoryTop;
+  }
+
+  HobInfo           = HobConstructor ((VOID *)(UINTN)MemoryBottom, (VOID *)(UINTN)MemoryTop, (VOID *)(UINTN)FreeMemoryBottom, (VOID *)(UINTN)FreeMemoryTop);
+  HobInfo->BootMode = Hob.HandoffInformationTable->BootMode;
+  //
+  // From now on, mHobList will point to the new Hob range.
+  //
+
+  //
+  // Create an empty FvHob for the DXE FV that contains DXE core.
+  //
+  BuildFvHob ((EFI_PHYSICAL_ADDRESS)0, 0);
+  //
+  // Since payload created new Hob, move all hobs except PHIT from boot loader hob list.
+  //
+  while (!END_OF_HOB_LIST (Hob)) {
+    if (IsHobNeed (Hob)) {
+      // Add this hob to payload HOB
+      AddNewHob (&Hob);
+    }
+
+    Hob.Raw = GET_NEXT_HOB (Hob);
+  }
+
+  BuildFitLoadablesFvHob (DxeFv);
+
+  //
+  // Create guid hob for acpi board information
+  //
+  GuidHob = GetFirstGuidHob (&gUniversalPayloadAcpiTableGuid);
+  if (GuidHob != NULL) {
+    AcpiTable = (UNIVERSAL_PAYLOAD_ACPI_TABLE *)GET_GUID_HOB_DATA (GuidHob);
+    GuidHob   = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid);
+    if (GuidHob == NULL) {
+      AcpiBoardInfo = BuildHobFromAcpi ((UINT64)AcpiTable->Rsdp);
+      ASSERT (AcpiBoardInfo != NULL);
+    }
+  }
+
+  //
+  // Update DXE FV information to first fv hob in the hob list, which
+  // is the empty FvHob created before.
+  //
+  FvHob              = GetFirstHob (EFI_HOB_TYPE_FV);
+  FvHob->BaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)*DxeFv;
+  FvHob->Length      = (*DxeFv)->FvLength;
+  return EFI_SUCCESS;
+}
+
+/**
+  Entry point to the C language phase of UEFI payload.
+  @param[in]   BootloaderParameter    The starting address of bootloader parameter block.
+  @retval      It will not return if SUCCESS, and return error when passing bootloader parameter.
+**/
+EFI_STATUS
+EFIAPI
+_ModuleEntryPoint (
+  IN UINTN  BootloaderParameter
+  )
+{
+  EFI_STATUS                  Status;
+  PHYSICAL_ADDRESS            DxeCoreEntryPoint;
+  EFI_PEI_HOB_POINTERS        Hob;
+  EFI_FIRMWARE_VOLUME_HEADER  *DxeFv;
+
+  mHobList = (VOID *)BootloaderParameter;
+  DxeFv    = NULL;
+  // Call constructor for all libraries
+  ProcessLibraryConstructorList ();
+
+  DEBUG ((DEBUG_INFO, "Entering Universal Payload...\n"));
+  DEBUG ((DEBUG_INFO, "sizeof(UINTN) = 0x%x\n", sizeof (UINTN)));
+
+  DEBUG_CODE (
+    //
+    // Dump the Hobs from boot loader
+    //
+    PrintHob (mHobList);
+    );
+
+  // Initialize floating point operating environment to be compliant with UEFI spec.
+  InitializeFloatingPointUnits ();
+
+  // Build HOB based on information from Bootloader
+  Status = BuildHobs (BootloaderParameter, &DxeFv);
+  ASSERT_EFI_ERROR (Status);
+
+  FixUpPcdDatabase (DxeFv);
+  Status = UniversalLoadDxeCore (DxeFv, &DxeCoreEntryPoint);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Mask off all legacy 8259 interrupt sources
+  //
+  IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF);
+  IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF);
+
+  Hob.HandoffInformationTable = (EFI_HOB_HANDOFF_INFO_TABLE *)GetFirstHob (EFI_HOB_TYPE_HANDOFF);
+  HandOffToDxeCore (DxeCoreEntryPoint, Hob);
+
+  // Should not get here
+  CpuDeadLoop ();
+  return EFI_SUCCESS;
+}
diff --git a/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
new file mode 100644
index 0000000000..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..9a83fc9e44 100644
--- a/UefiPayloadPkg/UniversalPayloadBuild.py
+++ b/UefiPayloadPkg/UniversalPayloadBuild.py
@@ -10,10 +10,22 @@ import subprocess
 import os
 import shutil
 import sys
+import pathlib
 from   ctypes import *
-from Tools.ElfFv import ReplaceFv
+
 sys.dont_write_bytecode = True
 
+class bcolors:
+    HEADER = '\033[95m'
+    OKBLUE = '\033[94m'
+    OKCYAN = '\033[96m'
+    OKGREEN = '\033[92m'
+    WARNING = '\033[93m'
+    FAIL = '\033[91m'
+    ENDC = '\033[0m'
+    BOLD = '\033[1m'
+    UNDERLINE = '\033[4m'
+
 class UPLD_INFO_HEADER(LittleEndianStructure):
     _pack_ = 1
     _fields_ = [
@@ -36,40 +48,114 @@ class UPLD_INFO_HEADER(LittleEndianStructure):
         self.ImageId        = b'UEFI'
         self.ProducerId     = b'INTEL'
 
-def BuildUniversalPayload(Args):
-    def RunCommand(cmd):
-        print(cmd)
-        p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,cwd=os.environ['WORKSPACE'])
-        while True:
-            line = p.stdout.readline()
-            if not line:
-                break
-            print(line.strip().decode(errors='ignore'))
-
-        p.communicate()
-        if p.returncode != 0:
-            print("- Failed - error happened when run command: %s"%cmd)
-            raise Exception("ERROR: when run command: %s"%cmd)
+def ValidateSpecRevision (Argument):
+    try:
+        (MajorStr, MinorStr) = Argument.split('.')
+    except:
+        raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
+    #
+    # Spec Revision Bits 15 : 8 - Major Version. Bits 7 : 0 - Minor Version.
+    #
+    if len(MinorStr) > 0 and len(MinorStr) < 3:
+        try:
+            Minor = int(MinorStr, 16) if len(MinorStr) == 2 else (int(MinorStr, 16) << 4)
+        except:
+            raise argparse.ArgumentTypeError ('{} Minor version of SpecRevision is not a valid integer value.'.format (Argument))
+    else:
+        raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
+
+    if len(MajorStr) > 0 and len(MajorStr) < 3:
+        try:
+            Major = int(MajorStr, 16)
+        except:
+            raise argparse.ArgumentTypeError ('{} Major version of SpecRevision is not a valid integer value.'.format (Argument))
+    else:
+        raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
+
+    return int('0x{0:02x}{1:02x}'.format(Major, Minor), 0)
+
+def Validate32BitInteger (Argument):
+    try:
+        Value = int (Argument, 0)
+    except:
+        raise argparse.ArgumentTypeError ('{} is not a valid integer value.'.format (Argument))
+    if Value < 0:
+        raise argparse.ArgumentTypeError ('{} is a negative value.'.format (Argument))
+    if Value > 0xffffffff:
+        raise argparse.ArgumentTypeError ('{} is larger than 32-bits.'.format (Argument))
+    return Value
 
+def ValidateAddFv (Argument):
+    Value = Argument.split ("=")
+    if len (Value) != 2:
+        raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
+    if Value[0][-3:] != "_fv":
+        raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
+    if Value[1][-3:].lower () != ".fv":
+        raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
+    if os.path.exists (Value[1]) == False:
+        raise argparse.ArgumentTypeError ('File {} is not found.'.format (Value[1]))
+    return Value
+
+def RunCommand(cmd):
+    print(cmd)
+    p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,cwd=os.environ['WORKSPACE'])
+    while True:
+        line = p.stdout.readline()
+        if not line:
+            break
+        print(line.strip().decode(errors='ignore'))
+
+    p.communicate()
+    if p.returncode != 0:
+        print("- Failed - error happened when run command: %s"%cmd)
+        raise Exception("ERROR: when run command: %s"%cmd)
+
+def BuildUniversalPayload(Args):
     BuildTarget = Args.Target
     ToolChain = Args.ToolChain
     Quiet     = "--quiet"  if Args.Quiet else ""
-    ElfToolChain = 'CLANGDWARF'
-    BuildDir     = os.path.join(os.environ['WORKSPACE'], os.path.normpath("Build/UefiPayloadPkgX64"))
-    BuildModule = ""
-    BuildArch = ""
 
+    if Args.Fit == True:
+        PayloadEntryToolChain = ToolChain
+        Args.Macro.append("UNIVERSAL_PAYLOAD_FORMAT=FIT")
+        UpldEntryFile = "FitUniversalPayloadEntry"
+    else:
+        PayloadEntryToolChain = 'CLANGDWARF'
+        Args.Macro.append("UNIVERSAL_PAYLOAD_FORMAT=ELF")
+        UpldEntryFile = "UniversalPayloadEntry"
+
+    BuildDir     = os.path.join(os.environ['WORKSPACE'], os.path.normpath("Build/UefiPayloadPkgX64"))
     if Args.Arch == 'X64':
         BuildArch      = "X64"
-        EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ElfToolChain), os.path.normpath("X64/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll"))
+        FitArch        = "x86_64"
+        ObjCopyFlag    = "elf64-x86-64"
+        EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, PayloadEntryToolChain), os.path.normpath("X64/UefiPayloadPkg/UefiPayloadEntry/{}/DEBUG/{}.dll".format (UpldEntryFile, UpldEntryFile)))
     else:
         BuildArch      = "IA32 -a X64"
-        EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ElfToolChain), os.path.normpath("IA32/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll"))
+        FitArch        = "x86"
+        ObjCopyFlag    = "elf32-i386"
+        EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, PayloadEntryToolChain), os.path.normpath("IA32/UefiPayloadPkg/UefiPayloadEntry/{}/DEBUG/{}.dll".format (UpldEntryFile, UpldEntryFile)))
 
+    EntryModuleInf = os.path.normpath("UefiPayloadPkg/UefiPayloadEntry/{}.inf".format (UpldEntryFile))
     DscPath = os.path.normpath("UefiPayloadPkg/UefiPayloadPkg.dsc")
+    DxeFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv"))
+    BdsFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv"))
+    NetworkFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv"))
+    PayloadReportPath = os.path.join(BuildDir, "UefiUniversalPayload.txt")
     ModuleReportPath = os.path.join(BuildDir, "UefiUniversalPayloadEntry.txt")
     UpldInfoFile = os.path.join(BuildDir, "UniversalPayloadInfo.bin")
 
+    if "CLANG_BIN" in os.environ:
+        LlvmObjcopyPath = os.path.join(os.environ["CLANG_BIN"], "llvm-objcopy")
+    else:
+        LlvmObjcopyPath = "llvm-objcopy"
+    try:
+        RunCommand('"%s" --version'%LlvmObjcopyPath)
+    except:
+        print("- Failed - Please check if LLVM is installed or if CLANG_BIN is set correctly")
+        sys.exit(1)
+
     Pcds = ""
     if (Args.pcd != None):
         for PcdItem in Args.pcd:
@@ -84,7 +170,6 @@ def BuildUniversalPayload(Args):
     # Building DXE core and DXE drivers as DXEFV.
     #
     if Args.BuildEntryOnly == False:
-        PayloadReportPath = os.path.join(BuildDir, "UefiUniversalPayload.txt")
         BuildPayload = "build -p {} -b {} -a X64 -t {} -y {} {}".format (DscPath, BuildTarget, ToolChain, PayloadReportPath, Quiet)
         BuildPayload += Pcds
         BuildPayload += Defines
@@ -93,94 +178,138 @@ def BuildUniversalPayload(Args):
     # Building Universal Payload entry.
     #
     if Args.PreBuildUplBinary is None:
-        EntryModuleInf = os.path.normpath("UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf")
-        BuildModule = "build -p {} -b {} -a {} -m {} -t {} -y {} {}".format (DscPath, BuildTarget, BuildArch, EntryModuleInf, ElfToolChain, ModuleReportPath, Quiet)
+        BuildModule = "build -p {} -b {} -a {} -m {} -t {} -y {} {}".format (DscPath, BuildTarget, BuildArch, EntryModuleInf, PayloadEntryToolChain, ModuleReportPath, Quiet)
         BuildModule += Pcds
         BuildModule += Defines
         RunCommand(BuildModule)
 
     if Args.PreBuildUplBinary is not None:
-        EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.elf")
+        if Args.Fit == False:
+            EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.elf")
+        else:
+            EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.fit")
         shutil.copy (os.path.abspath(Args.PreBuildUplBinary), EntryOutputDir)
 
     #
-    # Buid Universal Payload Information Section ".upld_info"
+    # Build Universal Payload Information Section ".upld_info"
     #
-    upld_info_hdr              = UPLD_INFO_HEADER()
-    upld_info_hdr.SpecRevision = Args.SpecRevision
-    upld_info_hdr.Revision     = Args.Revision
-    upld_info_hdr.ProducerId   = Args.ProducerId.encode()[:16]
-    upld_info_hdr.ImageId      = Args.ImageId.encode()[:16]
-    upld_info_hdr.Attribute   |= 1 if BuildTarget == "DEBUG" else 0
-    fp = open(UpldInfoFile, 'wb')
-    fp.write(bytearray(upld_info_hdr))
-    fp.close()
+    if Args.Fit == False:
+        upld_info_hdr = UPLD_INFO_HEADER()
+        upld_info_hdr.SpecRevision = Args.SpecRevision
+        upld_info_hdr.Revision = Args.Revision
+        upld_info_hdr.ProducerId = Args.ProducerId.encode()[:16]
+        upld_info_hdr.ImageId = Args.ImageId.encode()[:16]
+        upld_info_hdr.Attribute |= 1 if BuildTarget == "DEBUG" else 0
+        fp = open(UpldInfoFile, 'wb')
+        fp.write(bytearray(upld_info_hdr))
+        fp.close()
+
+        if Args.BuildEntryOnly == False:
+            import Tools.ElfFv as ElfFv
+            ElfFv.ReplaceFv (EntryOutputDir, UpldInfoFile, '.upld_info', Alignment = 4)
+    if Args.Fit == False:
+        shutil.copy (EntryOutputDir, os.path.join(BuildDir, 'UniversalPayload.elf'))
+    else:
+        shutil.copy (EntryOutputDir, os.path.join(BuildDir, 'UniversalPayload.fit'))
 
     MultiFvList = []
     if Args.BuildEntryOnly == False:
         MultiFvList = [
-            ['uefi_fv',    os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv"))    ],
-            ['bds_fv',     os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv"))    ],
-            ['network_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv"))    ],
+            ['uefi_fv',        os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv"))    ],
+            ['bds_fv',         os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv"))    ],
+            ['network_fv',     os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv"))],
         ]
-        AddSectionName = '.upld_info'
-        ReplaceFv (EntryOutputDir, UpldInfoFile, AddSectionName, Alignment = 4)
 
-    if Args.PreBuildUplBinary is None:
-        shutil.copy (EntryOutputDir, os.path.join(BuildDir, 'UniversalPayload.elf'))
 
-    return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.elf')
+    if Args.Fit == True:
+        import Tools.MkFitImage as MkFitImage
+        import pefile
+        fit_image_info_header               = MkFitImage.FIT_IMAGE_INFO_HEADER()
+        fit_image_info_header.Description   = 'Uefi Universal Payload'
+        fit_image_info_header.UplVersion    = Args.SpecRevision
+        fit_image_info_header.Type          = 'flat-binary'
+        fit_image_info_header.Arch          = FitArch
+        fit_image_info_header.Compression   = 'none'
+        fit_image_info_header.Revision      = Args.Revision
+        fit_image_info_header.BuildType     = Args.Target.lower()
+        fit_image_info_header.Capabilities  = None
+        fit_image_info_header.Producer      = Args.ProducerId.lower()
+        fit_image_info_header.ImageId       = Args.ImageId.lower()
+        fit_image_info_header.Binary        = os.path.join(BuildDir, 'UniversalPayload.fit')
+        fit_image_info_header.TargetPath    = os.path.join(BuildDir, 'UniversalPayload.fit')
+        fit_image_info_header.UefifvPath    = DxeFvOutputDir
+        fit_image_info_header.BdsfvPath     = BdsFvOutputDir
+        fit_image_info_header.NetworkfvPath = NetworkFvOutputDir
+        fit_image_info_header.DataOffset    = 0x1000
+        fit_image_info_header.LoadAddr      = Args.LoadAddress
+        fit_image_info_header.Project       = 'tianocore'
+
+        TargetRebaseFile = fit_image_info_header.Binary.replace (pathlib.Path(fit_image_info_header.Binary).suffix, ".pecoff")
+        TargetRebaseEntryFile = fit_image_info_header.Binary.replace (pathlib.Path(fit_image_info_header.Binary).suffix, ".entry")
+
 
-def main():
-    def ValidateSpecRevision (Argument):
-        try:
-            (MajorStr, MinorStr) = Argument.split('.')
-        except:
-            raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
         #
-        # Spec Revision Bits 15 : 8 - Major Version. Bits 7 : 0 - Minor Version.
+        # Rebase PECOFF to load address
         #
-        if len(MinorStr) > 0 and len(MinorStr) < 3:
-            try:
-                Minor = int(MinorStr, 16) if len(MinorStr) == 2 else (int(MinorStr, 16) << 4)
-            except:
-                raise argparse.ArgumentTypeError ('{} Minor version of SpecRevision is not a valid integer value.'.format (Argument))
-        else:
-            raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
+        RunCommand (
+            "GenFw -e SEC -o {} {}".format (
+              TargetRebaseFile,
+              fit_image_info_header.Binary
+            ))
+        RunCommand (
+            "GenFw --rebase 0x{:02X} -o {} {} ".format (
+              fit_image_info_header.LoadAddr + fit_image_info_header.DataOffset,
+              TargetRebaseFile,
+              TargetRebaseFile,
+            ))
 
-        if len(MajorStr) > 0 and len(MajorStr) < 3:
-            try:
-                Major = int(MajorStr, 16)
-            except:
-                raise argparse.ArgumentTypeError ('{} Major version of SpecRevision is not a valid integer value.'.format (Argument))
-        else:
-            raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
+        #
+        # Open PECOFF relocation table binary.
+        #
+        RelocBinary     = b''
+        PeCoff = pefile.PE (TargetRebaseFile)
+        for reloc in PeCoff.DIRECTORY_ENTRY_BASERELOC:
+            for entry in reloc.entries:
+                if (entry.type == 0):
+                    continue
+                Type = entry.type
+                Offset = entry.rva + fit_image_info_header.DataOffset
+                RelocBinary += Type.to_bytes (8, 'little') + Offset.to_bytes (8, 'little')
+        RelocBinary += b'\x00' * (0x1000 - (len(RelocBinary) % 0x1000))
 
-        return int('0x{0:02x}{1:02x}'.format(Major, Minor), 0)
+        #
+        # Output UniversalPayload.entry
+        #
+        TempBinary = open (TargetRebaseFile, 'rb')
+        TianoBinary = TempBinary.read ()
+        TempBinary.close ()
 
-    def Validate32BitInteger (Argument):
-        try:
-            Value = int (Argument, 0)
-        except:
-            raise argparse.ArgumentTypeError ('{} is not a valid integer value.'.format (Argument))
-        if Value < 0:
-            raise argparse.ArgumentTypeError ('{} is a negative value.'.format (Argument))
-        if Value > 0xffffffff:
-            raise argparse.ArgumentTypeError ('{} is larger than 32-bits.'.format (Argument))
-        return Value
-
-    def ValidateAddFv (Argument):
-        Value = Argument.split ("=")
-        if len (Value) != 2:
-            raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
-        if Value[0][-3:] != "_fv":
-            raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
-        if Value[1][-3:].lower () != ".fv":
-            raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
-        if os.path.exists (Value[1]) == False:
-            raise argparse.ArgumentTypeError ('File {} is not found.'.format (Value[1]))
-        return Value
+        TianoEntryBinary = TianoBinary + RelocBinary
+        TianoEntryBinary += (b'\x00' * (0x1000 - (len(TianoBinary) % 0x1000)))
+        TianoEntryBinarySize = len (TianoEntryBinary)
+
+        TempBinary = open(TargetRebaseEntryFile, "wb")
+        TempBinary.truncate()
+        TempBinary.write(TianoEntryBinary)
+        TempBinary.close()
+
+        #
+        # Calculate entry and update relocation table start address and data-size.
+        #
+        fit_image_info_header.Entry      = PeCoff.OPTIONAL_HEADER.ImageBase + PeCoff.OPTIONAL_HEADER.AddressOfEntryPoint
+        fit_image_info_header.RelocStart = fit_image_info_header.DataOffset + len(TianoBinary)
+        fit_image_info_header.DataSize   = TianoEntryBinarySize
+        fit_image_info_header.Binary     = TargetRebaseEntryFile
+
+        if MkFitImage.MakeFitImage(fit_image_info_header) is True:
+            print('\nSuccessfully build Fit Image')
+        else:
+            sys.exit(1)
+        return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.fit')
+    else:
+        return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.elf')
 
+def main():
     parser = argparse.ArgumentParser(description='For building Universal Payload')
     parser.add_argument('-t', '--ToolChain')
     parser.add_argument('-b', '--Target', default='DEBUG')
@@ -192,13 +321,16 @@ def main():
     parser.add_argument("-s", "--SpecRevision", type=ValidateSpecRevision, default ='0.7', help='Indicates compliance with a revision of this specification in the BCD format.')
     parser.add_argument("-r", "--Revision", type=Validate32BitInteger, default ='0x0000010105', help='Revision of the Payload binary. Major.Minor.Revision.Build')
     parser.add_argument("-o", "--ProducerId", default ='INTEL', help='A null-terminated OEM-supplied string that identifies the payload producer (16 bytes maximal).')
+    parser.add_argument("-e", "--BuildEntryOnly", action='store_true', help='Build UniversalPayload Entry file')
+    parser.add_argument("-pb", "--PreBuildUplBinary", default=None, help='Specify the UniversalPayload file')
     parser.add_argument("-sk", "--SkipBuild", action='store_true', help='Skip UniversalPayload build')
     parser.add_argument("-af", "--AddFv", type=ValidateAddFv, action='append', help='Add or replace specific FV into payload, Ex: uefi_fv=XXX.fv')
-    command_group = parser.add_mutually_exclusive_group()
-    command_group.add_argument("-e", "--BuildEntryOnly", action='store_true', help='Build UniversalPayload Entry file')
-    command_group.add_argument("-pb", "--PreBuildUplBinary", default=None, help='Specify the UniversalPayload file')
+    parser.add_argument("-f", "--Fit", action='store_true', help='Build UniversalPayload file as UniversalPayload.fit', default=False)
+    parser.add_argument('-l', "--LoadAddress", type=int, help='Specify payload load address', default =0x000800000)
+
     args = parser.parse_args()
 
+
     MultiFvList = []
     UniversalPayloadBinary = args.PreBuildUplBinary
     if (args.SkipBuild == False):
@@ -208,12 +340,24 @@ def main():
         for (SectionName, SectionFvFile) in args.AddFv:
             MultiFvList.append ([SectionName, SectionFvFile])
 
+    def ReplaceFv (UplBinary, SectionFvFile, SectionName):
+        print (bcolors.OKGREEN + "Patch {}={} into {}".format (SectionName, SectionFvFile, UplBinary) + bcolors.ENDC)
+        if (args.Fit == False):
+            import Tools.ElfFv as ElfFv
+            return ElfFv.ReplaceFv (UplBinary, SectionFvFile, '.upld.{}'.format (SectionName))
+        else:
+            import Tools.MkFitImage as MkFitImage
+            return MkFitImage.ReplaceFv (UplBinary, SectionFvFile, SectionName)
+
     if (UniversalPayloadBinary != None):
         for (SectionName, SectionFvFile) in MultiFvList:
             if os.path.exists (SectionFvFile) == False:
                 continue
-            print ("Patch {}={} into {}".format (SectionName, SectionFvFile, UniversalPayloadBinary))
-            ReplaceFv (UniversalPayloadBinary, SectionFvFile, '.upld.{}'.format (SectionName))
+
+            status = ReplaceFv (UniversalPayloadBinary, SectionFvFile, SectionName.replace ("_", "-"))
+            if status != 0:
+                print (bcolors.FAIL + "[Fail] Patch {}={}".format (SectionName, SectionFvFile) + bcolors.ENDC)
+                return status
 
     print ("\nSuccessfully build Universal Payload")
 
-- 
2.39.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#108787): https://edk2.groups.io/g/devel/message/108787
Mute This Topic: https://groups.io/mt/101435616/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] 6+ messages in thread

* [edk2-devel] [PATCH v4 2/4] UefiCpuPkg/ResetVector: Remove AP waking vector from ResetVector
  2023-09-18  6:42 [edk2-devel] [PATCH v4 0/4] " brucex.wang
@ 2023-09-18  6:42 ` brucex.wang
  0 siblings, 0 replies; 6+ messages in thread
From: brucex.wang @ 2023-09-18  6:42 UTC (permalink / raw)
  To: devel
  Cc: brucex.wang, Zhiguang Liu, Eric Dong, Ray Ni, Rahul Kumar,
	Gerd Hoffmann

From: Zhiguang Liu <zhiguang.liu@intel.com>

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4494

Current reset vector uses 0xffffffe0 as AP waking vector, and expects
GenFv generates code aligned on a 4k boundary which will jump to this
location. However, some issues are listed below
1. GenFV doesn't generate code as the comment expects, because GenFv
assumes no modifications are required to the VTF-0 'Volume Top File'.
2. Even if removing VFT0 signature and let GenFv to modify, Genfv is
hard-code using another flash address 0xffffffd0.
3. In the same patch series, AP waking vector code is removed from
GenFv, because no such usage anymore. The existing of first two issues
also approve the usage is not available for a long time.

Therefore, remove AP waking vector related code.

Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Signed-off-by: Zhiguang Liu <zhiguang.liu@intel.com>
---
 UefiCpuPkg/ResetVector/Vtf0/Ia16/Init16.asm       |  7 -------
 .../ResetVector/Vtf0/Ia16/ResetVectorVtf0.asm     | 15 +++------------
 2 files changed, 3 insertions(+), 19 deletions(-)

diff --git a/UefiCpuPkg/ResetVector/Vtf0/Ia16/Init16.asm b/UefiCpuPkg/ResetVector/Vtf0/Ia16/Init16.asm
index cbdadee166..02b9a0303c 100644
--- a/UefiCpuPkg/ResetVector/Vtf0/Ia16/Init16.asm
+++ b/UefiCpuPkg/ResetVector/Vtf0/Ia16/Init16.asm
@@ -17,13 +17,6 @@ EarlyBspInitReal16:
     mov     di, 'BP'
     jmp     short Main16
 
-;
-; @param[out] DI    'AP' to indicate application processor
-;
-EarlyApInitReal16:
-    mov     di, 'AP'
-    jmp     short Main16
-
 ;
 ; Modified:  EAX
 ;
diff --git a/UefiCpuPkg/ResetVector/Vtf0/Ia16/ResetVectorVtf0.asm b/UefiCpuPkg/ResetVector/Vtf0/Ia16/ResetVectorVtf0.asm
index fe5bbea803..384b1d4d98 100644
--- a/UefiCpuPkg/ResetVector/Vtf0/Ia16/ResetVectorVtf0.asm
+++ b/UefiCpuPkg/ResetVector/Vtf0/Ia16/ResetVectorVtf0.asm
@@ -32,22 +32,13 @@ ALIGN   16
     TIMES (0x1000 - 0x20) DB 0
 %endif
 
-applicationProcessorEntryPoint:
 ;
-; Application Processors entry point
+; 0xffffffe0
 ;
-; GenFv generates code aligned on a 4k boundary which will jump to this
-; location.  (0xffffffe0)  This allows the Local APIC Startup IPI to be
-; used to wake up the application processors.
-;
-    jmp     EarlyApInitReal16
-
-ALIGN   8
-
-    DD      0
+    DD      0, 0, 0
 
 ;
-; The VTF signature
+; The VTF signature (0xffffffec)
 ;
 ; VTF-0 means that the VTF (Volume Top File) code does not require
 ; any fixups.
-- 
2.39.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#108790): https://edk2.groups.io/g/devel/message/108790
Mute This Topic: https://groups.io/mt/101435618/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] 6+ messages in thread

end of thread, other threads:[~2023-09-18 15:17 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-18  6:37 [edk2-devel] [PATCH v4 0/4] UefiPayloadPkg: Add FIT support brucex.wang
2023-09-18  6:37 ` [edk2-devel] [PATCH v4 1/4] OvmfPkg: Remove applicationProcessorEntryPoint brucex.wang
2023-09-18  6:37 ` [edk2-devel] [PATCH v4 2/4] UefiCpuPkg/ResetVector: Remove AP waking vector from ResetVector brucex.wang
2023-09-18  6:37 ` [edk2-devel] [PATCH v4 3/4] MdePkg/BaseFdtLib: Add Fdt function brucex.wang
2023-09-18  6:37 ` [edk2-devel] [PATCH v4 4/4] UefiPayloadPkg: Add FIT support brucex.wang
  -- strict thread matches above, loose matches on Subject: below --
2023-09-18  6:42 [edk2-devel] [PATCH v4 0/4] " brucex.wang
2023-09-18  6:42 ` [edk2-devel] [PATCH v4 2/4] UefiCpuPkg/ResetVector: Remove AP waking vector from ResetVector brucex.wang

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