* [edk2-devel] [PATCH v2 0/2] UefiPayloadPkg supports Fit
@ 2023-09-15 8:58 brucex.wang
2023-09-15 8:58 ` [edk2-devel] [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function brucex.wang
2023-09-15 8:58 ` [edk2-devel] [PATCH v2 2/2] UefiPayloadPkg: Add FIT support brucex.wang
0 siblings, 2 replies; 10+ messages in thread
From: brucex.wang @ 2023-09-15 8:58 UTC (permalink / raw)
To: devel; +Cc: brucex.wang
From: "Brucex.Wang" <brucex.wang@intel.com>
v2: Add fit support and fix some spelling issues.
Brucex.Wang (2):
MdePkg/BaseFdtLib: Add Fdt function.
UefiPayloadPkg: Add FIT support
MdePkg/Include/Library/FdtLib.h | 34 +
MdePkg/Library/BaseFdtLib/FdtLib.c | 40 ++
.../Include/Guid/UniversalPayloadBase.h | 21 +
UefiPayloadPkg/PayloadLoaderPeim/FitLib.h | 60 ++
.../PayloadLoaderPeim/FitLib/FitLib.c | 127 ++++
.../PayloadLoaderPeim/FitPayloadLoaderPeim.c | 150 ++++
.../FitPayloadLoaderPeim.inf | 59 ++
UefiPayloadPkg/Readme.md | 191 +++++
UefiPayloadPkg/Tools/MkFitImage.py | 272 ++++++++
.../FitUniversalPayloadEntry.c | 654 ++++++++++++++++++
.../FitUniversalPayloadEntry.inf | 98 +++
UefiPayloadPkg/UefiPayloadPkg.dec | 3 +
UefiPayloadPkg/UefiPayloadPkg.dsc | 27 +-
UefiPayloadPkg/UniversalPayloadBuild.py | 328 ++++++---
14 files changed, 1968 insertions(+), 96 deletions(-)
create mode 100644 UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
create mode 100644 UefiPayloadPkg/Readme.md
create mode 100644 UefiPayloadPkg/Tools/MkFitImage.py
create mode 100644 UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
create mode 100644 UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
--
2.39.1.windows.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#108716): https://edk2.groups.io/g/devel/message/108716
Mute This Topic: https://groups.io/mt/101378802/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply [flat|nested] 10+ messages in thread
* [edk2-devel] [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function.
2023-09-15 8:58 [edk2-devel] [PATCH v2 0/2] UefiPayloadPkg supports Fit brucex.wang
@ 2023-09-15 8:58 ` brucex.wang
2023-09-15 9:02 ` Guo, Gua
` (2 more replies)
2023-09-15 8:58 ` [edk2-devel] [PATCH v2 2/2] UefiPayloadPkg: Add FIT support brucex.wang
1 sibling, 3 replies; 10+ messages in thread
From: brucex.wang @ 2023-09-15 8:58 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..2bd926b5b4 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 (#108717): https://edk2.groups.io/g/devel/message/108717
Mute This Topic: https://groups.io/mt/101378804/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] 10+ messages in thread
* [edk2-devel] [PATCH v2 2/2] UefiPayloadPkg: Add FIT support
2023-09-15 8:58 [edk2-devel] [PATCH v2 0/2] UefiPayloadPkg supports Fit brucex.wang
2023-09-15 8:58 ` [edk2-devel] [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function brucex.wang
@ 2023-09-15 8:58 ` brucex.wang
2023-09-15 9:02 ` Guo, Gua
2023-09-15 9:06 ` Lu, James
1 sibling, 2 replies; 10+ messages in thread
From: brucex.wang @ 2023-09-15 8:58 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 | 21 +
UefiPayloadPkg/PayloadLoaderPeim/FitLib.h | 60 ++
.../PayloadLoaderPeim/FitLib/FitLib.c | 127 ++++
.../PayloadLoaderPeim/FitPayloadLoaderPeim.c | 150 ++++
.../FitPayloadLoaderPeim.inf | 59 ++
UefiPayloadPkg/Readme.md | 191 +++++
UefiPayloadPkg/Tools/MkFitImage.py | 272 ++++++++
.../FitUniversalPayloadEntry.c | 654 ++++++++++++++++++
.../FitUniversalPayloadEntry.inf | 98 +++
UefiPayloadPkg/UefiPayloadPkg.dec | 3 +
UefiPayloadPkg/UefiPayloadPkg.dsc | 27 +-
UefiPayloadPkg/UniversalPayloadBuild.py | 328 ++++++---
12 files changed, 1894 insertions(+), 96 deletions(-)
create mode 100644 UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
create mode 100644 UefiPayloadPkg/Readme.md
create mode 100644 UefiPayloadPkg/Tools/MkFitImage.py
create mode 100644 UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
create mode 100644 UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
diff --git a/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
new file mode 100644
index 0000000000..31c9ec0bfb
--- /dev/null
+++ b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
@@ -0,0 +1,21 @@
+/** @file
+ Universal Payload general definitions.
+
+Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Revision Reference:
+ - Universal Payload Specification 0.75 (https://universalpayload.github.io/documentation/)
+**/
+
+#ifndef UNIVERSAL_PAYLOAD_BASE_H_
+#define UNIVERSAL_PAYLOAD_BASE_H_
+
+extern GUID gUniversalPayloadBaseGuid;
+
+typedef struct {
+ UNIVERSAL_PAYLOAD_GENERIC_HEADER Header;
+ EFI_PHYSICAL_ADDRESS Entry;
+} UNIVERSAL_PAYLOAD_BASE;
+
+#endif // UNIVERSAL_PAYLOAD_BASE_H_
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h b/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
new file mode 100644
index 0000000000..0514d675a6
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
@@ -0,0 +1,60 @@
+/** @file
+ FIT Load Image Support
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef FIT_LIB_H_
+#define FIT_LIB_H_
+
+#include <PiPei.h>
+#include <Library/DebugLib.h>
+#include <Library/FdtLib.h>
+
+typedef struct {
+ UINT64 RelocateType;
+ UINT64 Offset;
+} FIT_RELOCATE_ITEM;
+
+typedef struct {
+ EFI_PHYSICAL_ADDRESS ImageBase;
+ EFI_PHYSICAL_ADDRESS PayloadBaseAddress;
+ UINT64 PayloadSize;
+ UINTN PayloadEntryOffset;
+ UINTN PayloadEntrySize;
+ EFI_PHYSICAL_ADDRESS PayloadEntryPoint;
+ UINTN RelocateTableOffset;
+ UINTN RelocateTableCount;
+ EFI_PHYSICAL_ADDRESS PayloadLoadAddress;
+} FIT_IMAGE_CONTEXT;
+
+typedef struct {
+ UINT8 *Name;
+ UINT32 Offset;
+} PROPERTY_DATA;
+
+#define IMAGE_BASE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, ImageBase)
+#define PAYLOAD_BASE_ADDR_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadBaseAddress)
+#define PAYLOAD_BASE_SIZE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadSize)
+#define PAYLOAD_ENTRY_OFFSET_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntryOffset)
+#define PAYLOAD_ENTRY_SIZE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntrySize)
+#define PAYLOAD_ENTRY_POINT_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntryPoint)
+#define RELOCATE_TABLE_OFFSET_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, RelocateTableOffset)
+#define RELOCATE_TABLE_COUNT_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, RelocateTableCount)
+#define PAYLOAD_LOAD_ADDR_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadLoadAddress)
+
+/**
+ Parse the FIT image info.
+ @param[in] ImageBase Memory address of an image.
+ @param[out] Context The FIT image context pointer.
+ @retval EFI_UNSUPPORTED Unsupported binary type.
+ @retval EFI_SUCCESS FIT binary is loaded successfully.
+**/
+EFI_STATUS
+EFIAPI
+ParseFitImage (
+ IN VOID *ImageBase,
+ OUT FIT_IMAGE_CONTEXT *Context
+ );
+
+#endif
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c b/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
new file mode 100644
index 0000000000..9d1d8a4f61
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
@@ -0,0 +1,127 @@
+/** @file
+ FIT Load Image Support
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "FitLib.h"
+
+PROPERTY_DATA PropertyData32List[] = {
+ { "data-offset", PAYLOAD_ENTRY_OFFSET_OFFSET },
+ { "data-size", PAYLOAD_ENTRY_SIZE_OFFSET },
+ { "reloc-start", RELOCATE_TABLE_OFFSET_OFFSET }
+};
+
+PROPERTY_DATA PropertyData64List[] = {
+ { "entry-start", PAYLOAD_ENTRY_POINT_OFFSET },
+ { "load", PAYLOAD_LOAD_ADDR_OFFSET }
+};
+
+/**
+ Parse the target firmware image info in FIT.
+ @param[in] Fdt Memory address of a fdt.
+ @param[in] Firmware Target name of an image.
+ @param[out] Context The FIT image context pointer.
+ @retval EFI_NOT_FOUND FIT node dose not find.
+ @retval EFI_SUCCESS FIT binary is loaded successfully.
+**/
+EFI_STATUS
+EFIAPI
+FitParseFirmwarePropertyData (
+ IN VOID *Fdt,
+ IN CHAR8 *Firmware,
+ OUT FIT_IMAGE_CONTEXT *Context
+ )
+{
+ CONST FDT_PROPERTY *PropertyPtr;
+ INT32 ImageNode;
+ INT32 TianoNode;
+ INT32 TempLen;
+ UINT32 *Data32;
+ UINT64 *Data64;
+ UINT32 *ContextOffset32;
+ UINT64 *ContextOffset64;
+ INT32 Index;
+
+ ImageNode = FdtSubnodeOffsetNameLen (Fdt, 0, "images", (INT32)AsciiStrLen ("images"));
+ if (ImageNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ TianoNode = FdtSubnodeOffsetNameLen (Fdt, ImageNode, Firmware, (INT32)AsciiStrLen (Firmware));
+ if (TianoNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ for (Index = 0; Index < sizeof (PropertyData32List) / sizeof (PROPERTY_DATA); Index++) {
+ PropertyPtr = FdtGetProperty (Fdt, TianoNode, PropertyData32List[Index].Name, &TempLen);
+ Data32 = (UINT32 *)(PropertyPtr->Data);
+ ContextOffset32 = (UINT32 *)((UINTN)Context + PropertyData32List[Index].Offset);
+ *ContextOffset32 = Fdt32ToCpu (*Data32);
+ }
+
+ for (Index = 0; Index < sizeof (PropertyData64List)/sizeof (PROPERTY_DATA); Index++) {
+ PropertyPtr = FdtGetProperty (Fdt, TianoNode, PropertyData64List[Index].Name, &TempLen);
+ Data64 = (UINT64 *)(PropertyPtr->Data);
+ ContextOffset64 = (UINT64 *)((UINTN)Context + PropertyData64List[Index].Offset);
+ *ContextOffset64 = Fdt64ToCpu (*Data64);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Parse the FIT image info.
+ @param[in] ImageBase Memory address of an image.
+ @param[out] Context The FIT image context pointer.
+ @retval EFI_UNSUPPORTED Unsupported binary type.
+ @retval EFI_SUCCESS FIT binary is loaded successfully.
+**/
+EFI_STATUS
+EFIAPI
+ParseFitImage (
+ IN VOID *ImageBase,
+ OUT FIT_IMAGE_CONTEXT *Context
+ )
+{
+ VOID *Fdt;
+ INT32 ConfigNode;
+ INT32 Config1Node;
+ CONST FDT_PROPERTY *PropertyPtr;
+ INT32 TempLen;
+ UINT32 *Data32;
+ UINT64 Value;
+ EFI_STATUS Status;
+ UINTN UplSize;
+ CHAR8 *Firmware;
+
+ Status = FdtCheckHeader (ImageBase);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Fdt = ImageBase;
+ PropertyPtr = FdtGetProperty (Fdt, 0, "size", &TempLen);
+ Data32 = (UINT32 *)(PropertyPtr->Data);
+ UplSize = Value = Fdt32ToCpu (*Data32);
+ ConfigNode = FdtSubnodeOffsetNameLen (Fdt, 0, "configurations", (INT32)AsciiStrLen ("configurations"));
+ if (ConfigNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ Config1Node = FdtSubnodeOffsetNameLen (Fdt, ConfigNode, "conf-1", (INT32)AsciiStrLen ("conf-1"));
+ if (Config1Node <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ PropertyPtr = FdtGetProperty (Fdt, Config1Node, "firmware", &TempLen);
+ Firmware = (CHAR8 *)(PropertyPtr->Data);
+
+ FitParseFirmwarePropertyData (Fdt, Firmware, Context);
+
+ Context->ImageBase = (EFI_PHYSICAL_ADDRESS)ImageBase;
+ Context->PayloadSize = UplSize;
+ Context->RelocateTableCount = (Context->PayloadEntrySize - (Context->RelocateTableOffset - Context->PayloadEntryOffset)) / sizeof (FIT_RELOCATE_ITEM);
+
+ return EFI_SUCCESS;
+}
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
new file mode 100644
index 0000000000..3c5dacbb65
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
@@ -0,0 +1,150 @@
+/** @file
+ ELF Load Image Support
+Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiPei.h>
+#include <UniversalPayload/UniversalPayload.h>
+#include <Guid/UniversalPayloadBase.h>
+#include <UniversalPayload/ExtraData.h>
+
+#include <Ppi/LoadFile.h>
+
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+
+#include "FitLib.h"
+
+/**
+ The wrapper function of PeiLoadImageLoadImage().
+ @param This - Pointer to EFI_PEI_LOAD_FILE_PPI.
+ @param FileHandle - Pointer to the FFS file header of the image.
+ @param ImageAddressArg - Pointer to PE/TE image.
+ @param ImageSizeArg - Size of PE/TE image.
+ @param EntryPoint - Pointer to entry point of specified image file for output.
+ @param AuthenticationState - Pointer to attestation authentication state of image.
+ @return Status of PeiLoadImageLoadImage().
+**/
+EFI_STATUS
+EFIAPI
+PeiLoadFileLoadPayload (
+ IN CONST EFI_PEI_LOAD_FILE_PPI *This,
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL,
+ OUT UINT64 *ImageSizeArg OPTIONAL,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
+ OUT UINT32 *AuthenticationState
+ )
+{
+ EFI_STATUS Status;
+ FIT_IMAGE_CONTEXT Context;
+ UINTN Instance;
+ VOID *Binary;
+ FIT_RELOCATE_ITEM *RelocateTable;
+ UNIVERSAL_PAYLOAD_BASE *PayloadBase;
+ UINTN Length;
+ UINTN Delta;
+ UINTN Index;
+
+ Instance = 0;
+ do {
+ Status = PeiServicesFfsFindSectionData3 (EFI_SECTION_RAW, Instance++, FileHandle, &Binary, AuthenticationState);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ZeroMem (&Context, sizeof (Context));
+ Status = ParseFitImage (Binary, &Context);
+ } while (EFI_ERROR (Status));
+
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "Before Rebase Payload File Base: 0x%08x, File Size: 0x%08X, EntryPoint: 0x%08x\n",
+ Context.PayloadBaseAddress,
+ Context.PayloadSize,
+ Context.PayloadEntryPoint
+ ));
+ Context.PayloadBaseAddress = (EFI_PHYSICAL_ADDRESS)AllocatePages (EFI_SIZE_TO_PAGES (Context.PayloadSize));
+
+ RelocateTable = (FIT_RELOCATE_ITEM *)(UINTN)(Context.PayloadBaseAddress + Context.RelocateTableOffset);
+ CopyMem ((VOID *)Context.PayloadBaseAddress, Binary, Context.PayloadSize);
+
+ if (Context.PayloadBaseAddress > Context.PayloadLoadAddress) {
+ Delta = Context.PayloadBaseAddress - Context.PayloadLoadAddress;
+ Context.PayloadEntryPoint += Delta;
+ for (Index = 0; Index < Context.RelocateTableCount; Index++) {
+ if ((RelocateTable[Index].RelocateType == 10) || (RelocateTable[Index].RelocateType == 3)) {
+ *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) = *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) + Delta;
+ }
+ }
+ } else {
+ Delta = Context.PayloadLoadAddress - Context.PayloadBaseAddress;
+ Context.PayloadEntryPoint -= Delta;
+ for (Index = 0; Index < Context.RelocateTableCount; Index++) {
+ if ((RelocateTable[Index].RelocateType == 10) || (RelocateTable[Index].RelocateType == 3)) {
+ *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) = *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) - Delta;
+ }
+ }
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "After Rebase Payload File Base: 0x%08x, File Size: 0x%08X, EntryPoint: 0x%08x\n",
+ Context.PayloadBaseAddress,
+ Context.PayloadSize,
+ Context.PayloadEntryPoint
+ ));
+
+ Length = sizeof (UNIVERSAL_PAYLOAD_BASE);
+ PayloadBase = BuildGuidHob (
+ &gUniversalPayloadBaseGuid,
+ Length
+ );
+ PayloadBase->Entry = (EFI_PHYSICAL_ADDRESS)Context.ImageBase;
+
+ *ImageAddressArg = Context.PayloadBaseAddress;
+ *ImageSizeArg = Context.PayloadSize;
+ *EntryPoint = Context.PayloadEntryPoint;
+
+ return EFI_SUCCESS;
+}
+
+EFI_PEI_LOAD_FILE_PPI mPeiLoadFilePpi = {
+ PeiLoadFileLoadPayload
+};
+
+EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiLoadFilePpiGuid,
+ &mPeiLoadFilePpi
+};
+
+/**
+ Install Pei Load File PPI.
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+ @retval EFI_SUCESS The entry point executes successfully.
+ @retval Others Some error occurs during the execution of this function.
+**/
+EFI_STATUS
+EFIAPI
+InitializeFitPayloadLoaderPeim (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PeiServicesInstallPpi (&gPpiLoadFilePpiList);
+
+ return Status;
+}
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
new file mode 100644
index 0000000000..acb0e09f68
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
@@ -0,0 +1,59 @@
+## @file
+# Produce LoadFile PPI for payload loading.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FitPayloadLoaderPeim
+ FILE_GUID = 55AC82C8-FC17-4C56-BCDA-990BB0A73E41
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InitializeFitPayloadLoaderPeim
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ FitPayloadLoaderPeim.c
+ FitLib.h
+ FitLib/FitLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ PcAtChipsetPkg/PcAtChipsetPkg.dec
+ UefiPayloadPkg/UefiPayloadPkg.dec
+
+[LibraryClasses]
+ PcdLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ PeiServicesLib
+ HobLib
+ BaseLib
+ PeimEntryPoint
+ DebugLib
+ FdtLib
+
+[Ppis]
+ gEfiPeiLoadFilePpiGuid ## PRODUCES
+
+[Pcd]
+ gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister
+ gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister
+
+[Guids]
+ gUniversalPayloadExtraDataGuid ## PRODUCES
+ gUniversalPayloadBaseGuid ## PRODUCES
+
+[Depex]
+ TRUE
diff --git a/UefiPayloadPkg/Readme.md b/UefiPayloadPkg/Readme.md
new file mode 100644
index 0000000000..616a5dd467
--- /dev/null
+++ b/UefiPayloadPkg/Readme.md
@@ -0,0 +1,191 @@
+# UefiPayloadPkg
+Provide UEFI Universal Payload for different bootloader to generate EFI environment
+
+# Spec
+
+UniversalPayload URL: https://universalscalablefirmware.github.io/documentation/2_universal_payload.html
+
+ELF Format URL: https://refspecs.linuxfoundation.org/elf/elf.pdf
+
+FIT Format URL: https://universalpayload.github.io/spec/chapter2-payload-image-format.html
+
+# Uefi UniversalPayload Format
+ | Binary Format | HandOffPayload - HOB |
+ |---------------|----------------------|
+ | ELF | V (Default) |
+ | FIT | V |
+
+# Binary Format
+ - ELF
+ ```
+ + +-----------------------+
+ | | UniversalPayloadEntry | <----------- UefiPayloadPkg\UefiPayloadEntry\UniversalPayloadEntry.c:_ModuleEntryPoint (HOB)
+ | +-----------------------+
+ | | .upld_info | patch it directly
+ ELF Format | +-----------------------+
+ | | .upld.uefi_fv | patch it directly
+ | +-----------------------+
+ | | .upld.bds_fv | patch it directly
+ | +-----------------------+
+ | | .upld.<afpx>_fv | patch it directly
+ + +-----------------------+
+ ```
+
+ - FIT
+ ```
+ + +-----------------------+
+ FIT Data | | FIT Header | <----------- Generate by pylibfdt
+ + +-----------------------+
+ PECOFF Format | | UniversalPayloadEntry | <----------- UefiPayloadPkg\UefiPayloadEntry\FitUniversalPayloadEntry.c:_ModuleEntryPoint (HOB)
+ + +-----------------------+
+ Relocate Data | | reloc-start |
+ + +-----------------------+
+ | | uefi_fv | patch it directly
+ | +-----------------------+
+ Multi Binary | | bds_fv | patch it directly
+ | +-----------------------+
+ | | afp_xxx_fv | patch it directly
+ | +-----------------------+
+ | | afp_xxx_fv | patch it directly
+ + +-----------------------+
+ ```
+
+# Environment
+ - ELF
+ ```
+ Download and install https://github.com/llvm/llvm-project/releases/tag/llvmorg-10.0.1
+ ```
+ - FIT
+ - Windows
+ ```powershell
+ Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
+ choco install dtc-msys2
+ pip3 install pefile
+ pip3 install swig
+ pip3 install pylibfdt
+ ```
+ - Ubuntu
+ ```bash
+ sudo apt install -y u-boot-tools
+ pip3 install pefile
+ pip3 install swig
+ pip3 install pylibfdt
+ ```
+# How to build UEFI UniversalPayload
+ - Windows
+ - edksetup Rebuild
+ - Linux
+ - make -C BaseTools
+ - source edksetup.sh
+
+ - UniversalPayload.elf
+ - python UefiPayloadPkg/UniversalPayloadBuild.py -t <TOOL_CHAIN_TAG>
+ - llvm-objdump -h Build/UefiPayloadPkgX64/UniversalPayload.elf
+
+ - UniversalPayload.fit
+ - python UefiPayloadPkg/UniversalPayloadBuild.py -t <TOOL_CHAIN_TAG> --Fit
+ - fdtdump Build/UefiPayloadPkgX64/UniversalPayload.fit
+
+# Edk2boot + UefiUniversalPayload
+ELF Edk2boot use below way to support compress and sign.
+
+- ELF Behavior - Edk2boot + UefiUniversalPayload.elf
+ ```
+ Boot Flow
+ +-------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+-------------------+
+ | Platform Init | Universal Loader Interface | OS |
+ +-------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+-------------------+
+ HOBs
+ SEC -> PEI -> DXE -> DXE IPL -> UefiPayloadPkg\PayloadLoaderPeim\PayloadLoaderPeim.c ------------------------------------------------------------------------------------> Load UniversalPayload.elf -> Operation System
+
+
+ | Platform Initialize - Edk2 | UniversalPayload - Edk2 |
+ +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
+
+ Binary Format
+
+ +-------------------+
+ | BIOS.rom |
+ +-------------------+
+ | Other Firmware |
+ +-------------------+
+ | ... | FMMT UniversalPayloadBuild.py
+ +-------------------+<----------------+-----------------------+ GenFfs +-----------------------+ Rsa2048Sha256 Sign +-----------------------+ LzmaCompress +----------------------+ GenSec +--------------------------------+
+ | | | EDK2 FFS Header |<-----------| Rsa2048Sha256 Hash |<--------------------| UniversalPayload.lzma |<--------------| EDK2 SEC Header |<--------| UniversalPayload.elf |
+ | RAW Data | +-----------------------+ +-----------------------+ +-----------------------+ +----------------------+ +--------------------------------+
+ | | | Rsa2048Sha256 Hash | | UniversalPayload.lzma | | UniversalPayload.elf | | upld_info |
+ | | +-----------------------+ +-----------------------+ +----------------------+ +--------------------------------+
+ | | | UniversalPayload.lzma | | upld_info | | upld.uefi_fv |
+ +-------------------+<----------------+-----------------------+ +----------------------+ +--------------------------------+
+ | ... | | upld.uefi_fv | | upld.bds_fv |
+ +-------------------+ +----------------------+ +--------------------------------+
+ | Other Firmware | | upld.bds_fv | | upld.AFP1 |
+ +-------------------+ +----------------------+ +--------------------------------+
+ | upld.AFP1 | | upld.AFP2 |
+ +----------------------+ +--------------------------------+
+ | upld.AFP2 | | ... |
+ +----------------------+ +--------------------------------+
+ | ... | | upld.AFPn |
+ +----------------------+ +--------------------------------+
+ | upld.AFPn |
+ +----------------------+
+ ```
+
+FIT Edk2boot use below way to support compress and sign
+- FIT Behavior - Edk2boot + UefiUniversalPayload.fit
+ ```
+ Boot Flow
+ +-------------------------------------------------------------------------------------+------------------------------------------------------------------------+-------------------+
+ | Platform Init | Universal Loader Interface | OS |
+ +-------------------------------------------------------------------------------------+------------------------------------------------------------------------+-------------------+
+ HOBs
+ SEC -> PEI -> DXE -> DXE IPL -> *UefiPayloadPkg\PayloadLoaderPeim\PayloadLoaderPeim.c ----------------------------------------------> Load UniversalPayload.fit -> Operation System
+
+ Binary Format
+
+ | Platform Initialize - Edk2 | UniversalPayload - Edk2 (UniversalPayloadBuild.py --Fit) |
+ +---------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
+
+ +-------------------+
+ | BIOS.rom |
+ +-------------------+
+ | Other Firmware |
+ +-------------------+
+ | ... | FMMT UniversalPayloadBuild.py --Fit tianocore -> data-offset
+ +-------------------+<----------------+--------------------------------+ GenFfs +--------------------------------+ GenSec +--------------------------------+ tianocore -> reloc-start +--------------------------+
+ | | | EDK2 FFS Header |<--------| EDK2 SEC Header |<--------| FIT Header |<-------------------------| UniversalPayload.pecoff |
+ | | +--------------------------------+ +--------------------------------+ | description = "Uefi Payload"; | +--------------------------+
+ | | | EDK2 SEC Header | | FIT Header | | ... |
+ | RAW Data | +--------------------------------+ | | | images { | uefi-fv -> data-offset +--------------------------+
+ | | | FIT Header | | | | tianocore {...}; |<-------------------------| uefi_fv |
+ | | | | +--------------------------------+ | uefi-fv {...}; | bds-fv -> data-offset +--------------------------+
+ | | | | | tianocore -> data | | bds-fv {...}; |<-------------------------| bds_fv |
+ | | +--------------------------------+ +--------------------------------+ | afp1-fv {...}; | AFP1 -> data-offset +--------------------------+
+ | | | tianocore -> data | | tianocore -> reloc-start | | ... |<-------------------------| AFP1 |
+ | | +--------------------------------+ +--------------------------------+ | afpn-fv {...}; | AFP2 -> data-offset +--------------------------+
+ | | | tianocore -> reloc-start | | uefi-fv -> data | | } |<-------------------------| AFP2 |
+ | | +--------------------------------+ +--------------------------------+ | configurations { | ... +--------------------------+
+ | | | uefi-fv -> data | | bds-fv -> data | | conf-1 {...} |<-------------------------| ... |
+ | | +--------------------------------+ +--------------------------------+ | } | AFPn -> data-offset +--------------------------+
+ | | | bds-fv -> data | | AFP1-fv -> data | | |<-------------------------| AFPn |
+ | | +--------------------------------+ +--------------------------------+ | | +--------------------------+
+ | | | AFP1-fv -> data | | AFP2-fv -> data | | |
+ | | +--------------------------------+ +--------------------------------+ +--------------------------------+
+ | | | AFP2-fv -> data | | ... | | tianocore -> data |
+ | | +--------------------------------+ +--------------------------------+ +--------------------------------+
+ | | | ... | | AFPn-fv -> data | | tianocore -> reloc-start |
+ | | +--------------------------------+ +--------------------------------+ +--------------------------------+
+ | | | AFPn-fv -> data | | uefi-fv -> data |
+ +-------------------+<----------------+--------------------------------+ +--------------------------------+
+ | ... | | bds-fv -> data |
+ +-------------------+ +--------------------------------+
+ | Other Firmware | | AFP1-fv -> data |
+ +-------------------+ +--------------------------------+
+ | AFP2-fv -> data |
+ +--------------------------------+
+ | ... |
+ +--------------------------------+
+ | AFPn-fv -> data |
+ +--------------------------------+
+
+ ```
diff --git a/UefiPayloadPkg/Tools/MkFitImage.py b/UefiPayloadPkg/Tools/MkFitImage.py
new file mode 100644
index 0000000000..82ab933d6d
--- /dev/null
+++ b/UefiPayloadPkg/Tools/MkFitImage.py
@@ -0,0 +1,272 @@
+## @file
+# This file is a script to build fit image.
+# It generate a dtb header and combine a binary file after this header.
+#
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+from os.path import exists
+import libfdt
+from ctypes import *
+import time
+
+class FIT_IMAGE_INFO_HEADER:
+ """Class for user setting data to use MakeFitImage()
+ """
+ _pack_ = 1
+ _fields_ = [
+ ('Compatible', str),
+ ('UplVersion', int),
+ ('Description', str),
+ ('Type', str),
+ ('Arch', str),
+ ('Compression', str),
+ ('Revision', int),
+ ('BuildType', str),
+ ('Capabilities', str),
+ ('Producer', str),
+ ('ImageId', str),
+ ('DataOffset', int),
+ ('DataSize', int),
+ ('RelocStart', int),
+ ('LoadAddr', int),
+ ('Entry', int),
+ ('Binary', str),
+ ('TargetPath', str),
+ ('UefifvPath', str),
+ ('BdsfvPath', str),
+ ('NetworkfvPath', str),
+ ('Project', str),
+ ]
+
+ def __init__(self):
+ self.Compatible = 'universal-payload'
+ self.UplVersion = 0x0100
+ self.TargetPath = 'mkimage.fit'
+
+def CreatFdt(Fdt):
+ FdtEmptyTree = libfdt.fdt_create_empty_tree(Fdt, len(Fdt))
+ if FdtEmptyTree != 0:
+ print('\n- Failed - Create Fdt failed!')
+ return False
+ return True
+
+def BuildConfNode(Fdt, ParentNode, MultiImage):
+ ConfNode1 = libfdt.fdt_add_subnode(Fdt, ParentNode, 'conf-1')
+
+ libfdt.fdt_setprop(Fdt, ConfNode1, 'require-fit', b'', 0)
+ libfdt.fdt_setprop(Fdt, ConfNode1, 'firmware', bytes('tianocore', 'utf-8'), len('tianocore') + 1)
+
+def BuildFvImageNode(Fdt, InfoHeader, ParentNode, DataOffset, DataSize, Description):
+ libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-size', DataSize)
+ libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-offset', DataOffset)
+ libfdt.fdt_setprop(Fdt, ParentNode, 'compression', bytes('none', 'utf-8'), len('none') + 1)
+ libfdt.fdt_setprop(Fdt, ParentNode, 'project ', bytes('tianocore', 'utf-8'), len('tianocore') + 1)
+ libfdt.fdt_setprop(Fdt, ParentNode, 'arch', bytes('x86_64', 'utf-8'), len('x86_64') + 1)
+ libfdt.fdt_setprop(Fdt, ParentNode, 'type', bytes('flat-binary', 'utf-8'), len('flat-binary') + 1)
+ libfdt.fdt_setprop(Fdt, ParentNode, 'description', bytes(Description, 'utf-8'), len(Description) + 1)
+
+def BuildTianoImageNode(Fdt, InfoHeader, ParentNode, DataOffset, DataSize, Description):
+ #
+ # Set 'load' and 'data-offset' to reserve the memory first.
+ # They would be set again when Fdt completes or this function parses target binary file.
+ #
+ if InfoHeader.LoadAddr is not None:
+ libfdt.fdt_setprop_u64(Fdt, ParentNode, 'load', InfoHeader.LoadAddr)
+ if InfoHeader.Entry is not None:
+ libfdt.fdt_setprop_u64(Fdt, ParentNode, 'entry-start', InfoHeader.Entry)
+ if InfoHeader.RelocStart is not None:
+ libfdt.fdt_setprop_u32(Fdt, ParentNode, 'reloc-start', InfoHeader.RelocStart)
+ if InfoHeader.DataSize is not None:
+ libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-size', DataSize)
+ if InfoHeader.DataOffset is not None:
+ libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-offset', DataOffset)
+ if InfoHeader.Producer is not None:
+ libfdt.fdt_setprop(Fdt, ParentNode, 'producer ', bytes(InfoHeader.Producer, 'utf-8'), len(InfoHeader.Producer) + 1)
+ if InfoHeader.Capabilities is not None:
+ CapStrs = ','.join(InfoHeader.Capabilities)
+ libfdt.fdt_setprop(Fdt, ParentNode, 'capabilities ', bytes(CapStrs, 'utf-8'), len(CapStrs) + 1)
+ if InfoHeader.Type is not None:
+ libfdt.fdt_setprop(Fdt, ParentNode, 'type ', bytes(InfoHeader.Type, 'utf-8'), len(InfoHeader.Type) + 1)
+ if InfoHeader.Arch is not None:
+ libfdt.fdt_setprop(Fdt, ParentNode, 'arch ', bytes(InfoHeader.Arch, 'utf-8'), len(InfoHeader.Arch) + 1)
+ if InfoHeader.Project is not None:
+ libfdt.fdt_setprop(Fdt, ParentNode, 'project ', bytes(InfoHeader.Project, 'utf-8'), len(InfoHeader.Project) + 1)
+ if InfoHeader.Description is not None:
+ libfdt.fdt_setprop(Fdt, ParentNode, 'description', bytes(Description, 'utf-8'), len(Description) + 1)
+
+#
+# The subnode would be inserted from bottom to top of structure block.
+#
+def BuildFitImage(Fdt, InfoHeader):
+ MultiImage = [
+ ["tianocore", InfoHeader.Binary, BuildTianoImageNode , InfoHeader.Description, None, 0 ],
+ ["uefi-fv", InfoHeader.UefifvPath, BuildFvImageNode, "UEFI Firmware Volume", None, 0 ],
+ ["bds-fv", InfoHeader.BdsfvPath, BuildFvImageNode , "BDS Firmware Volume", None, 0 ],
+ ["network-fv", InfoHeader.NetworkfvPath, BuildFvImageNode , "Network Firmware Volume", None, 0 ],
+ ]
+
+ #
+ # Set basic information
+ #
+ libfdt.fdt_setprop_u32(Fdt, 0, 'build-revision ', InfoHeader.Revision)
+ libfdt.fdt_setprop_u32(Fdt, 0, 'spec-version', InfoHeader.UplVersion)
+
+ #
+ # Build configurations node
+ #
+ ConfNode = libfdt.fdt_add_subnode(Fdt, 0, 'configurations')
+ BuildConfNode(Fdt, ConfNode, MultiImage)
+
+ # Build image
+ DataOffset = InfoHeader.DataOffset
+ for Index in range (0, len (MultiImage)):
+ _, Path, _, _, _, _ = MultiImage[Index]
+ if exists(Path) == 1:
+ TempBinary = open(Path, 'rb')
+ BinaryData = TempBinary.read()
+ TempBinary.close()
+ MultiImage[Index][-2] = BinaryData
+ MultiImage[Index][-1] = DataOffset
+ DataOffset += len (BinaryData)
+ libfdt.fdt_setprop_u32(Fdt, 0, 'size', DataOffset)
+ posix_time = int(time.time())
+ libfdt.fdt_setprop_u32(Fdt, 0, 'timestamp', posix_time)
+ DescriptionFit = 'Uefi OS Loader'
+ libfdt.fdt_setprop(Fdt, 0, 'description', bytes(DescriptionFit, 'utf-8'), len(DescriptionFit) + 1)
+
+ ImageNode = libfdt.fdt_add_subnode(Fdt, 0, 'images')
+ for Item in reversed (MultiImage):
+ Name, Path, BuildFvNode, Description, BinaryData, DataOffset = Item
+ FvNode = libfdt.fdt_add_subnode(Fdt, ImageNode, Name)
+ BuildFvNode (Fdt, InfoHeader, FvNode, DataOffset, len(BinaryData), Description)
+
+ #
+ # Create new image file and combine all binary.
+ #
+ DtbFile = open(InfoHeader.TargetPath, "wb")
+ DtbFile.truncate()
+ DtbFile.write(Fdt)
+ for Item in MultiImage:
+ _, _, _, _, BinaryData, _ = Item
+ DtbFile.write(BinaryData)
+ DtbFile.close()
+
+ return True
+
+def MakeFitImage(InfoHeader):
+ #
+ # Allocate fdt byte array.
+ #
+ Fdt = bytearray(InfoHeader.DataOffset)
+
+ #
+ # Create fdt empty tree.
+ #
+ if CreatFdt(Fdt) is False:
+ return False
+
+ #
+ # Parse args to build fit image.
+ #
+ return BuildFitImage(Fdt, InfoHeader)
+
+def ReplaceFv (UplBinary, SectionFvFile, SectionName):
+ try:
+ #
+ # Get Original Multi Fv
+ #
+ with open (UplBinary, "rb") as File:
+ Dtb = File.read ()
+ Fit = libfdt.Fdt (Dtb)
+ NewFitHeader = bytearray(Dtb[0:Fit.totalsize()])
+ FitSize = len(Dtb)
+
+ LoadablesList = []
+ ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'images')
+ FvNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, 'uefi-fv')
+ NodeDepth = libfdt.fdt_node_depth (NewFitHeader, ImagesNode)
+ node_name = libfdt.fdt_get_name(NewFitHeader, FvNode)
+ FvNode = libfdt.fdt_next_node(NewFitHeader, FvNode, NodeDepth)
+
+ while node_name[0][-2:] == 'fv':
+ LoadablesList.append (node_name[0])
+ node_name = libfdt.fdt_get_name(NewFitHeader, FvNode[0])
+ FvNode = libfdt.fdt_next_node(NewFitHeader, FvNode[0], NodeDepth)
+ #
+ # Get current Fit Binary FV data
+ #
+ MultiFvList = []
+ for Item in LoadablesList:
+ ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, Item)
+ ImageOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big')
+ ImageSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-size')[0], 'big')
+ MultiFvList.append ([Item, Dtb[ImageOffset:ImageOffset + ImageSize]])
+
+ IsFvExist = False
+ for Index in range (0, len (MultiFvList)):
+ if MultiFvList[Index][0] == SectionName:
+ with open (SectionFvFile, 'rb') as File:
+ MultiFvList[Index][1] = File.read ()
+ ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, SectionName)
+ ImageSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-size')[0], 'big')
+ ReplaceOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big')
+ OffsetDelta = len(MultiFvList[Index][1]) - ImageSize
+ FitSize += OffsetDelta
+ IsFvExist = True
+ libfdt.fdt_setprop_u32(NewFitHeader, ImageNode, 'data-size', len(MultiFvList[Index][1]))
+
+ #
+ # Update new fit header
+ #
+ ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'images')
+ if (IsFvExist == False):
+ with open (SectionFvFile, 'rb') as File:
+ SectionFvFileBinary = File.read ()
+ MultiFvList.append ([SectionName, SectionFvFileBinary])
+ FvNode = libfdt.fdt_add_subnode(NewFitHeader, ImagesNode, SectionName)
+ BuildFvImageNode (NewFitHeader, None, FvNode, FitSize, len(SectionFvFileBinary), SectionName + " Firmware Volume")
+ FitSize += len(SectionFvFileBinary)
+ else:
+ for Index in range (0, len (MultiFvList)):
+ ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, MultiFvList[Index][0])
+ ImageOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big')
+ if ImageOffset > ReplaceOffset:
+ libfdt.fdt_setprop_u32(NewFitHeader, ImageNode, 'data-offset', ImageOffset + OffsetDelta)
+
+ ConfNodes = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'configurations')
+ libfdt.fdt_setprop(NewFitHeader, ConfNodes, 'default ', bytes('conf-1', 'utf-8'), len('conf-1') + 1)
+ ConfNode = libfdt.fdt_subnode_offset(NewFitHeader, ConfNodes, 'conf-1')
+
+ libfdt.fdt_setprop_u32(NewFitHeader, 0, 'size', FitSize)
+
+ #
+ # Generate new fit image
+ #
+ ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'images')
+ TianoNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, 'tianocore')
+ TianoOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, TianoNode, 'data-offset')[0], 'big')
+ TianoSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, TianoNode, 'data-size')[0], 'big')
+ TianoBinary = Dtb[TianoOffset:TianoOffset + TianoSize]
+
+ print("\nGenerate new fit image:")
+ NewUplBinary = bytearray(FitSize)
+ print("Update fit header\t to 0x0\t\t ~ " + str(hex(len(NewFitHeader))))
+ NewUplBinary[:len(NewFitHeader)] = NewFitHeader
+ print("Update tiano image\t to " + str(hex(len(NewFitHeader))) + "\t ~ " + str(hex(len(NewFitHeader) + len(TianoBinary))))
+ NewUplBinary[len(NewFitHeader):len(NewFitHeader) + len(TianoBinary)] = TianoBinary
+ for Index in range (0, len (MultiFvList)):
+ ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, MultiFvList[Index][0])
+ ImageOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big')
+ ImageSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-size')[0], 'big')
+ NewUplBinary[ImageOffset:ImageOffset + ImageSize] = MultiFvList[Index][1]
+ print("Update " + MultiFvList[Index][0] + "\t\t to " + str(hex(ImageOffset)) + "\t ~ " + str(hex(ImageOffset + ImageSize)))
+
+ with open (UplBinary, "wb") as File:
+ File.write (NewUplBinary)
+
+ return 0
+ except Exception as Ex:
+ print(Ex)
+ return 1
diff --git a/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
new file mode 100644
index 0000000000..a53d988627
--- /dev/null
+++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
@@ -0,0 +1,654 @@
+/** @file
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "UefiPayloadEntry.h"
+#include <Library/FdtLib.h>
+#include <Guid/UniversalPayloadBase.h>
+
+#define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
+ EFI_RESOURCE_ATTRIBUTE_TESTED | \
+ EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \
+ EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \
+ EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \
+ EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED | \
+ EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
+ EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
+ EFI_RESOURCE_ATTRIBUTE_64_BIT_IO | \
+ EFI_RESOURCE_ATTRIBUTE_PERSISTENT )
+
+#define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
+ EFI_RESOURCE_ATTRIBUTE_TESTED )
+
+extern VOID *mHobList;
+
+CHAR8 *mLineBuffer = NULL;
+
+/**
+ Print all HOBs info from the HOB list.
+ @return The pointer to the HOB list.
+**/
+VOID
+PrintHob (
+ IN CONST VOID *HobStart
+ );
+
+/**
+ Find the first substring.
+ @param String Point to the string where to find the substring.
+ @param CharSet Point to the string to be found.
+**/
+UINTN
+EFIAPI
+AsciiStrSpn (
+ IN CHAR8 *String,
+ IN CHAR8 *CharSet
+ )
+{
+ UINTN Count;
+ CHAR8 *Str1;
+ CHAR8 *Str2;
+
+ Count = 0;
+
+ for (Str1 = String; *Str1 != L'\0'; Str1++) {
+ for (Str2 = CharSet; *Str2 != L'\0'; Str2++) {
+ if (*Str1 == *Str2) {
+ break;
+ }
+ }
+
+ if (*Str2 == L'\0') {
+ return Count;
+ }
+
+ Count++;
+ }
+
+ return Count;
+}
+
+/**
+ Searches a string for the first occurrence of a character contained in a
+ specified buffer.
+ @param String Point to the string where to find the substring.
+ @param CharSet Point to the string to be found.
+**/
+CHAR8 *
+EFIAPI
+AsciiStrBrk (
+ IN CHAR8 *String,
+ IN CHAR8 *CharSet
+ )
+{
+ CHAR8 *Str1;
+ CHAR8 *Str2;
+
+ for (Str1 = String; *Str1 != L'\0'; Str1++) {
+ for (Str2 = CharSet; *Str2 != L'\0'; Str2++) {
+ if (*Str1 == *Str2) {
+ return (CHAR8 *)Str1;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ Find the next token after one or more specified characters.
+ @param String Point to the string where to find the substring.
+ @param CharSet Point to the string to be found.
+**/
+CHAR8 *
+EFIAPI
+AsciiStrTokenLine (
+ IN CHAR8 *String OPTIONAL,
+ IN CHAR8 *CharSet
+ )
+{
+ CHAR8 *Begin;
+ CHAR8 *End;
+
+ Begin = (String == NULL) ? mLineBuffer : String;
+ if (Begin == NULL) {
+ return NULL;
+ }
+
+ Begin += AsciiStrSpn (Begin, CharSet);
+ if (*Begin == L'\0') {
+ mLineBuffer = NULL;
+ return NULL;
+ }
+
+ End = AsciiStrBrk (Begin, CharSet);
+ if ((End != NULL) && (*End != L'\0')) {
+ *End = L'\0';
+ End++;
+ }
+
+ mLineBuffer = End;
+ return Begin;
+}
+
+/**
+ Some bootloader may pass a pcd database, and UPL also contain a PCD database.
+ Dxe PCD driver has the assumption that the two PCD database can be catenated and
+ the local token number should be successive.
+ This function will fix up the UPL PCD database to meet that assumption.
+ @param[in] DxeFv The FV where to find the Universal PCD database.
+ @retval EFI_SUCCESS If it completed successfully.
+ @retval other Failed to fix up.
+**/
+EFI_STATUS
+FixUpPcdDatabase (
+ IN EFI_FIRMWARE_VOLUME_HEADER *DxeFv
+ )
+{
+ EFI_STATUS Status;
+ EFI_FFS_FILE_HEADER *FileHeader;
+ VOID *PcdRawData;
+ PEI_PCD_DATABASE *PeiDatabase;
+ PEI_PCD_DATABASE *UplDatabase;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ DYNAMICEX_MAPPING *ExMapTable;
+ UINTN Index;
+
+ GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);
+ if (GuidHob == NULL) {
+ //
+ // No fix-up is needed.
+ //
+ return EFI_SUCCESS;
+ }
+
+ PeiDatabase = (PEI_PCD_DATABASE *)GET_GUID_HOB_DATA (GuidHob);
+ DEBUG ((DEBUG_INFO, "Find the Pei PCD data base, the total local token number is %d\n", PeiDatabase->LocalTokenCount));
+
+ Status = FvFindFileByTypeGuid (DxeFv, EFI_FV_FILETYPE_DRIVER, PcdGetPtr (PcdPcdDriverFile), &FileHeader);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = FileFindSection (FileHeader, EFI_SECTION_RAW, &PcdRawData);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ UplDatabase = (PEI_PCD_DATABASE *)PcdRawData;
+ ExMapTable = (DYNAMICEX_MAPPING *)(UINTN)((UINTN)PcdRawData + UplDatabase->ExMapTableOffset);
+
+ for (Index = 0; Index < UplDatabase->ExTokenCount; Index++) {
+ ExMapTable[Index].TokenNumber += PeiDatabase->LocalTokenCount;
+ }
+
+ DEBUG ((DEBUG_INFO, "Fix up UPL PCD database successfully\n"));
+ return EFI_SUCCESS;
+}
+
+/**
+ Add HOB into HOB list
+ @param[in] Hob The HOB to be added into the HOB list.
+**/
+VOID
+AddNewHob (
+ IN EFI_PEI_HOB_POINTERS *Hob
+ )
+{
+ EFI_PEI_HOB_POINTERS NewHob;
+
+ if (Hob->Raw == NULL) {
+ return;
+ }
+
+ NewHob.Header = CreateHob (Hob->Header->HobType, Hob->Header->HobLength);
+
+ if (NewHob.Header != NULL) {
+ CopyMem (NewHob.Header + 1, Hob->Header + 1, Hob->Header->HobLength - sizeof (EFI_HOB_GENERIC_HEADER));
+ }
+}
+
+/**
+ Found the Resource Descriptor HOB that contains a range (Base, Top)
+ @param[in] HobList Hob start address
+ @param[in] Base Memory start address
+ @param[in] Top Memory end address.
+ @retval The pointer to the Resource Descriptor HOB.
+**/
+EFI_HOB_RESOURCE_DESCRIPTOR *
+FindResourceDescriptorByRange (
+ IN VOID *HobList,
+ IN EFI_PHYSICAL_ADDRESS Base,
+ IN EFI_PHYSICAL_ADDRESS Top
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
+
+ for (Hob.Raw = (UINT8 *)HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
+ //
+ // Skip all HOBs except Resource Descriptor HOBs
+ //
+ if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+ continue;
+ }
+
+ //
+ // Skip Resource Descriptor HOBs that do not describe tested system memory
+ //
+ ResourceHob = Hob.ResourceDescriptor;
+ if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
+ continue;
+ }
+
+ if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
+ continue;
+ }
+
+ //
+ // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
+ //
+ if (Base < ResourceHob->PhysicalStart) {
+ continue;
+ }
+
+ if (Top > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) {
+ continue;
+ }
+
+ return ResourceHob;
+ }
+
+ return NULL;
+}
+
+/**
+ Find the highest below 4G memory resource descriptor, except the input Resource Descriptor.
+ @param[in] HobList Hob start address
+ @param[in] MinimalNeededSize Minimal needed size.
+ @param[in] ExceptResourceHob Ignore this Resource Descriptor.
+ @retval The pointer to the Resource Descriptor HOB.
+**/
+EFI_HOB_RESOURCE_DESCRIPTOR *
+FindAnotherHighestBelow4GResourceDescriptor (
+ IN VOID *HobList,
+ IN UINTN MinimalNeededSize,
+ IN EFI_HOB_RESOURCE_DESCRIPTOR *ExceptResourceHob
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
+ EFI_HOB_RESOURCE_DESCRIPTOR *ReturnResourceHob;
+
+ ReturnResourceHob = NULL;
+
+ for (Hob.Raw = (UINT8 *)HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
+ //
+ // Skip all HOBs except Resource Descriptor HOBs
+ //
+ if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+ continue;
+ }
+
+ //
+ // Skip Resource Descriptor HOBs that do not describe tested system memory
+ //
+ ResourceHob = Hob.ResourceDescriptor;
+ if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
+ continue;
+ }
+
+ if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
+ continue;
+ }
+
+ //
+ // Skip if the Resource Descriptor HOB equals to ExceptResourceHob
+ //
+ if (ResourceHob == ExceptResourceHob) {
+ continue;
+ }
+
+ //
+ // Skip Resource Descriptor HOBs that are beyond 4G
+ //
+ if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > BASE_4GB) {
+ continue;
+ }
+
+ //
+ // Skip Resource Descriptor HOBs that are too small
+ //
+ if (ResourceHob->ResourceLength < MinimalNeededSize) {
+ continue;
+ }
+
+ //
+ // Return the topest Resource Descriptor
+ //
+ if (ReturnResourceHob == NULL) {
+ ReturnResourceHob = ResourceHob;
+ } else {
+ if (ReturnResourceHob->PhysicalStart < ResourceHob->PhysicalStart) {
+ ReturnResourceHob = ResourceHob;
+ }
+ }
+ }
+
+ return ReturnResourceHob;
+}
+
+/**
+ Check the HOB and decide if it is need inside Payload
+ Payload maintainer may make decision which HOB is need or needn't
+ Then add the check logic in the function.
+ @param[in] Hob The HOB to check
+ @retval TRUE If HOB is need inside Payload
+ @retval FALSE If HOB is needn't inside Payload
+**/
+BOOLEAN
+IsHobNeed (
+ EFI_PEI_HOB_POINTERS Hob
+ )
+{
+ if (Hob.Header->HobType == EFI_HOB_TYPE_HANDOFF) {
+ return FALSE;
+ }
+
+ if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
+ if (CompareGuid (&Hob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) {
+ return FALSE;
+ }
+ }
+
+ // Arrive here mean the HOB is need
+ return TRUE;
+}
+
+/**
+ It will build Fv HOBs based on information from bootloaders.
+ @param[out] DxeFv The pointer to the DXE FV in memory.
+ @retval EFI_SUCCESS If it completed successfully.
+ @retval EFI_NOT_FOUND If it failed to find node in fit image.
+ @retval Others If it failed to build required HOBs.
+**/
+EFI_STATUS
+BuildFitLoadablesFvHob (
+ OUT EFI_FIRMWARE_VOLUME_HEADER **DxeFv
+ )
+{
+ EFI_STATUS Status;
+ VOID *Fdt;
+ UINT8 *GuidHob;
+ UNIVERSAL_PAYLOAD_BASE *PayloadBase;
+ INT32 ConfigNode;
+ INT32 Config1Node;
+ INT32 ImageNode;
+ INT32 FvNode;
+ INT32 Depth;
+ CONST FDT_PROPERTY *PropertyPtr;
+ INT32 TempLen;
+ CONST CHAR8 *Fvname;
+ UINT32 DataOffset;
+ UINT32 DataSize;
+ UINT32 *Data32;
+
+ GuidHob = GetFirstGuidHob (&gUniversalPayloadBaseGuid);
+ if (GuidHob != NULL) {
+ PayloadBase = (UNIVERSAL_PAYLOAD_BASE *)GET_GUID_HOB_DATA (GuidHob);
+ Fdt = (VOID *)(UINTN)PayloadBase->Entry;
+ DEBUG ((DEBUG_INFO, "PayloadBase Entry = 0x%08x\n", PayloadBase->Entry));
+ }
+
+ Status = FdtCheckHeader (Fdt);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ ConfigNode = FdtSubnodeOffsetNameLen (Fdt, 0, "configurations", (INT32)AsciiStrLen ("configurations"));
+ if (ConfigNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ Config1Node = FdtSubnodeOffsetNameLen (Fdt, ConfigNode, "conf-1", (INT32)AsciiStrLen ("conf-1"));
+ if (Config1Node <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ ImageNode = FdtSubnodeOffsetNameLen (Fdt, 0, "images", (INT32)AsciiStrLen ("images"));
+ if (ImageNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ FvNode = FdtSubnodeOffsetNameLen (Fdt, ImageNode, "tianocore", (INT32)AsciiStrLen ("tianocore"));
+ Depth = FdtNodeDepth (Fdt, FvNode);
+ FvNode = FdtNextNode (Fdt, FvNode, &Depth);
+ Fvname = FdtGetName (Fdt, FvNode, &TempLen);
+ while ((AsciiStrCmp ((Fvname + AsciiStrLen (Fvname) - 2), "fv") == 0)) {
+ if (FvNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ PropertyPtr = FdtGetProperty (Fdt, FvNode, "data-offset", &TempLen);
+ Data32 = (UINT32 *)(PropertyPtr->Data);
+ DataOffset = SwapBytes32 (*Data32);
+
+ PropertyPtr = FdtGetProperty (Fdt, FvNode, "data-size", &TempLen);
+ Data32 = (UINT32 *)(PropertyPtr->Data);
+ DataSize = SwapBytes32 (*Data32);
+
+ if (AsciiStrCmp (Fvname, "uefi-fv") == 0) {
+ *DxeFv = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)PayloadBase->Entry + (UINTN)DataOffset);
+ ASSERT ((*DxeFv)->FvLength == DataSize);
+ } else {
+ BuildFvHob (((UINTN)PayloadBase->Entry + (UINTN)DataOffset), DataSize);
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "UPL Multiple fv[%a], Base=0x%08x, size=0x%08x\n",
+ Fvname,
+ ((UINTN)PayloadBase->Entry + (UINTN)DataOffset),
+ DataSize,
+ DataOffset
+ ));
+ Depth = FdtNodeDepth (Fdt, FvNode);
+ FvNode = FdtNextNode (Fdt, FvNode, &Depth);
+ Fvname = FdtGetName (Fdt, FvNode, &TempLen);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ It will build HOBs based on information from bootloaders.
+ @param[in] BootloaderParameter The starting memory address of bootloader parameter block.
+ @param[out] DxeFv The pointer to the DXE FV in memory.
+ @retval EFI_SUCCESS If it completed successfully.
+ @retval Others If it failed to build required HOBs.
+**/
+EFI_STATUS
+BuildHobs (
+ IN UINTN BootloaderParameter,
+ OUT EFI_FIRMWARE_VOLUME_HEADER **DxeFv
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ UINTN MinimalNeededSize;
+ EFI_PHYSICAL_ADDRESS FreeMemoryBottom;
+ EFI_PHYSICAL_ADDRESS FreeMemoryTop;
+ EFI_PHYSICAL_ADDRESS MemoryBottom;
+ EFI_PHYSICAL_ADDRESS MemoryTop;
+ EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob;
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
+ UINT8 *GuidHob;
+ EFI_HOB_FIRMWARE_VOLUME *FvHob;
+ UNIVERSAL_PAYLOAD_ACPI_TABLE *AcpiTable;
+ ACPI_BOARD_INFO *AcpiBoardInfo;
+ EFI_HOB_HANDOFF_INFO_TABLE *HobInfo;
+
+ Hob.Raw = (UINT8 *)BootloaderParameter;
+ MinimalNeededSize = FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
+
+ ASSERT (Hob.Raw != NULL);
+ ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryTop == Hob.HandoffInformationTable->EfiFreeMemoryTop);
+ ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryTop == Hob.HandoffInformationTable->EfiMemoryTop);
+ ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryBottom == Hob.HandoffInformationTable->EfiFreeMemoryBottom);
+ ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryBottom == Hob.HandoffInformationTable->EfiMemoryBottom);
+
+ //
+ // Try to find Resource Descriptor HOB that contains Hob range EfiMemoryBottom..EfiMemoryTop
+ //
+ PhitResourceHob = FindResourceDescriptorByRange (Hob.Raw, Hob.HandoffInformationTable->EfiMemoryBottom, Hob.HandoffInformationTable->EfiMemoryTop);
+ if (PhitResourceHob == NULL) {
+ //
+ // Boot loader's Phit Hob is not in an available Resource Descriptor, find another Resource Descriptor for new Phit Hob
+ //
+ ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, MinimalNeededSize, NULL);
+ if (ResourceHob == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ MemoryBottom = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize;
+ FreeMemoryBottom = MemoryBottom;
+ FreeMemoryTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength;
+ MemoryTop = FreeMemoryTop;
+ } else if (PhitResourceHob->PhysicalStart + PhitResourceHob->ResourceLength - Hob.HandoffInformationTable->EfiMemoryTop >= MinimalNeededSize) {
+ //
+ // New availiable Memory range in new hob is right above memory top in old hob.
+ //
+ MemoryBottom = Hob.HandoffInformationTable->EfiFreeMemoryTop;
+ FreeMemoryBottom = Hob.HandoffInformationTable->EfiMemoryTop;
+ FreeMemoryTop = FreeMemoryBottom + MinimalNeededSize;
+ MemoryTop = FreeMemoryTop;
+ } else if (Hob.HandoffInformationTable->EfiMemoryBottom - PhitResourceHob->PhysicalStart >= MinimalNeededSize) {
+ //
+ // New availiable Memory range in new hob is right below memory bottom in old hob.
+ //
+ MemoryBottom = Hob.HandoffInformationTable->EfiMemoryBottom - MinimalNeededSize;
+ FreeMemoryBottom = MemoryBottom;
+ FreeMemoryTop = Hob.HandoffInformationTable->EfiMemoryBottom;
+ MemoryTop = Hob.HandoffInformationTable->EfiMemoryTop;
+ } else {
+ //
+ // In the Resource Descriptor HOB contains boot loader Hob, there is no enough free memory size for payload hob
+ // Find another Resource Descriptor Hob
+ //
+ ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, MinimalNeededSize, PhitResourceHob);
+ if (ResourceHob == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ MemoryBottom = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize;
+ FreeMemoryBottom = MemoryBottom;
+ FreeMemoryTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength;
+ MemoryTop = FreeMemoryTop;
+ }
+
+ HobInfo = HobConstructor ((VOID *)(UINTN)MemoryBottom, (VOID *)(UINTN)MemoryTop, (VOID *)(UINTN)FreeMemoryBottom, (VOID *)(UINTN)FreeMemoryTop);
+ HobInfo->BootMode = Hob.HandoffInformationTable->BootMode;
+ //
+ // From now on, mHobList will point to the new Hob range.
+ //
+
+ //
+ // Create an empty FvHob for the DXE FV that contains DXE core.
+ //
+ BuildFvHob ((EFI_PHYSICAL_ADDRESS)0, 0);
+ //
+ // Since payload created new Hob, move all hobs except PHIT from boot loader hob list.
+ //
+ while (!END_OF_HOB_LIST (Hob)) {
+ if (IsHobNeed (Hob)) {
+ // Add this hob to payload HOB
+ AddNewHob (&Hob);
+ }
+
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ }
+
+ BuildFitLoadablesFvHob (DxeFv);
+
+ //
+ // Create guid hob for acpi board information
+ //
+ GuidHob = GetFirstGuidHob (&gUniversalPayloadAcpiTableGuid);
+ if (GuidHob != NULL) {
+ AcpiTable = (UNIVERSAL_PAYLOAD_ACPI_TABLE *)GET_GUID_HOB_DATA (GuidHob);
+ GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid);
+ if (GuidHob == NULL) {
+ AcpiBoardInfo = BuildHobFromAcpi ((UINT64)AcpiTable->Rsdp);
+ ASSERT (AcpiBoardInfo != NULL);
+ }
+ }
+
+ //
+ // Update DXE FV information to first fv hob in the hob list, which
+ // is the empty FvHob created before.
+ //
+ FvHob = GetFirstHob (EFI_HOB_TYPE_FV);
+ FvHob->BaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)*DxeFv;
+ FvHob->Length = (*DxeFv)->FvLength;
+ return EFI_SUCCESS;
+}
+
+/**
+ Entry point to the C language phase of UEFI payload.
+ @param[in] BootloaderParameter The starting address of bootloader parameter block.
+ @retval It will not return if SUCCESS, and return error when passing bootloader parameter.
+**/
+EFI_STATUS
+EFIAPI
+_ModuleEntryPoint (
+ IN UINTN BootloaderParameter
+ )
+{
+ EFI_STATUS Status;
+ PHYSICAL_ADDRESS DxeCoreEntryPoint;
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_FIRMWARE_VOLUME_HEADER *DxeFv;
+
+ mHobList = (VOID *)BootloaderParameter;
+ DxeFv = NULL;
+ // Call constructor for all libraries
+ ProcessLibraryConstructorList ();
+
+ DEBUG ((DEBUG_INFO, "Entering Universal Payload...\n"));
+ DEBUG ((DEBUG_INFO, "sizeof(UINTN) = 0x%x\n", sizeof (UINTN)));
+
+ DEBUG_CODE (
+ //
+ // Dump the Hobs from boot loader
+ //
+ PrintHob (mHobList);
+ );
+
+ // Initialize floating point operating environment to be compliant with UEFI spec.
+ InitializeFloatingPointUnits ();
+
+ // Build HOB based on information from Bootloader
+ Status = BuildHobs (BootloaderParameter, &DxeFv);
+ ASSERT_EFI_ERROR (Status);
+
+ FixUpPcdDatabase (DxeFv);
+ Status = UniversalLoadDxeCore (DxeFv, &DxeCoreEntryPoint);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Mask off all legacy 8259 interrupt sources
+ //
+ IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF);
+ IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF);
+
+ Hob.HandoffInformationTable = (EFI_HOB_HANDOFF_INFO_TABLE *)GetFirstHob (EFI_HOB_TYPE_HANDOFF);
+ HandOffToDxeCore (DxeCoreEntryPoint, Hob);
+
+ // Should not get here
+ CpuDeadLoop ();
+ return EFI_SUCCESS;
+}
diff --git a/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
new file mode 100644
index 0000000000..a7d1a8c9e5
--- /dev/null
+++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
@@ -0,0 +1,98 @@
+## @file
+# This is the first module for UEFI payload.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FitUniversalPayloadEntry
+ FILE_GUID = CED5A8A9-B6EA-4D5A-8689-577EE88566CF
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ FitUniversalPayloadEntry.c
+ LoadDxeCore.c
+ MemoryAllocation.c
+ PrintHob.c
+ AcpiTable.c
+
+[Sources.Ia32]
+ X64/VirtualMemory.h
+ X64/VirtualMemory.c
+ Ia32/DxeLoadFunc.c
+ Ia32/IdtVectorAsm.nasm
+
+[Sources.X64]
+ X64/VirtualMemory.h
+ X64/VirtualMemory.c
+ X64/DxeLoadFunc.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ UefiPayloadPkg/UefiPayloadPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ BaseLib
+ SerialPortLib
+ IoLib
+ HobLib
+ PeCoffLib
+ CpuLib
+ FdtLib
+
+[Guids]
+ gEfiMemoryTypeInformationGuid
+ gEfiFirmwareFileSystem2Guid
+ gEfiGraphicsInfoHobGuid
+ gEfiGraphicsDeviceInfoHobGuid
+ gUefiAcpiBoardInfoGuid
+ gEfiSmbiosTableGuid
+ gUefiSerialPortInfoGuid
+ gUniversalPayloadExtraDataGuid
+ gUniversalPayloadBaseGuid
+ gPcdDataBaseHobGuid
+ gUniversalPayloadSmbiosTableGuid
+ gEfiHobMemoryAllocBspStoreGuid
+ gUniversalPayloadAcpiTableGuid
+ gUniversalPayloadPciRootBridgeInfoGuid
+ gUniversalPayloadSmbios3TableGuid
+
+[FeaturePcd.IA32]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES
+
+[FeaturePcd.X64]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables ## CONSUMES
+
+
+[Pcd.IA32,Pcd.X64]
+ gUefiPayloadPkgTokenSpaceGuid.PcdPcdDriverFile
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize ## CONSUMES
+
+ gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase
+ gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize
+ gUefiPayloadPkgTokenSpaceGuid.PcdSystemMemoryUefiRegionSize
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy ## SOMETIMES_CONSUMES
diff --git a/UefiPayloadPkg/UefiPayloadPkg.dec b/UefiPayloadPkg/UefiPayloadPkg.dec
index e2e4a79db3..2f1fd82487 100644
--- a/UefiPayloadPkg/UefiPayloadPkg.dec
+++ b/UefiPayloadPkg/UefiPayloadPkg.dec
@@ -24,6 +24,9 @@
#
gUefiPayloadPkgTokenSpaceGuid = {0x1d127ea, 0xf6f1, 0x4ef6, {0x94, 0x15, 0x8a, 0x0, 0x0, 0x93, 0xf8, 0x9d}}
+ ## Include/Guid/UniversalPayloadBase.h
+ gUniversalPayloadBaseGuid = { 0x03d4c61d, 0x2713, 0x4ec5, {0xa1, 0xcc, 0x88, 0x3b, 0xe9, 0xdc, 0x18, 0xe5 } }
+
#
# Gop Temp
#
diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc b/UefiPayloadPkg/UefiPayloadPkg.dsc
index 47812048dd..af9308ef8e 100644
--- a/UefiPayloadPkg/UefiPayloadPkg.dsc
+++ b/UefiPayloadPkg/UefiPayloadPkg.dsc
@@ -30,7 +30,6 @@
DEFINE PS2_KEYBOARD_ENABLE = FALSE
DEFINE RAM_DISK_ENABLE = FALSE
DEFINE SIO_BUS_ENABLE = FALSE
- DEFINE UNIVERSAL_PAYLOAD = FALSE
DEFINE SECURITY_STUB_ENABLE = TRUE
DEFINE SMM_SUPPORT = FALSE
DEFINE PLATFORM_BOOT_TIMEOUT = 3
@@ -44,6 +43,14 @@
DEFINE BOOTSPLASH_IMAGE = FALSE
DEFINE NVME_ENABLE = TRUE
DEFINE CAPSULE_SUPPORT = FALSE
+ #
+ # Setup Universal Payload
+ #
+ # ELF: Build UniversalPayload file as UniversalPayload.elf
+ # FIT: Build UniversalPayload file as UniversalPayload.fit
+ #
+ DEFINE UNIVERSAL_PAYLOAD = FALSE
+ DEFINE UNIVERSAL_PAYLOAD_FORMAT = ELF
#
# NULL: NullMemoryTestDxe
@@ -311,7 +318,7 @@
VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf
CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
-
+ FdtLib|MdePkg/Library/BaseFdtLib/BaseFdtLib.inf
[LibraryClasses.common]
!if $(BOOTSPLASH_IMAGE)
SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
@@ -600,14 +607,26 @@
!if "IA32" in "$(ARCH)"
[Components.IA32]
!if $(UNIVERSAL_PAYLOAD) == TRUE
- UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
+ !if $(UNIVERSAL_PAYLOAD_FORMAT) == "ELF"
+ UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
+ !elseif $(UNIVERSAL_PAYLOAD_FORMAT) == "FIT"
+ UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
+ !else
+ UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
+ !endif
!else
UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
!endif
!else
[Components.X64]
!if $(UNIVERSAL_PAYLOAD) == TRUE
- UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
+ !if $(UNIVERSAL_PAYLOAD_FORMAT) == "ELF"
+ UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
+ !elseif $(UNIVERSAL_PAYLOAD_FORMAT) == "FIT"
+ UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
+ !else
+ UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
+ !endif
!else
UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
!endif
diff --git a/UefiPayloadPkg/UniversalPayloadBuild.py b/UefiPayloadPkg/UniversalPayloadBuild.py
index 47f37b3377..9a83fc9e44 100644
--- a/UefiPayloadPkg/UniversalPayloadBuild.py
+++ b/UefiPayloadPkg/UniversalPayloadBuild.py
@@ -10,10 +10,22 @@ import subprocess
import os
import shutil
import sys
+import pathlib
from ctypes import *
-from Tools.ElfFv import ReplaceFv
+
sys.dont_write_bytecode = True
+class bcolors:
+ HEADER = '\033[95m'
+ OKBLUE = '\033[94m'
+ OKCYAN = '\033[96m'
+ OKGREEN = '\033[92m'
+ WARNING = '\033[93m'
+ FAIL = '\033[91m'
+ ENDC = '\033[0m'
+ BOLD = '\033[1m'
+ UNDERLINE = '\033[4m'
+
class UPLD_INFO_HEADER(LittleEndianStructure):
_pack_ = 1
_fields_ = [
@@ -36,40 +48,114 @@ class UPLD_INFO_HEADER(LittleEndianStructure):
self.ImageId = b'UEFI'
self.ProducerId = b'INTEL'
-def BuildUniversalPayload(Args):
- def RunCommand(cmd):
- print(cmd)
- p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,cwd=os.environ['WORKSPACE'])
- while True:
- line = p.stdout.readline()
- if not line:
- break
- print(line.strip().decode(errors='ignore'))
-
- p.communicate()
- if p.returncode != 0:
- print("- Failed - error happened when run command: %s"%cmd)
- raise Exception("ERROR: when run command: %s"%cmd)
+def ValidateSpecRevision (Argument):
+ try:
+ (MajorStr, MinorStr) = Argument.split('.')
+ except:
+ raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
+ #
+ # Spec Revision Bits 15 : 8 - Major Version. Bits 7 : 0 - Minor Version.
+ #
+ if len(MinorStr) > 0 and len(MinorStr) < 3:
+ try:
+ Minor = int(MinorStr, 16) if len(MinorStr) == 2 else (int(MinorStr, 16) << 4)
+ except:
+ raise argparse.ArgumentTypeError ('{} Minor version of SpecRevision is not a valid integer value.'.format (Argument))
+ else:
+ raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
+
+ if len(MajorStr) > 0 and len(MajorStr) < 3:
+ try:
+ Major = int(MajorStr, 16)
+ except:
+ raise argparse.ArgumentTypeError ('{} Major version of SpecRevision is not a valid integer value.'.format (Argument))
+ else:
+ raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
+
+ return int('0x{0:02x}{1:02x}'.format(Major, Minor), 0)
+
+def Validate32BitInteger (Argument):
+ try:
+ Value = int (Argument, 0)
+ except:
+ raise argparse.ArgumentTypeError ('{} is not a valid integer value.'.format (Argument))
+ if Value < 0:
+ raise argparse.ArgumentTypeError ('{} is a negative value.'.format (Argument))
+ if Value > 0xffffffff:
+ raise argparse.ArgumentTypeError ('{} is larger than 32-bits.'.format (Argument))
+ return Value
+def ValidateAddFv (Argument):
+ Value = Argument.split ("=")
+ if len (Value) != 2:
+ raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
+ if Value[0][-3:] != "_fv":
+ raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
+ if Value[1][-3:].lower () != ".fv":
+ raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
+ if os.path.exists (Value[1]) == False:
+ raise argparse.ArgumentTypeError ('File {} is not found.'.format (Value[1]))
+ return Value
+
+def RunCommand(cmd):
+ print(cmd)
+ p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,cwd=os.environ['WORKSPACE'])
+ while True:
+ line = p.stdout.readline()
+ if not line:
+ break
+ print(line.strip().decode(errors='ignore'))
+
+ p.communicate()
+ if p.returncode != 0:
+ print("- Failed - error happened when run command: %s"%cmd)
+ raise Exception("ERROR: when run command: %s"%cmd)
+
+def BuildUniversalPayload(Args):
BuildTarget = Args.Target
ToolChain = Args.ToolChain
Quiet = "--quiet" if Args.Quiet else ""
- ElfToolChain = 'CLANGDWARF'
- BuildDir = os.path.join(os.environ['WORKSPACE'], os.path.normpath("Build/UefiPayloadPkgX64"))
- BuildModule = ""
- BuildArch = ""
+ if Args.Fit == True:
+ PayloadEntryToolChain = ToolChain
+ Args.Macro.append("UNIVERSAL_PAYLOAD_FORMAT=FIT")
+ UpldEntryFile = "FitUniversalPayloadEntry"
+ else:
+ PayloadEntryToolChain = 'CLANGDWARF'
+ Args.Macro.append("UNIVERSAL_PAYLOAD_FORMAT=ELF")
+ UpldEntryFile = "UniversalPayloadEntry"
+
+ BuildDir = os.path.join(os.environ['WORKSPACE'], os.path.normpath("Build/UefiPayloadPkgX64"))
if Args.Arch == 'X64':
BuildArch = "X64"
- EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ElfToolChain), os.path.normpath("X64/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll"))
+ FitArch = "x86_64"
+ ObjCopyFlag = "elf64-x86-64"
+ EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, PayloadEntryToolChain), os.path.normpath("X64/UefiPayloadPkg/UefiPayloadEntry/{}/DEBUG/{}.dll".format (UpldEntryFile, UpldEntryFile)))
else:
BuildArch = "IA32 -a X64"
- EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ElfToolChain), os.path.normpath("IA32/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll"))
+ FitArch = "x86"
+ ObjCopyFlag = "elf32-i386"
+ EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, PayloadEntryToolChain), os.path.normpath("IA32/UefiPayloadPkg/UefiPayloadEntry/{}/DEBUG/{}.dll".format (UpldEntryFile, UpldEntryFile)))
+ EntryModuleInf = os.path.normpath("UefiPayloadPkg/UefiPayloadEntry/{}.inf".format (UpldEntryFile))
DscPath = os.path.normpath("UefiPayloadPkg/UefiPayloadPkg.dsc")
+ DxeFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv"))
+ BdsFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv"))
+ NetworkFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv"))
+ PayloadReportPath = os.path.join(BuildDir, "UefiUniversalPayload.txt")
ModuleReportPath = os.path.join(BuildDir, "UefiUniversalPayloadEntry.txt")
UpldInfoFile = os.path.join(BuildDir, "UniversalPayloadInfo.bin")
+ if "CLANG_BIN" in os.environ:
+ LlvmObjcopyPath = os.path.join(os.environ["CLANG_BIN"], "llvm-objcopy")
+ else:
+ LlvmObjcopyPath = "llvm-objcopy"
+ try:
+ RunCommand('"%s" --version'%LlvmObjcopyPath)
+ except:
+ print("- Failed - Please check if LLVM is installed or if CLANG_BIN is set correctly")
+ sys.exit(1)
+
Pcds = ""
if (Args.pcd != None):
for PcdItem in Args.pcd:
@@ -84,7 +170,6 @@ def BuildUniversalPayload(Args):
# Building DXE core and DXE drivers as DXEFV.
#
if Args.BuildEntryOnly == False:
- PayloadReportPath = os.path.join(BuildDir, "UefiUniversalPayload.txt")
BuildPayload = "build -p {} -b {} -a X64 -t {} -y {} {}".format (DscPath, BuildTarget, ToolChain, PayloadReportPath, Quiet)
BuildPayload += Pcds
BuildPayload += Defines
@@ -93,94 +178,138 @@ def BuildUniversalPayload(Args):
# Building Universal Payload entry.
#
if Args.PreBuildUplBinary is None:
- EntryModuleInf = os.path.normpath("UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf")
- BuildModule = "build -p {} -b {} -a {} -m {} -t {} -y {} {}".format (DscPath, BuildTarget, BuildArch, EntryModuleInf, ElfToolChain, ModuleReportPath, Quiet)
+ BuildModule = "build -p {} -b {} -a {} -m {} -t {} -y {} {}".format (DscPath, BuildTarget, BuildArch, EntryModuleInf, PayloadEntryToolChain, ModuleReportPath, Quiet)
BuildModule += Pcds
BuildModule += Defines
RunCommand(BuildModule)
if Args.PreBuildUplBinary is not None:
- EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.elf")
+ if Args.Fit == False:
+ EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.elf")
+ else:
+ EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.fit")
shutil.copy (os.path.abspath(Args.PreBuildUplBinary), EntryOutputDir)
#
- # Buid Universal Payload Information Section ".upld_info"
+ # Build Universal Payload Information Section ".upld_info"
#
- upld_info_hdr = UPLD_INFO_HEADER()
- upld_info_hdr.SpecRevision = Args.SpecRevision
- upld_info_hdr.Revision = Args.Revision
- upld_info_hdr.ProducerId = Args.ProducerId.encode()[:16]
- upld_info_hdr.ImageId = Args.ImageId.encode()[:16]
- upld_info_hdr.Attribute |= 1 if BuildTarget == "DEBUG" else 0
- fp = open(UpldInfoFile, 'wb')
- fp.write(bytearray(upld_info_hdr))
- fp.close()
+ if Args.Fit == False:
+ upld_info_hdr = UPLD_INFO_HEADER()
+ upld_info_hdr.SpecRevision = Args.SpecRevision
+ upld_info_hdr.Revision = Args.Revision
+ upld_info_hdr.ProducerId = Args.ProducerId.encode()[:16]
+ upld_info_hdr.ImageId = Args.ImageId.encode()[:16]
+ upld_info_hdr.Attribute |= 1 if BuildTarget == "DEBUG" else 0
+ fp = open(UpldInfoFile, 'wb')
+ fp.write(bytearray(upld_info_hdr))
+ fp.close()
+
+ if Args.BuildEntryOnly == False:
+ import Tools.ElfFv as ElfFv
+ ElfFv.ReplaceFv (EntryOutputDir, UpldInfoFile, '.upld_info', Alignment = 4)
+ if Args.Fit == False:
+ shutil.copy (EntryOutputDir, os.path.join(BuildDir, 'UniversalPayload.elf'))
+ else:
+ shutil.copy (EntryOutputDir, os.path.join(BuildDir, 'UniversalPayload.fit'))
MultiFvList = []
if Args.BuildEntryOnly == False:
MultiFvList = [
- ['uefi_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv")) ],
- ['bds_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv")) ],
- ['network_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv")) ],
+ ['uefi_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv")) ],
+ ['bds_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv")) ],
+ ['network_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv"))],
]
- AddSectionName = '.upld_info'
- ReplaceFv (EntryOutputDir, UpldInfoFile, AddSectionName, Alignment = 4)
- if Args.PreBuildUplBinary is None:
- shutil.copy (EntryOutputDir, os.path.join(BuildDir, 'UniversalPayload.elf'))
- return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.elf')
+ if Args.Fit == True:
+ import Tools.MkFitImage as MkFitImage
+ import pefile
+ fit_image_info_header = MkFitImage.FIT_IMAGE_INFO_HEADER()
+ fit_image_info_header.Description = 'Uefi Universal Payload'
+ fit_image_info_header.UplVersion = Args.SpecRevision
+ fit_image_info_header.Type = 'flat-binary'
+ fit_image_info_header.Arch = FitArch
+ fit_image_info_header.Compression = 'none'
+ fit_image_info_header.Revision = Args.Revision
+ fit_image_info_header.BuildType = Args.Target.lower()
+ fit_image_info_header.Capabilities = None
+ fit_image_info_header.Producer = Args.ProducerId.lower()
+ fit_image_info_header.ImageId = Args.ImageId.lower()
+ fit_image_info_header.Binary = os.path.join(BuildDir, 'UniversalPayload.fit')
+ fit_image_info_header.TargetPath = os.path.join(BuildDir, 'UniversalPayload.fit')
+ fit_image_info_header.UefifvPath = DxeFvOutputDir
+ fit_image_info_header.BdsfvPath = BdsFvOutputDir
+ fit_image_info_header.NetworkfvPath = NetworkFvOutputDir
+ fit_image_info_header.DataOffset = 0x1000
+ fit_image_info_header.LoadAddr = Args.LoadAddress
+ fit_image_info_header.Project = 'tianocore'
+
+ TargetRebaseFile = fit_image_info_header.Binary.replace (pathlib.Path(fit_image_info_header.Binary).suffix, ".pecoff")
+ TargetRebaseEntryFile = fit_image_info_header.Binary.replace (pathlib.Path(fit_image_info_header.Binary).suffix, ".entry")
+
-def main():
- def ValidateSpecRevision (Argument):
- try:
- (MajorStr, MinorStr) = Argument.split('.')
- except:
- raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
#
- # Spec Revision Bits 15 : 8 - Major Version. Bits 7 : 0 - Minor Version.
+ # Rebase PECOFF to load address
#
- if len(MinorStr) > 0 and len(MinorStr) < 3:
- try:
- Minor = int(MinorStr, 16) if len(MinorStr) == 2 else (int(MinorStr, 16) << 4)
- except:
- raise argparse.ArgumentTypeError ('{} Minor version of SpecRevision is not a valid integer value.'.format (Argument))
- else:
- raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
+ RunCommand (
+ "GenFw -e SEC -o {} {}".format (
+ TargetRebaseFile,
+ fit_image_info_header.Binary
+ ))
+ RunCommand (
+ "GenFw --rebase 0x{:02X} -o {} {} ".format (
+ fit_image_info_header.LoadAddr + fit_image_info_header.DataOffset,
+ TargetRebaseFile,
+ TargetRebaseFile,
+ ))
- if len(MajorStr) > 0 and len(MajorStr) < 3:
- try:
- Major = int(MajorStr, 16)
- except:
- raise argparse.ArgumentTypeError ('{} Major version of SpecRevision is not a valid integer value.'.format (Argument))
- else:
- raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
+ #
+ # Open PECOFF relocation table binary.
+ #
+ RelocBinary = b''
+ PeCoff = pefile.PE (TargetRebaseFile)
+ for reloc in PeCoff.DIRECTORY_ENTRY_BASERELOC:
+ for entry in reloc.entries:
+ if (entry.type == 0):
+ continue
+ Type = entry.type
+ Offset = entry.rva + fit_image_info_header.DataOffset
+ RelocBinary += Type.to_bytes (8, 'little') + Offset.to_bytes (8, 'little')
+ RelocBinary += b'\x00' * (0x1000 - (len(RelocBinary) % 0x1000))
- return int('0x{0:02x}{1:02x}'.format(Major, Minor), 0)
+ #
+ # Output UniversalPayload.entry
+ #
+ TempBinary = open (TargetRebaseFile, 'rb')
+ TianoBinary = TempBinary.read ()
+ TempBinary.close ()
- def Validate32BitInteger (Argument):
- try:
- Value = int (Argument, 0)
- except:
- raise argparse.ArgumentTypeError ('{} is not a valid integer value.'.format (Argument))
- if Value < 0:
- raise argparse.ArgumentTypeError ('{} is a negative value.'.format (Argument))
- if Value > 0xffffffff:
- raise argparse.ArgumentTypeError ('{} is larger than 32-bits.'.format (Argument))
- return Value
-
- def ValidateAddFv (Argument):
- Value = Argument.split ("=")
- if len (Value) != 2:
- raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
- if Value[0][-3:] != "_fv":
- raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
- if Value[1][-3:].lower () != ".fv":
- raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
- if os.path.exists (Value[1]) == False:
- raise argparse.ArgumentTypeError ('File {} is not found.'.format (Value[1]))
- return Value
+ TianoEntryBinary = TianoBinary + RelocBinary
+ TianoEntryBinary += (b'\x00' * (0x1000 - (len(TianoBinary) % 0x1000)))
+ TianoEntryBinarySize = len (TianoEntryBinary)
+
+ TempBinary = open(TargetRebaseEntryFile, "wb")
+ TempBinary.truncate()
+ TempBinary.write(TianoEntryBinary)
+ TempBinary.close()
+
+ #
+ # Calculate entry and update relocation table start address and data-size.
+ #
+ fit_image_info_header.Entry = PeCoff.OPTIONAL_HEADER.ImageBase + PeCoff.OPTIONAL_HEADER.AddressOfEntryPoint
+ fit_image_info_header.RelocStart = fit_image_info_header.DataOffset + len(TianoBinary)
+ fit_image_info_header.DataSize = TianoEntryBinarySize
+ fit_image_info_header.Binary = TargetRebaseEntryFile
+
+ if MkFitImage.MakeFitImage(fit_image_info_header) is True:
+ print('\nSuccessfully build Fit Image')
+ else:
+ sys.exit(1)
+ return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.fit')
+ else:
+ return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.elf')
+def main():
parser = argparse.ArgumentParser(description='For building Universal Payload')
parser.add_argument('-t', '--ToolChain')
parser.add_argument('-b', '--Target', default='DEBUG')
@@ -192,13 +321,16 @@ def main():
parser.add_argument("-s", "--SpecRevision", type=ValidateSpecRevision, default ='0.7', help='Indicates compliance with a revision of this specification in the BCD format.')
parser.add_argument("-r", "--Revision", type=Validate32BitInteger, default ='0x0000010105', help='Revision of the Payload binary. Major.Minor.Revision.Build')
parser.add_argument("-o", "--ProducerId", default ='INTEL', help='A null-terminated OEM-supplied string that identifies the payload producer (16 bytes maximal).')
+ parser.add_argument("-e", "--BuildEntryOnly", action='store_true', help='Build UniversalPayload Entry file')
+ parser.add_argument("-pb", "--PreBuildUplBinary", default=None, help='Specify the UniversalPayload file')
parser.add_argument("-sk", "--SkipBuild", action='store_true', help='Skip UniversalPayload build')
parser.add_argument("-af", "--AddFv", type=ValidateAddFv, action='append', help='Add or replace specific FV into payload, Ex: uefi_fv=XXX.fv')
- command_group = parser.add_mutually_exclusive_group()
- command_group.add_argument("-e", "--BuildEntryOnly", action='store_true', help='Build UniversalPayload Entry file')
- command_group.add_argument("-pb", "--PreBuildUplBinary", default=None, help='Specify the UniversalPayload file')
+ parser.add_argument("-f", "--Fit", action='store_true', help='Build UniversalPayload file as UniversalPayload.fit', default=False)
+ parser.add_argument('-l', "--LoadAddress", type=int, help='Specify payload load address', default =0x000800000)
+
args = parser.parse_args()
+
MultiFvList = []
UniversalPayloadBinary = args.PreBuildUplBinary
if (args.SkipBuild == False):
@@ -208,12 +340,24 @@ def main():
for (SectionName, SectionFvFile) in args.AddFv:
MultiFvList.append ([SectionName, SectionFvFile])
+ def ReplaceFv (UplBinary, SectionFvFile, SectionName):
+ print (bcolors.OKGREEN + "Patch {}={} into {}".format (SectionName, SectionFvFile, UplBinary) + bcolors.ENDC)
+ if (args.Fit == False):
+ import Tools.ElfFv as ElfFv
+ return ElfFv.ReplaceFv (UplBinary, SectionFvFile, '.upld.{}'.format (SectionName))
+ else:
+ import Tools.MkFitImage as MkFitImage
+ return MkFitImage.ReplaceFv (UplBinary, SectionFvFile, SectionName)
+
if (UniversalPayloadBinary != None):
for (SectionName, SectionFvFile) in MultiFvList:
if os.path.exists (SectionFvFile) == False:
continue
- print ("Patch {}={} into {}".format (SectionName, SectionFvFile, UniversalPayloadBinary))
- ReplaceFv (UniversalPayloadBinary, SectionFvFile, '.upld.{}'.format (SectionName))
+
+ status = ReplaceFv (UniversalPayloadBinary, SectionFvFile, SectionName.replace ("_", "-"))
+ if status != 0:
+ print (bcolors.FAIL + "[Fail] Patch {}={}".format (SectionName, SectionFvFile) + bcolors.ENDC)
+ return status
print ("\nSuccessfully build Universal Payload")
--
2.39.1.windows.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#108718): https://edk2.groups.io/g/devel/message/108718
Mute This Topic: https://groups.io/mt/101378805/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] 10+ messages in thread
* Re: [edk2-devel] [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function.
2023-09-15 8:58 ` [edk2-devel] [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function brucex.wang
@ 2023-09-15 9:02 ` Guo, Gua
2023-09-15 9:06 ` Lu, James
2023-09-15 9:09 ` Benny Lin
2 siblings, 0 replies; 10+ messages in thread
From: Guo, Gua @ 2023-09-15 9:02 UTC (permalink / raw)
To: Wang, BruceX, devel@edk2.groups.io; +Cc: Lin, Benny, Chiu, Chasel, Lu, James
Reviewed-by: Gua Guo <gua.guo@intel.com>
-----Original Message-----
From: Wang, BruceX <brucex.wang@intel.com>
Sent: Friday, September 15, 2023 4:58 PM
To: devel@edk2.groups.io
Cc: Wang, BruceX <brucex.wang@intel.com>; Lin, Benny <benny.lin@intel.com>; Guo, Gua <gua.guo@intel.com>; Chiu, Chasel <chasel.chiu@intel.com>; Lu, James <james.lu@intel.com>
Subject: [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function.
From: "Brucex.Wang" <brucex.wang@intel.com>
Add FdtGetName() and FdtNodeDepth() function.
Cc: Benny Lin <benny.lin@intel.com>
Cc: Gua Guo <gua.guo@intel.com>
Cc: Chasel Chiu <chasel.chiu@intel.com>
Cc: James Lu <james.lu@intel.com>
Signed-off-by: BruceX Wang <brucex.wang@intel.com>
---
MdePkg/Include/Library/FdtLib.h | 34 +++++++++++++++++++++++++
MdePkg/Library/BaseFdtLib/FdtLib.c | 40 ++++++++++++++++++++++++++++++
2 files changed, 74 insertions(+)
diff --git a/MdePkg/Include/Library/FdtLib.h b/MdePkg/Include/Library/FdtLib.h index cf5ceba9e9..2bd926b5b4 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 (#108700): https://edk2.groups.io/g/devel/message/108700
Mute This Topic: https://groups.io/mt/101375949/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] 10+ messages in thread
* Re: [edk2-devel] [PATCH v2 2/2] UefiPayloadPkg: Add FIT support
2023-09-15 8:58 ` [edk2-devel] [PATCH v2 2/2] UefiPayloadPkg: Add FIT support brucex.wang
@ 2023-09-15 9:02 ` Guo, Gua
2023-09-15 10:26 ` Sheng Lean Tan
2023-09-15 9:06 ` Lu, James
1 sibling, 1 reply; 10+ messages in thread
From: Guo, Gua @ 2023-09-15 9:02 UTC (permalink / raw)
To: Wang, BruceX, devel@edk2.groups.io; +Cc: Dong, Guo, Rhodes, Sean, Lu, James
Reviewed-by: Gua Guo <gua.guo@intel.com>
-----Original Message-----
From: Wang, BruceX <brucex.wang@intel.com>
Sent: Friday, September 15, 2023 4:58 PM
To: devel@edk2.groups.io
Cc: Wang, BruceX <brucex.wang@intel.com>; Dong, Guo <guo.dong@intel.com>; Rhodes, Sean <sean@starlabs.systems>; Lu, James <james.lu@intel.com>; Guo, Gua <gua.guo@intel.com>
Subject: [PATCH v2 2/2] UefiPayloadPkg: Add FIT support
From: "Brucex.Wang" <brucex.wang@intel.com>
Provide Fit format for UniversalPayload, developer can use argument
"--Fit" to build UniversalPayload.fit
Cc: Guo Dong <guo.dong@intel.com>
Cc: Sean Rhodes <sean@starlabs.systems>
Cc: James Lu <james.lu@intel.com>
Cc: Gua Guo <gua.guo@intel.com>
Signed-off-by: BruceX Wang <brucex.wang@intel.com>
---
.../Include/Guid/UniversalPayloadBase.h | 21 +
UefiPayloadPkg/PayloadLoaderPeim/FitLib.h | 60 ++
.../PayloadLoaderPeim/FitLib/FitLib.c | 127 ++++
.../PayloadLoaderPeim/FitPayloadLoaderPeim.c | 150 ++++
.../FitPayloadLoaderPeim.inf | 59 ++
UefiPayloadPkg/Readme.md | 191 +++++
UefiPayloadPkg/Tools/MkFitImage.py | 272 ++++++++
.../FitUniversalPayloadEntry.c | 654 ++++++++++++++++++
.../FitUniversalPayloadEntry.inf | 98 +++
UefiPayloadPkg/UefiPayloadPkg.dec | 3 +
UefiPayloadPkg/UefiPayloadPkg.dsc | 27 +-
UefiPayloadPkg/UniversalPayloadBuild.py | 328 ++++++---
12 files changed, 1894 insertions(+), 96 deletions(-)
create mode 100644 UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
create mode 100644 UefiPayloadPkg/Readme.md
create mode 100644 UefiPayloadPkg/Tools/MkFitImage.py
create mode 100644 UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
create mode 100644 UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
diff --git a/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
new file mode 100644
index 0000000000..31c9ec0bfb
--- /dev/null
+++ b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
@@ -0,0 +1,21 @@
+/** @file
+ Universal Payload general definitions.
+
+Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Revision Reference:
+ - Universal Payload Specification 0.75 (https://universalpayload.github.io/documentation/)
+**/
+
+#ifndef UNIVERSAL_PAYLOAD_BASE_H_
+#define UNIVERSAL_PAYLOAD_BASE_H_
+
+extern GUID gUniversalPayloadBaseGuid;
+
+typedef struct {
+ UNIVERSAL_PAYLOAD_GENERIC_HEADER Header;
+ EFI_PHYSICAL_ADDRESS Entry;
+} UNIVERSAL_PAYLOAD_BASE;
+
+#endif // UNIVERSAL_PAYLOAD_BASE_H_
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h b/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
new file mode 100644
index 0000000000..0514d675a6
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
@@ -0,0 +1,60 @@
+/** @file
+ FIT Load Image Support
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef FIT_LIB_H_
+#define FIT_LIB_H_
+
+#include <PiPei.h>
+#include <Library/DebugLib.h>
+#include <Library/FdtLib.h>
+
+typedef struct {
+ UINT64 RelocateType;
+ UINT64 Offset;
+} FIT_RELOCATE_ITEM;
+
+typedef struct {
+ EFI_PHYSICAL_ADDRESS ImageBase;
+ EFI_PHYSICAL_ADDRESS PayloadBaseAddress;
+ UINT64 PayloadSize;
+ UINTN PayloadEntryOffset;
+ UINTN PayloadEntrySize;
+ EFI_PHYSICAL_ADDRESS PayloadEntryPoint;
+ UINTN RelocateTableOffset;
+ UINTN RelocateTableCount;
+ EFI_PHYSICAL_ADDRESS PayloadLoadAddress;
+} FIT_IMAGE_CONTEXT;
+
+typedef struct {
+ UINT8 *Name;
+ UINT32 Offset;
+} PROPERTY_DATA;
+
+#define IMAGE_BASE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, ImageBase)
+#define PAYLOAD_BASE_ADDR_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadBaseAddress)
+#define PAYLOAD_BASE_SIZE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadSize)
+#define PAYLOAD_ENTRY_OFFSET_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntryOffset)
+#define PAYLOAD_ENTRY_SIZE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntrySize)
+#define PAYLOAD_ENTRY_POINT_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntryPoint)
+#define RELOCATE_TABLE_OFFSET_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, RelocateTableOffset)
+#define RELOCATE_TABLE_COUNT_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, RelocateTableCount)
+#define PAYLOAD_LOAD_ADDR_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadLoadAddress)
+
+/**
+ Parse the FIT image info.
+ @param[in] ImageBase Memory address of an image.
+ @param[out] Context The FIT image context pointer.
+ @retval EFI_UNSUPPORTED Unsupported binary type.
+ @retval EFI_SUCCESS FIT binary is loaded successfully.
+**/
+EFI_STATUS
+EFIAPI
+ParseFitImage (
+ IN VOID *ImageBase,
+ OUT FIT_IMAGE_CONTEXT *Context
+ );
+
+#endif
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c b/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
new file mode 100644
index 0000000000..9d1d8a4f61
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
@@ -0,0 +1,127 @@
+/** @file
+ FIT Load Image Support
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "FitLib.h"
+
+PROPERTY_DATA PropertyData32List[] = {
+ { "data-offset", PAYLOAD_ENTRY_OFFSET_OFFSET },
+ { "data-size", PAYLOAD_ENTRY_SIZE_OFFSET },
+ { "reloc-start", RELOCATE_TABLE_OFFSET_OFFSET }
+};
+
+PROPERTY_DATA PropertyData64List[] = {
+ { "entry-start", PAYLOAD_ENTRY_POINT_OFFSET },
+ { "load", PAYLOAD_LOAD_ADDR_OFFSET }
+};
+
+/**
+ Parse the target firmware image info in FIT.
+ @param[in] Fdt Memory address of a fdt.
+ @param[in] Firmware Target name of an image.
+ @param[out] Context The FIT image context pointer.
+ @retval EFI_NOT_FOUND FIT node dose not find.
+ @retval EFI_SUCCESS FIT binary is loaded successfully.
+**/
+EFI_STATUS
+EFIAPI
+FitParseFirmwarePropertyData (
+ IN VOID *Fdt,
+ IN CHAR8 *Firmware,
+ OUT FIT_IMAGE_CONTEXT *Context
+ )
+{
+ CONST FDT_PROPERTY *PropertyPtr;
+ INT32 ImageNode;
+ INT32 TianoNode;
+ INT32 TempLen;
+ UINT32 *Data32;
+ UINT64 *Data64;
+ UINT32 *ContextOffset32;
+ UINT64 *ContextOffset64;
+ INT32 Index;
+
+ ImageNode = FdtSubnodeOffsetNameLen (Fdt, 0, "images", (INT32)AsciiStrLen ("images"));
+ if (ImageNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ TianoNode = FdtSubnodeOffsetNameLen (Fdt, ImageNode, Firmware, (INT32)AsciiStrLen (Firmware));
+ if (TianoNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ for (Index = 0; Index < sizeof (PropertyData32List) / sizeof (PROPERTY_DATA); Index++) {
+ PropertyPtr = FdtGetProperty (Fdt, TianoNode, PropertyData32List[Index].Name, &TempLen);
+ Data32 = (UINT32 *)(PropertyPtr->Data);
+ ContextOffset32 = (UINT32 *)((UINTN)Context + PropertyData32List[Index].Offset);
+ *ContextOffset32 = Fdt32ToCpu (*Data32);
+ }
+
+ for (Index = 0; Index < sizeof (PropertyData64List)/sizeof (PROPERTY_DATA); Index++) {
+ PropertyPtr = FdtGetProperty (Fdt, TianoNode, PropertyData64List[Index].Name, &TempLen);
+ Data64 = (UINT64 *)(PropertyPtr->Data);
+ ContextOffset64 = (UINT64 *)((UINTN)Context + PropertyData64List[Index].Offset);
+ *ContextOffset64 = Fdt64ToCpu (*Data64);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Parse the FIT image info.
+ @param[in] ImageBase Memory address of an image.
+ @param[out] Context The FIT image context pointer.
+ @retval EFI_UNSUPPORTED Unsupported binary type.
+ @retval EFI_SUCCESS FIT binary is loaded successfully.
+**/
+EFI_STATUS
+EFIAPI
+ParseFitImage (
+ IN VOID *ImageBase,
+ OUT FIT_IMAGE_CONTEXT *Context
+ )
+{
+ VOID *Fdt;
+ INT32 ConfigNode;
+ INT32 Config1Node;
+ CONST FDT_PROPERTY *PropertyPtr;
+ INT32 TempLen;
+ UINT32 *Data32;
+ UINT64 Value;
+ EFI_STATUS Status;
+ UINTN UplSize;
+ CHAR8 *Firmware;
+
+ Status = FdtCheckHeader (ImageBase);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Fdt = ImageBase;
+ PropertyPtr = FdtGetProperty (Fdt, 0, "size", &TempLen);
+ Data32 = (UINT32 *)(PropertyPtr->Data);
+ UplSize = Value = Fdt32ToCpu (*Data32);
+ ConfigNode = FdtSubnodeOffsetNameLen (Fdt, 0, "configurations", (INT32)AsciiStrLen ("configurations"));
+ if (ConfigNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ Config1Node = FdtSubnodeOffsetNameLen (Fdt, ConfigNode, "conf-1", (INT32)AsciiStrLen ("conf-1"));
+ if (Config1Node <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ PropertyPtr = FdtGetProperty (Fdt, Config1Node, "firmware", &TempLen);
+ Firmware = (CHAR8 *)(PropertyPtr->Data);
+
+ FitParseFirmwarePropertyData (Fdt, Firmware, Context);
+
+ Context->ImageBase = (EFI_PHYSICAL_ADDRESS)ImageBase;
+ Context->PayloadSize = UplSize;
+ Context->RelocateTableCount = (Context->PayloadEntrySize - (Context->RelocateTableOffset - Context->PayloadEntryOffset)) / sizeof (FIT_RELOCATE_ITEM);
+
+ return EFI_SUCCESS;
+}
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
new file mode 100644
index 0000000000..3c5dacbb65
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
@@ -0,0 +1,150 @@
+/** @file
+ ELF Load Image Support
+Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiPei.h>
+#include <UniversalPayload/UniversalPayload.h>
+#include <Guid/UniversalPayloadBase.h>
+#include <UniversalPayload/ExtraData.h>
+
+#include <Ppi/LoadFile.h>
+
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+
+#include "FitLib.h"
+
+/**
+ The wrapper function of PeiLoadImageLoadImage().
+ @param This - Pointer to EFI_PEI_LOAD_FILE_PPI.
+ @param FileHandle - Pointer to the FFS file header of the image.
+ @param ImageAddressArg - Pointer to PE/TE image.
+ @param ImageSizeArg - Size of PE/TE image.
+ @param EntryPoint - Pointer to entry point of specified image file for output.
+ @param AuthenticationState - Pointer to attestation authentication state of image.
+ @return Status of PeiLoadImageLoadImage().
+**/
+EFI_STATUS
+EFIAPI
+PeiLoadFileLoadPayload (
+ IN CONST EFI_PEI_LOAD_FILE_PPI *This,
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL,
+ OUT UINT64 *ImageSizeArg OPTIONAL,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
+ OUT UINT32 *AuthenticationState
+ )
+{
+ EFI_STATUS Status;
+ FIT_IMAGE_CONTEXT Context;
+ UINTN Instance;
+ VOID *Binary;
+ FIT_RELOCATE_ITEM *RelocateTable;
+ UNIVERSAL_PAYLOAD_BASE *PayloadBase;
+ UINTN Length;
+ UINTN Delta;
+ UINTN Index;
+
+ Instance = 0;
+ do {
+ Status = PeiServicesFfsFindSectionData3 (EFI_SECTION_RAW, Instance++, FileHandle, &Binary, AuthenticationState);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ZeroMem (&Context, sizeof (Context));
+ Status = ParseFitImage (Binary, &Context);
+ } while (EFI_ERROR (Status));
+
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "Before Rebase Payload File Base: 0x%08x, File Size: 0x%08X, EntryPoint: 0x%08x\n",
+ Context.PayloadBaseAddress,
+ Context.PayloadSize,
+ Context.PayloadEntryPoint
+ ));
+ Context.PayloadBaseAddress = (EFI_PHYSICAL_ADDRESS)AllocatePages (EFI_SIZE_TO_PAGES (Context.PayloadSize));
+
+ RelocateTable = (FIT_RELOCATE_ITEM *)(UINTN)(Context.PayloadBaseAddress + Context.RelocateTableOffset);
+ CopyMem ((VOID *)Context.PayloadBaseAddress, Binary, Context.PayloadSize);
+
+ if (Context.PayloadBaseAddress > Context.PayloadLoadAddress) {
+ Delta = Context.PayloadBaseAddress - Context.PayloadLoadAddress;
+ Context.PayloadEntryPoint += Delta;
+ for (Index = 0; Index < Context.RelocateTableCount; Index++) {
+ if ((RelocateTable[Index].RelocateType == 10) || (RelocateTable[Index].RelocateType == 3)) {
+ *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) = *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) + Delta;
+ }
+ }
+ } else {
+ Delta = Context.PayloadLoadAddress - Context.PayloadBaseAddress;
+ Context.PayloadEntryPoint -= Delta;
+ for (Index = 0; Index < Context.RelocateTableCount; Index++) {
+ if ((RelocateTable[Index].RelocateType == 10) || (RelocateTable[Index].RelocateType == 3)) {
+ *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) = *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) - Delta;
+ }
+ }
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "After Rebase Payload File Base: 0x%08x, File Size: 0x%08X, EntryPoint: 0x%08x\n",
+ Context.PayloadBaseAddress,
+ Context.PayloadSize,
+ Context.PayloadEntryPoint
+ ));
+
+ Length = sizeof (UNIVERSAL_PAYLOAD_BASE);
+ PayloadBase = BuildGuidHob (
+ &gUniversalPayloadBaseGuid,
+ Length
+ );
+ PayloadBase->Entry = (EFI_PHYSICAL_ADDRESS)Context.ImageBase;
+
+ *ImageAddressArg = Context.PayloadBaseAddress;
+ *ImageSizeArg = Context.PayloadSize;
+ *EntryPoint = Context.PayloadEntryPoint;
+
+ return EFI_SUCCESS;
+}
+
+EFI_PEI_LOAD_FILE_PPI mPeiLoadFilePpi = {
+ PeiLoadFileLoadPayload
+};
+
+EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiLoadFilePpiGuid,
+ &mPeiLoadFilePpi
+};
+
+/**
+ Install Pei Load File PPI.
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+ @retval EFI_SUCESS The entry point executes successfully.
+ @retval Others Some error occurs during the execution of this function.
+**/
+EFI_STATUS
+EFIAPI
+InitializeFitPayloadLoaderPeim (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PeiServicesInstallPpi (&gPpiLoadFilePpiList);
+
+ return Status;
+}
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
new file mode 100644
index 0000000000..acb0e09f68
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
@@ -0,0 +1,59 @@
+## @file
+# Produce LoadFile PPI for payload loading.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FitPayloadLoaderPeim
+ FILE_GUID = 55AC82C8-FC17-4C56-BCDA-990BB0A73E41
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InitializeFitPayloadLoaderPeim
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ FitPayloadLoaderPeim.c
+ FitLib.h
+ FitLib/FitLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ PcAtChipsetPkg/PcAtChipsetPkg.dec
+ UefiPayloadPkg/UefiPayloadPkg.dec
+
+[LibraryClasses]
+ PcdLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ PeiServicesLib
+ HobLib
+ BaseLib
+ PeimEntryPoint
+ DebugLib
+ FdtLib
+
+[Ppis]
+ gEfiPeiLoadFilePpiGuid ## PRODUCES
+
+[Pcd]
+ gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister
+ gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister
+
+[Guids]
+ gUniversalPayloadExtraDataGuid ## PRODUCES
+ gUniversalPayloadBaseGuid ## PRODUCES
+
+[Depex]
+ TRUE
diff --git a/UefiPayloadPkg/Readme.md b/UefiPayloadPkg/Readme.md
new file mode 100644
index 0000000000..616a5dd467
--- /dev/null
+++ b/UefiPayloadPkg/Readme.md
@@ -0,0 +1,191 @@
+# UefiPayloadPkg
+Provide UEFI Universal Payload for different bootloader to generate EFI environment
+
+# Spec
+
+UniversalPayload URL: https://universalscalablefirmware.github.io/documentation/2_universal_payload.html
+
+ELF Format URL: https://refspecs.linuxfoundation.org/elf/elf.pdf
+
+FIT Format URL: https://universalpayload.github.io/spec/chapter2-payload-image-format.html
+
+# Uefi UniversalPayload Format
+ | Binary Format | HandOffPayload - HOB |
+ |---------------|----------------------|
+ | ELF | V (Default) |
+ | FIT | V |
+
+# Binary Format
+ - ELF
+ ```
+ + +-----------------------+
+ | | UniversalPayloadEntry | <----------- UefiPayloadPkg\UefiPayloadEntry\UniversalPayloadEntry.c:_ModuleEntryPoint (HOB)
+ | +-----------------------+
+ | | .upld_info | patch it directly
+ ELF Format | +-----------------------+
+ | | .upld.uefi_fv | patch it directly
+ | +-----------------------+
+ | | .upld.bds_fv | patch it directly
+ | +-----------------------+
+ | | .upld.<afpx>_fv | patch it directly
+ + +-----------------------+
+ ```
+
+ - FIT
+ ```
+ + +-----------------------+
+ FIT Data | | FIT Header | <----------- Generate by pylibfdt
+ + +-----------------------+
+ PECOFF Format | | UniversalPayloadEntry | <----------- UefiPayloadPkg\UefiPayloadEntry\FitUniversalPayloadEntry.c:_ModuleEntryPoint (HOB)
+ + +-----------------------+
+ Relocate Data | | reloc-start |
+ + +-----------------------+
+ | | uefi_fv | patch it directly
+ | +-----------------------+
+ Multi Binary | | bds_fv | patch it directly
+ | +-----------------------+
+ | | afp_xxx_fv | patch it directly
+ | +-----------------------+
+ | | afp_xxx_fv | patch it directly
+ + +-----------------------+
+ ```
+
+# Environment
+ - ELF
+ ```
+ Download and install https://github.com/llvm/llvm-project/releases/tag/llvmorg-10.0.1
+ ```
+ - FIT
+ - Windows
+ ```powershell
+ Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
+ choco install dtc-msys2
+ pip3 install pefile
+ pip3 install swig
+ pip3 install pylibfdt
+ ```
+ - Ubuntu
+ ```bash
+ sudo apt install -y u-boot-tools
+ pip3 install pefile
+ pip3 install swig
+ pip3 install pylibfdt
+ ```
+# How to build UEFI UniversalPayload
+ - Windows
+ - edksetup Rebuild
+ - Linux
+ - make -C BaseTools
+ - source edksetup.sh
+
+ - UniversalPayload.elf
+ - python UefiPayloadPkg/UniversalPayloadBuild.py -t <TOOL_CHAIN_TAG>
+ - llvm-objdump -h Build/UefiPayloadPkgX64/UniversalPayload.elf
+
+ - UniversalPayload.fit
+ - python UefiPayloadPkg/UniversalPayloadBuild.py -t <TOOL_CHAIN_TAG> --Fit
+ - fdtdump Build/UefiPayloadPkgX64/UniversalPayload.fit
+
+# Edk2boot + UefiUniversalPayload
+ELF Edk2boot use below way to support compress and sign.
+
+- ELF Behavior - Edk2boot + UefiUniversalPayload.elf
+ ```
+ Boot Flow
+ +-------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+-------------------+
+ | Platform Init | Universal Loader Interface | OS |
+ +-------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+-------------------+
+ HOBs
+ SEC -> PEI -> DXE -> DXE IPL -> UefiPayloadPkg\PayloadLoaderPeim\PayloadLoaderPeim.c ------------------------------------------------------------------------------------> Load UniversalPayload.elf -> Operation System
+
+
+ | Platform Initialize - Edk2 | UniversalPayload - Edk2 |
+ +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
+
+ Binary Format
+
+ +-------------------+
+ | BIOS.rom |
+ +-------------------+
+ | Other Firmware |
+ +-------------------+
+ | ... | FMMT UniversalPayloadBuild.py
+ +-------------------+<----------------+-----------------------+ GenFfs +-----------------------+ Rsa2048Sha256 Sign +-----------------------+ LzmaCompress +----------------------+ GenSec +--------------------------------+
+ | | | EDK2 FFS Header |<-----------| Rsa2048Sha256 Hash |<--------------------| UniversalPayload.lzma |<--------------| EDK2 SEC Header |<--------| UniversalPayload.elf |
+ | RAW Data | +-----------------------+ +-----------------------+ +-----------------------+ +----------------------+ +--------------------------------+
+ | | | Rsa2048Sha256 Hash | | UniversalPayload.lzma | | UniversalPayload.elf | | upld_info |
+ | | +-----------------------+ +-----------------------+ +----------------------+ +--------------------------------+
+ | | | UniversalPayload.lzma | | upld_info | | upld.uefi_fv |
+ +-------------------+<----------------+-----------------------+ +----------------------+ +--------------------------------+
+ | ... | | upld.uefi_fv | | upld.bds_fv |
+ +-------------------+ +----------------------+ +--------------------------------+
+ | Other Firmware | | upld.bds_fv | | upld.AFP1 |
+ +-------------------+ +----------------------+ +--------------------------------+
+ | upld.AFP1 | | upld.AFP2 |
+ +----------------------+ +--------------------------------+
+ | upld.AFP2 | | ... |
+ +----------------------+ +--------------------------------+
+ | ... | | upld.AFPn |
+ +----------------------+ +--------------------------------+
+ | upld.AFPn |
+ +----------------------+
+ ```
+
+FIT Edk2boot use below way to support compress and sign
+- FIT Behavior - Edk2boot + UefiUniversalPayload.fit
+ ```
+ Boot Flow
+ +-------------------------------------------------------------------------------------+------------------------------------------------------------------------+-------------------+
+ | Platform Init | Universal Loader Interface | OS |
+ +-------------------------------------------------------------------------------------+------------------------------------------------------------------------+-------------------+
+ HOBs
+ SEC -> PEI -> DXE -> DXE IPL -> *UefiPayloadPkg\PayloadLoaderPeim\PayloadLoaderPeim.c ----------------------------------------------> Load UniversalPayload.fit -> Operation System
+
+ Binary Format
+
+ | Platform Initialize - Edk2 | UniversalPayload - Edk2 (UniversalPayloadBuild.py --Fit) |
+ +---------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
+
+ +-------------------+
+ | BIOS.rom |
+ +-------------------+
+ | Other Firmware |
+ +-------------------+
+ | ... | FMMT UniversalPayloadBuild.py --Fit tianocore -> data-offset
+ +-------------------+<----------------+--------------------------------+ GenFfs +--------------------------------+ GenSec +--------------------------------+ tianocore -> reloc-start +--------------------------+
+ | | | EDK2 FFS Header |<--------| EDK2 SEC Header |<--------| FIT Header |<-------------------------| UniversalPayload.pecoff |
+ | | +--------------------------------+ +--------------------------------+ | description = "Uefi Payload"; | +--------------------------+
+ | | | EDK2 SEC Header | | FIT Header | | ... |
+ | RAW Data | +--------------------------------+ | | | images { | uefi-fv -> data-offset +--------------------------+
+ | | | FIT Header | | | | tianocore {...}; |<-------------------------| uefi_fv |
+ | | | | +--------------------------------+ | uefi-fv {...}; | bds-fv -> data-offset +--------------------------+
+ | | | | | tianocore -> data | | bds-fv {...}; |<-------------------------| bds_fv |
+ | | +--------------------------------+ +--------------------------------+ | afp1-fv {...}; | AFP1 -> data-offset +--------------------------+
+ | | | tianocore -> data | | tianocore -> reloc-start | | ... |<-------------------------| AFP1 |
+ | | +--------------------------------+ +--------------------------------+ | afpn-fv {...}; | AFP2 -> data-offset +--------------------------+
+ | | | tianocore -> reloc-start | | uefi-fv -> data | | } |<-------------------------| AFP2 |
+ | | +--------------------------------+ +--------------------------------+ | configurations { | ... +--------------------------+
+ | | | uefi-fv -> data | | bds-fv -> data | | conf-1 {...} |<-------------------------| ... |
+ | | +--------------------------------+ +--------------------------------+ | } | AFPn -> data-offset +--------------------------+
+ | | | bds-fv -> data | | AFP1-fv -> data | | |<-------------------------| AFPn |
+ | | +--------------------------------+ +--------------------------------+ | | +--------------------------+
+ | | | AFP1-fv -> data | | AFP2-fv -> data | | |
+ | | +--------------------------------+ +--------------------------------+ +--------------------------------+
+ | | | AFP2-fv -> data | | ... | | tianocore -> data |
+ | | +--------------------------------+ +--------------------------------+ +--------------------------------+
+ | | | ... | | AFPn-fv -> data | | tianocore -> reloc-start |
+ | | +--------------------------------+ +--------------------------------+ +--------------------------------+
+ | | | AFPn-fv -> data | | uefi-fv -> data |
+ +-------------------+<----------------+--------------------------------+ +--------------------------------+
+ | ... | | bds-fv -> data |
+ +-------------------+ +--------------------------------+
+ | Other Firmware | | AFP1-fv -> data |
+ +-------------------+ +--------------------------------+
+ | AFP2-fv -> data |
+ +--------------------------------+
+ | ... |
+ +--------------------------------+
+ | AFPn-fv -> data |
+ +--------------------------------+
+
+ ```
diff --git a/UefiPayloadPkg/Tools/MkFitImage.py b/UefiPayloadPkg/Tools/MkFitImage.py
new file mode 100644
index 0000000000..82ab933d6d
--- /dev/null
+++ b/UefiPayloadPkg/Tools/MkFitImage.py
@@ -0,0 +1,272 @@
+## @file
+# This file is a script to build fit image.
+# It generate a dtb header and combine a binary file after this header.
+#
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+from os.path import exists
+import libfdt
+from ctypes import *
+import time
+
+class FIT_IMAGE_INFO_HEADER:
+ """Class for user setting data to use MakeFitImage()
+ """
+ _pack_ = 1
+ _fields_ = [
+ ('Compatible', str),
+ ('UplVersion', int),
+ ('Description', str),
+ ('Type', str),
+ ('Arch', str),
+ ('Compression', str),
+ ('Revision', int),
+ ('BuildType', str),
+ ('Capabilities', str),
+ ('Producer', str),
+ ('ImageId', str),
+ ('DataOffset', int),
+ ('DataSize', int),
+ ('RelocStart', int),
+ ('LoadAddr', int),
+ ('Entry', int),
+ ('Binary', str),
+ ('TargetPath', str),
+ ('UefifvPath', str),
+ ('BdsfvPath', str),
+ ('NetworkfvPath', str),
+ ('Project', str),
+ ]
+
+ def __init__(self):
+ self.Compatible = 'universal-payload'
+ self.UplVersion = 0x0100
+ self.TargetPath = 'mkimage.fit'
+
+def CreatFdt(Fdt):
+ FdtEmptyTree = libfdt.fdt_create_empty_tree(Fdt, len(Fdt))
+ if FdtEmptyTree != 0:
+ print('\n- Failed - Create Fdt failed!')
+ return False
+ return True
+
+def BuildConfNode(Fdt, ParentNode, MultiImage):
+ ConfNode1 = libfdt.fdt_add_subnode(Fdt, ParentNode, 'conf-1')
+
+ libfdt.fdt_setprop(Fdt, ConfNode1, 'require-fit', b'', 0)
+ libfdt.fdt_setprop(Fdt, ConfNode1, 'firmware', bytes('tianocore', 'utf-8'), len('tianocore') + 1)
+
+def BuildFvImageNode(Fdt, InfoHeader, ParentNode, DataOffset, DataSize, Description):
+ libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-size', DataSize)
+ libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-offset', DataOffset)
+ libfdt.fdt_setprop(Fdt, ParentNode, 'compression', bytes('none', 'utf-8'), len('none') + 1)
+ libfdt.fdt_setprop(Fdt, ParentNode, 'project ', bytes('tianocore', 'utf-8'), len('tianocore') + 1)
+ libfdt.fdt_setprop(Fdt, ParentNode, 'arch', bytes('x86_64', 'utf-8'), len('x86_64') + 1)
+ libfdt.fdt_setprop(Fdt, ParentNode, 'type', bytes('flat-binary', 'utf-8'), len('flat-binary') + 1)
+ libfdt.fdt_setprop(Fdt, ParentNode, 'description', bytes(Description, 'utf-8'), len(Description) + 1)
+
+def BuildTianoImageNode(Fdt, InfoHeader, ParentNode, DataOffset, DataSize, Description):
+ #
+ # Set 'load' and 'data-offset' to reserve the memory first.
+ # They would be set again when Fdt completes or this function parses target binary file.
+ #
+ if InfoHeader.LoadAddr is not None:
+ libfdt.fdt_setprop_u64(Fdt, ParentNode, 'load', InfoHeader.LoadAddr)
+ if InfoHeader.Entry is not None:
+ libfdt.fdt_setprop_u64(Fdt, ParentNode, 'entry-start', InfoHeader.Entry)
+ if InfoHeader.RelocStart is not None:
+ libfdt.fdt_setprop_u32(Fdt, ParentNode, 'reloc-start', InfoHeader.RelocStart)
+ if InfoHeader.DataSize is not None:
+ libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-size', DataSize)
+ if InfoHeader.DataOffset is not None:
+ libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-offset', DataOffset)
+ if InfoHeader.Producer is not None:
+ libfdt.fdt_setprop(Fdt, ParentNode, 'producer ', bytes(InfoHeader.Producer, 'utf-8'), len(InfoHeader.Producer) + 1)
+ if InfoHeader.Capabilities is not None:
+ CapStrs = ','.join(InfoHeader.Capabilities)
+ libfdt.fdt_setprop(Fdt, ParentNode, 'capabilities ', bytes(CapStrs, 'utf-8'), len(CapStrs) + 1)
+ if InfoHeader.Type is not None:
+ libfdt.fdt_setprop(Fdt, ParentNode, 'type ', bytes(InfoHeader.Type, 'utf-8'), len(InfoHeader.Type) + 1)
+ if InfoHeader.Arch is not None:
+ libfdt.fdt_setprop(Fdt, ParentNode, 'arch ', bytes(InfoHeader.Arch, 'utf-8'), len(InfoHeader.Arch) + 1)
+ if InfoHeader.Project is not None:
+ libfdt.fdt_setprop(Fdt, ParentNode, 'project ', bytes(InfoHeader.Project, 'utf-8'), len(InfoHeader.Project) + 1)
+ if InfoHeader.Description is not None:
+ libfdt.fdt_setprop(Fdt, ParentNode, 'description', bytes(Description, 'utf-8'), len(Description) + 1)
+
+#
+# The subnode would be inserted from bottom to top of structure block.
+#
+def BuildFitImage(Fdt, InfoHeader):
+ MultiImage = [
+ ["tianocore", InfoHeader.Binary, BuildTianoImageNode , InfoHeader.Description, None, 0 ],
+ ["uefi-fv", InfoHeader.UefifvPath, BuildFvImageNode, "UEFI Firmware Volume", None, 0 ],
+ ["bds-fv", InfoHeader.BdsfvPath, BuildFvImageNode , "BDS Firmware Volume", None, 0 ],
+ ["network-fv", InfoHeader.NetworkfvPath, BuildFvImageNode , "Network Firmware Volume", None, 0 ],
+ ]
+
+ #
+ # Set basic information
+ #
+ libfdt.fdt_setprop_u32(Fdt, 0, 'build-revision ', InfoHeader.Revision)
+ libfdt.fdt_setprop_u32(Fdt, 0, 'spec-version', InfoHeader.UplVersion)
+
+ #
+ # Build configurations node
+ #
+ ConfNode = libfdt.fdt_add_subnode(Fdt, 0, 'configurations')
+ BuildConfNode(Fdt, ConfNode, MultiImage)
+
+ # Build image
+ DataOffset = InfoHeader.DataOffset
+ for Index in range (0, len (MultiImage)):
+ _, Path, _, _, _, _ = MultiImage[Index]
+ if exists(Path) == 1:
+ TempBinary = open(Path, 'rb')
+ BinaryData = TempBinary.read()
+ TempBinary.close()
+ MultiImage[Index][-2] = BinaryData
+ MultiImage[Index][-1] = DataOffset
+ DataOffset += len (BinaryData)
+ libfdt.fdt_setprop_u32(Fdt, 0, 'size', DataOffset)
+ posix_time = int(time.time())
+ libfdt.fdt_setprop_u32(Fdt, 0, 'timestamp', posix_time)
+ DescriptionFit = 'Uefi OS Loader'
+ libfdt.fdt_setprop(Fdt, 0, 'description', bytes(DescriptionFit, 'utf-8'), len(DescriptionFit) + 1)
+
+ ImageNode = libfdt.fdt_add_subnode(Fdt, 0, 'images')
+ for Item in reversed (MultiImage):
+ Name, Path, BuildFvNode, Description, BinaryData, DataOffset = Item
+ FvNode = libfdt.fdt_add_subnode(Fdt, ImageNode, Name)
+ BuildFvNode (Fdt, InfoHeader, FvNode, DataOffset, len(BinaryData), Description)
+
+ #
+ # Create new image file and combine all binary.
+ #
+ DtbFile = open(InfoHeader.TargetPath, "wb")
+ DtbFile.truncate()
+ DtbFile.write(Fdt)
+ for Item in MultiImage:
+ _, _, _, _, BinaryData, _ = Item
+ DtbFile.write(BinaryData)
+ DtbFile.close()
+
+ return True
+
+def MakeFitImage(InfoHeader):
+ #
+ # Allocate fdt byte array.
+ #
+ Fdt = bytearray(InfoHeader.DataOffset)
+
+ #
+ # Create fdt empty tree.
+ #
+ if CreatFdt(Fdt) is False:
+ return False
+
+ #
+ # Parse args to build fit image.
+ #
+ return BuildFitImage(Fdt, InfoHeader)
+
+def ReplaceFv (UplBinary, SectionFvFile, SectionName):
+ try:
+ #
+ # Get Original Multi Fv
+ #
+ with open (UplBinary, "rb") as File:
+ Dtb = File.read ()
+ Fit = libfdt.Fdt (Dtb)
+ NewFitHeader = bytearray(Dtb[0:Fit.totalsize()])
+ FitSize = len(Dtb)
+
+ LoadablesList = []
+ ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'images')
+ FvNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, 'uefi-fv')
+ NodeDepth = libfdt.fdt_node_depth (NewFitHeader, ImagesNode)
+ node_name = libfdt.fdt_get_name(NewFitHeader, FvNode)
+ FvNode = libfdt.fdt_next_node(NewFitHeader, FvNode, NodeDepth)
+
+ while node_name[0][-2:] == 'fv':
+ LoadablesList.append (node_name[0])
+ node_name = libfdt.fdt_get_name(NewFitHeader, FvNode[0])
+ FvNode = libfdt.fdt_next_node(NewFitHeader, FvNode[0], NodeDepth)
+ #
+ # Get current Fit Binary FV data
+ #
+ MultiFvList = []
+ for Item in LoadablesList:
+ ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, Item)
+ ImageOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big')
+ ImageSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-size')[0], 'big')
+ MultiFvList.append ([Item, Dtb[ImageOffset:ImageOffset + ImageSize]])
+
+ IsFvExist = False
+ for Index in range (0, len (MultiFvList)):
+ if MultiFvList[Index][0] == SectionName:
+ with open (SectionFvFile, 'rb') as File:
+ MultiFvList[Index][1] = File.read ()
+ ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, SectionName)
+ ImageSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-size')[0], 'big')
+ ReplaceOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big')
+ OffsetDelta = len(MultiFvList[Index][1]) - ImageSize
+ FitSize += OffsetDelta
+ IsFvExist = True
+ libfdt.fdt_setprop_u32(NewFitHeader, ImageNode, 'data-size', len(MultiFvList[Index][1]))
+
+ #
+ # Update new fit header
+ #
+ ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'images')
+ if (IsFvExist == False):
+ with open (SectionFvFile, 'rb') as File:
+ SectionFvFileBinary = File.read ()
+ MultiFvList.append ([SectionName, SectionFvFileBinary])
+ FvNode = libfdt.fdt_add_subnode(NewFitHeader, ImagesNode, SectionName)
+ BuildFvImageNode (NewFitHeader, None, FvNode, FitSize, len(SectionFvFileBinary), SectionName + " Firmware Volume")
+ FitSize += len(SectionFvFileBinary)
+ else:
+ for Index in range (0, len (MultiFvList)):
+ ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, MultiFvList[Index][0])
+ ImageOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big')
+ if ImageOffset > ReplaceOffset:
+ libfdt.fdt_setprop_u32(NewFitHeader, ImageNode, 'data-offset', ImageOffset + OffsetDelta)
+
+ ConfNodes = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'configurations')
+ libfdt.fdt_setprop(NewFitHeader, ConfNodes, 'default ', bytes('conf-1', 'utf-8'), len('conf-1') + 1)
+ ConfNode = libfdt.fdt_subnode_offset(NewFitHeader, ConfNodes, 'conf-1')
+
+ libfdt.fdt_setprop_u32(NewFitHeader, 0, 'size', FitSize)
+
+ #
+ # Generate new fit image
+ #
+ ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'images')
+ TianoNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, 'tianocore')
+ TianoOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, TianoNode, 'data-offset')[0], 'big')
+ TianoSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, TianoNode, 'data-size')[0], 'big')
+ TianoBinary = Dtb[TianoOffset:TianoOffset + TianoSize]
+
+ print("\nGenerate new fit image:")
+ NewUplBinary = bytearray(FitSize)
+ print("Update fit header\t to 0x0\t\t ~ " + str(hex(len(NewFitHeader))))
+ NewUplBinary[:len(NewFitHeader)] = NewFitHeader
+ print("Update tiano image\t to " + str(hex(len(NewFitHeader))) + "\t ~ " + str(hex(len(NewFitHeader) + len(TianoBinary))))
+ NewUplBinary[len(NewFitHeader):len(NewFitHeader) + len(TianoBinary)] = TianoBinary
+ for Index in range (0, len (MultiFvList)):
+ ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, MultiFvList[Index][0])
+ ImageOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big')
+ ImageSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-size')[0], 'big')
+ NewUplBinary[ImageOffset:ImageOffset + ImageSize] = MultiFvList[Index][1]
+ print("Update " + MultiFvList[Index][0] + "\t\t to " + str(hex(ImageOffset)) + "\t ~ " + str(hex(ImageOffset + ImageSize)))
+
+ with open (UplBinary, "wb") as File:
+ File.write (NewUplBinary)
+
+ return 0
+ except Exception as Ex:
+ print(Ex)
+ return 1
diff --git a/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
new file mode 100644
index 0000000000..a53d988627
--- /dev/null
+++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
@@ -0,0 +1,654 @@
+/** @file
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "UefiPayloadEntry.h"
+#include <Library/FdtLib.h>
+#include <Guid/UniversalPayloadBase.h>
+
+#define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
+ EFI_RESOURCE_ATTRIBUTE_TESTED | \
+ EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \
+ EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \
+ EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \
+ EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED | \
+ EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
+ EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
+ EFI_RESOURCE_ATTRIBUTE_64_BIT_IO | \
+ EFI_RESOURCE_ATTRIBUTE_PERSISTENT )
+
+#define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
+ EFI_RESOURCE_ATTRIBUTE_TESTED )
+
+extern VOID *mHobList;
+
+CHAR8 *mLineBuffer = NULL;
+
+/**
+ Print all HOBs info from the HOB list.
+ @return The pointer to the HOB list.
+**/
+VOID
+PrintHob (
+ IN CONST VOID *HobStart
+ );
+
+/**
+ Find the first substring.
+ @param String Point to the string where to find the substring.
+ @param CharSet Point to the string to be found.
+**/
+UINTN
+EFIAPI
+AsciiStrSpn (
+ IN CHAR8 *String,
+ IN CHAR8 *CharSet
+ )
+{
+ UINTN Count;
+ CHAR8 *Str1;
+ CHAR8 *Str2;
+
+ Count = 0;
+
+ for (Str1 = String; *Str1 != L'\0'; Str1++) {
+ for (Str2 = CharSet; *Str2 != L'\0'; Str2++) {
+ if (*Str1 == *Str2) {
+ break;
+ }
+ }
+
+ if (*Str2 == L'\0') {
+ return Count;
+ }
+
+ Count++;
+ }
+
+ return Count;
+}
+
+/**
+ Searches a string for the first occurrence of a character contained in a
+ specified buffer.
+ @param String Point to the string where to find the substring.
+ @param CharSet Point to the string to be found.
+**/
+CHAR8 *
+EFIAPI
+AsciiStrBrk (
+ IN CHAR8 *String,
+ IN CHAR8 *CharSet
+ )
+{
+ CHAR8 *Str1;
+ CHAR8 *Str2;
+
+ for (Str1 = String; *Str1 != L'\0'; Str1++) {
+ for (Str2 = CharSet; *Str2 != L'\0'; Str2++) {
+ if (*Str1 == *Str2) {
+ return (CHAR8 *)Str1;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ Find the next token after one or more specified characters.
+ @param String Point to the string where to find the substring.
+ @param CharSet Point to the string to be found.
+**/
+CHAR8 *
+EFIAPI
+AsciiStrTokenLine (
+ IN CHAR8 *String OPTIONAL,
+ IN CHAR8 *CharSet
+ )
+{
+ CHAR8 *Begin;
+ CHAR8 *End;
+
+ Begin = (String == NULL) ? mLineBuffer : String;
+ if (Begin == NULL) {
+ return NULL;
+ }
+
+ Begin += AsciiStrSpn (Begin, CharSet);
+ if (*Begin == L'\0') {
+ mLineBuffer = NULL;
+ return NULL;
+ }
+
+ End = AsciiStrBrk (Begin, CharSet);
+ if ((End != NULL) && (*End != L'\0')) {
+ *End = L'\0';
+ End++;
+ }
+
+ mLineBuffer = End;
+ return Begin;
+}
+
+/**
+ Some bootloader may pass a pcd database, and UPL also contain a PCD database.
+ Dxe PCD driver has the assumption that the two PCD database can be catenated and
+ the local token number should be successive.
+ This function will fix up the UPL PCD database to meet that assumption.
+ @param[in] DxeFv The FV where to find the Universal PCD database.
+ @retval EFI_SUCCESS If it completed successfully.
+ @retval other Failed to fix up.
+**/
+EFI_STATUS
+FixUpPcdDatabase (
+ IN EFI_FIRMWARE_VOLUME_HEADER *DxeFv
+ )
+{
+ EFI_STATUS Status;
+ EFI_FFS_FILE_HEADER *FileHeader;
+ VOID *PcdRawData;
+ PEI_PCD_DATABASE *PeiDatabase;
+ PEI_PCD_DATABASE *UplDatabase;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ DYNAMICEX_MAPPING *ExMapTable;
+ UINTN Index;
+
+ GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);
+ if (GuidHob == NULL) {
+ //
+ // No fix-up is needed.
+ //
+ return EFI_SUCCESS;
+ }
+
+ PeiDatabase = (PEI_PCD_DATABASE *)GET_GUID_HOB_DATA (GuidHob);
+ DEBUG ((DEBUG_INFO, "Find the Pei PCD data base, the total local token number is %d\n", PeiDatabase->LocalTokenCount));
+
+ Status = FvFindFileByTypeGuid (DxeFv, EFI_FV_FILETYPE_DRIVER, PcdGetPtr (PcdPcdDriverFile), &FileHeader);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = FileFindSection (FileHeader, EFI_SECTION_RAW, &PcdRawData);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ UplDatabase = (PEI_PCD_DATABASE *)PcdRawData;
+ ExMapTable = (DYNAMICEX_MAPPING *)(UINTN)((UINTN)PcdRawData + UplDatabase->ExMapTableOffset);
+
+ for (Index = 0; Index < UplDatabase->ExTokenCount; Index++) {
+ ExMapTable[Index].TokenNumber += PeiDatabase->LocalTokenCount;
+ }
+
+ DEBUG ((DEBUG_INFO, "Fix up UPL PCD database successfully\n"));
+ return EFI_SUCCESS;
+}
+
+/**
+ Add HOB into HOB list
+ @param[in] Hob The HOB to be added into the HOB list.
+**/
+VOID
+AddNewHob (
+ IN EFI_PEI_HOB_POINTERS *Hob
+ )
+{
+ EFI_PEI_HOB_POINTERS NewHob;
+
+ if (Hob->Raw == NULL) {
+ return;
+ }
+
+ NewHob.Header = CreateHob (Hob->Header->HobType, Hob->Header->HobLength);
+
+ if (NewHob.Header != NULL) {
+ CopyMem (NewHob.Header + 1, Hob->Header + 1, Hob->Header->HobLength - sizeof (EFI_HOB_GENERIC_HEADER));
+ }
+}
+
+/**
+ Found the Resource Descriptor HOB that contains a range (Base, Top)
+ @param[in] HobList Hob start address
+ @param[in] Base Memory start address
+ @param[in] Top Memory end address.
+ @retval The pointer to the Resource Descriptor HOB.
+**/
+EFI_HOB_RESOURCE_DESCRIPTOR *
+FindResourceDescriptorByRange (
+ IN VOID *HobList,
+ IN EFI_PHYSICAL_ADDRESS Base,
+ IN EFI_PHYSICAL_ADDRESS Top
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
+
+ for (Hob.Raw = (UINT8 *)HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
+ //
+ // Skip all HOBs except Resource Descriptor HOBs
+ //
+ if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+ continue;
+ }
+
+ //
+ // Skip Resource Descriptor HOBs that do not describe tested system memory
+ //
+ ResourceHob = Hob.ResourceDescriptor;
+ if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
+ continue;
+ }
+
+ if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
+ continue;
+ }
+
+ //
+ // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
+ //
+ if (Base < ResourceHob->PhysicalStart) {
+ continue;
+ }
+
+ if (Top > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) {
+ continue;
+ }
+
+ return ResourceHob;
+ }
+
+ return NULL;
+}
+
+/**
+ Find the highest below 4G memory resource descriptor, except the input Resource Descriptor.
+ @param[in] HobList Hob start address
+ @param[in] MinimalNeededSize Minimal needed size.
+ @param[in] ExceptResourceHob Ignore this Resource Descriptor.
+ @retval The pointer to the Resource Descriptor HOB.
+**/
+EFI_HOB_RESOURCE_DESCRIPTOR *
+FindAnotherHighestBelow4GResourceDescriptor (
+ IN VOID *HobList,
+ IN UINTN MinimalNeededSize,
+ IN EFI_HOB_RESOURCE_DESCRIPTOR *ExceptResourceHob
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
+ EFI_HOB_RESOURCE_DESCRIPTOR *ReturnResourceHob;
+
+ ReturnResourceHob = NULL;
+
+ for (Hob.Raw = (UINT8 *)HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
+ //
+ // Skip all HOBs except Resource Descriptor HOBs
+ //
+ if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+ continue;
+ }
+
+ //
+ // Skip Resource Descriptor HOBs that do not describe tested system memory
+ //
+ ResourceHob = Hob.ResourceDescriptor;
+ if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
+ continue;
+ }
+
+ if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
+ continue;
+ }
+
+ //
+ // Skip if the Resource Descriptor HOB equals to ExceptResourceHob
+ //
+ if (ResourceHob == ExceptResourceHob) {
+ continue;
+ }
+
+ //
+ // Skip Resource Descriptor HOBs that are beyond 4G
+ //
+ if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > BASE_4GB) {
+ continue;
+ }
+
+ //
+ // Skip Resource Descriptor HOBs that are too small
+ //
+ if (ResourceHob->ResourceLength < MinimalNeededSize) {
+ continue;
+ }
+
+ //
+ // Return the topest Resource Descriptor
+ //
+ if (ReturnResourceHob == NULL) {
+ ReturnResourceHob = ResourceHob;
+ } else {
+ if (ReturnResourceHob->PhysicalStart < ResourceHob->PhysicalStart) {
+ ReturnResourceHob = ResourceHob;
+ }
+ }
+ }
+
+ return ReturnResourceHob;
+}
+
+/**
+ Check the HOB and decide if it is need inside Payload
+ Payload maintainer may make decision which HOB is need or needn't
+ Then add the check logic in the function.
+ @param[in] Hob The HOB to check
+ @retval TRUE If HOB is need inside Payload
+ @retval FALSE If HOB is needn't inside Payload
+**/
+BOOLEAN
+IsHobNeed (
+ EFI_PEI_HOB_POINTERS Hob
+ )
+{
+ if (Hob.Header->HobType == EFI_HOB_TYPE_HANDOFF) {
+ return FALSE;
+ }
+
+ if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
+ if (CompareGuid (&Hob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) {
+ return FALSE;
+ }
+ }
+
+ // Arrive here mean the HOB is need
+ return TRUE;
+}
+
+/**
+ It will build Fv HOBs based on information from bootloaders.
+ @param[out] DxeFv The pointer to the DXE FV in memory.
+ @retval EFI_SUCCESS If it completed successfully.
+ @retval EFI_NOT_FOUND If it failed to find node in fit image.
+ @retval Others If it failed to build required HOBs.
+**/
+EFI_STATUS
+BuildFitLoadablesFvHob (
+ OUT EFI_FIRMWARE_VOLUME_HEADER **DxeFv
+ )
+{
+ EFI_STATUS Status;
+ VOID *Fdt;
+ UINT8 *GuidHob;
+ UNIVERSAL_PAYLOAD_BASE *PayloadBase;
+ INT32 ConfigNode;
+ INT32 Config1Node;
+ INT32 ImageNode;
+ INT32 FvNode;
+ INT32 Depth;
+ CONST FDT_PROPERTY *PropertyPtr;
+ INT32 TempLen;
+ CONST CHAR8 *Fvname;
+ UINT32 DataOffset;
+ UINT32 DataSize;
+ UINT32 *Data32;
+
+ GuidHob = GetFirstGuidHob (&gUniversalPayloadBaseGuid);
+ if (GuidHob != NULL) {
+ PayloadBase = (UNIVERSAL_PAYLOAD_BASE *)GET_GUID_HOB_DATA (GuidHob);
+ Fdt = (VOID *)(UINTN)PayloadBase->Entry;
+ DEBUG ((DEBUG_INFO, "PayloadBase Entry = 0x%08x\n", PayloadBase->Entry));
+ }
+
+ Status = FdtCheckHeader (Fdt);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ ConfigNode = FdtSubnodeOffsetNameLen (Fdt, 0, "configurations", (INT32)AsciiStrLen ("configurations"));
+ if (ConfigNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ Config1Node = FdtSubnodeOffsetNameLen (Fdt, ConfigNode, "conf-1", (INT32)AsciiStrLen ("conf-1"));
+ if (Config1Node <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ ImageNode = FdtSubnodeOffsetNameLen (Fdt, 0, "images", (INT32)AsciiStrLen ("images"));
+ if (ImageNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ FvNode = FdtSubnodeOffsetNameLen (Fdt, ImageNode, "tianocore", (INT32)AsciiStrLen ("tianocore"));
+ Depth = FdtNodeDepth (Fdt, FvNode);
+ FvNode = FdtNextNode (Fdt, FvNode, &Depth);
+ Fvname = FdtGetName (Fdt, FvNode, &TempLen);
+ while ((AsciiStrCmp ((Fvname + AsciiStrLen (Fvname) - 2), "fv") == 0)) {
+ if (FvNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ PropertyPtr = FdtGetProperty (Fdt, FvNode, "data-offset", &TempLen);
+ Data32 = (UINT32 *)(PropertyPtr->Data);
+ DataOffset = SwapBytes32 (*Data32);
+
+ PropertyPtr = FdtGetProperty (Fdt, FvNode, "data-size", &TempLen);
+ Data32 = (UINT32 *)(PropertyPtr->Data);
+ DataSize = SwapBytes32 (*Data32);
+
+ if (AsciiStrCmp (Fvname, "uefi-fv") == 0) {
+ *DxeFv = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)PayloadBase->Entry + (UINTN)DataOffset);
+ ASSERT ((*DxeFv)->FvLength == DataSize);
+ } else {
+ BuildFvHob (((UINTN)PayloadBase->Entry + (UINTN)DataOffset), DataSize);
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "UPL Multiple fv[%a], Base=0x%08x, size=0x%08x\n",
+ Fvname,
+ ((UINTN)PayloadBase->Entry + (UINTN)DataOffset),
+ DataSize,
+ DataOffset
+ ));
+ Depth = FdtNodeDepth (Fdt, FvNode);
+ FvNode = FdtNextNode (Fdt, FvNode, &Depth);
+ Fvname = FdtGetName (Fdt, FvNode, &TempLen);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ It will build HOBs based on information from bootloaders.
+ @param[in] BootloaderParameter The starting memory address of bootloader parameter block.
+ @param[out] DxeFv The pointer to the DXE FV in memory.
+ @retval EFI_SUCCESS If it completed successfully.
+ @retval Others If it failed to build required HOBs.
+**/
+EFI_STATUS
+BuildHobs (
+ IN UINTN BootloaderParameter,
+ OUT EFI_FIRMWARE_VOLUME_HEADER **DxeFv
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ UINTN MinimalNeededSize;
+ EFI_PHYSICAL_ADDRESS FreeMemoryBottom;
+ EFI_PHYSICAL_ADDRESS FreeMemoryTop;
+ EFI_PHYSICAL_ADDRESS MemoryBottom;
+ EFI_PHYSICAL_ADDRESS MemoryTop;
+ EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob;
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
+ UINT8 *GuidHob;
+ EFI_HOB_FIRMWARE_VOLUME *FvHob;
+ UNIVERSAL_PAYLOAD_ACPI_TABLE *AcpiTable;
+ ACPI_BOARD_INFO *AcpiBoardInfo;
+ EFI_HOB_HANDOFF_INFO_TABLE *HobInfo;
+
+ Hob.Raw = (UINT8 *)BootloaderParameter;
+ MinimalNeededSize = FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
+
+ ASSERT (Hob.Raw != NULL);
+ ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryTop == Hob.HandoffInformationTable->EfiFreeMemoryTop);
+ ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryTop == Hob.HandoffInformationTable->EfiMemoryTop);
+ ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryBottom == Hob.HandoffInformationTable->EfiFreeMemoryBottom);
+ ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryBottom == Hob.HandoffInformationTable->EfiMemoryBottom);
+
+ //
+ // Try to find Resource Descriptor HOB that contains Hob range EfiMemoryBottom..EfiMemoryTop
+ //
+ PhitResourceHob = FindResourceDescriptorByRange (Hob.Raw, Hob.HandoffInformationTable->EfiMemoryBottom, Hob.HandoffInformationTable->EfiMemoryTop);
+ if (PhitResourceHob == NULL) {
+ //
+ // Boot loader's Phit Hob is not in an available Resource Descriptor, find another Resource Descriptor for new Phit Hob
+ //
+ ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, MinimalNeededSize, NULL);
+ if (ResourceHob == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ MemoryBottom = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize;
+ FreeMemoryBottom = MemoryBottom;
+ FreeMemoryTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength;
+ MemoryTop = FreeMemoryTop;
+ } else if (PhitResourceHob->PhysicalStart + PhitResourceHob->ResourceLength - Hob.HandoffInformationTable->EfiMemoryTop >= MinimalNeededSize) {
+ //
+ // New availiable Memory range in new hob is right above memory top in old hob.
+ //
+ MemoryBottom = Hob.HandoffInformationTable->EfiFreeMemoryTop;
+ FreeMemoryBottom = Hob.HandoffInformationTable->EfiMemoryTop;
+ FreeMemoryTop = FreeMemoryBottom + MinimalNeededSize;
+ MemoryTop = FreeMemoryTop;
+ } else if (Hob.HandoffInformationTable->EfiMemoryBottom - PhitResourceHob->PhysicalStart >= MinimalNeededSize) {
+ //
+ // New availiable Memory range in new hob is right below memory bottom in old hob.
+ //
+ MemoryBottom = Hob.HandoffInformationTable->EfiMemoryBottom - MinimalNeededSize;
+ FreeMemoryBottom = MemoryBottom;
+ FreeMemoryTop = Hob.HandoffInformationTable->EfiMemoryBottom;
+ MemoryTop = Hob.HandoffInformationTable->EfiMemoryTop;
+ } else {
+ //
+ // In the Resource Descriptor HOB contains boot loader Hob, there is no enough free memory size for payload hob
+ // Find another Resource Descriptor Hob
+ //
+ ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, MinimalNeededSize, PhitResourceHob);
+ if (ResourceHob == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ MemoryBottom = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize;
+ FreeMemoryBottom = MemoryBottom;
+ FreeMemoryTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength;
+ MemoryTop = FreeMemoryTop;
+ }
+
+ HobInfo = HobConstructor ((VOID *)(UINTN)MemoryBottom, (VOID *)(UINTN)MemoryTop, (VOID *)(UINTN)FreeMemoryBottom, (VOID *)(UINTN)FreeMemoryTop);
+ HobInfo->BootMode = Hob.HandoffInformationTable->BootMode;
+ //
+ // From now on, mHobList will point to the new Hob range.
+ //
+
+ //
+ // Create an empty FvHob for the DXE FV that contains DXE core.
+ //
+ BuildFvHob ((EFI_PHYSICAL_ADDRESS)0, 0);
+ //
+ // Since payload created new Hob, move all hobs except PHIT from boot loader hob list.
+ //
+ while (!END_OF_HOB_LIST (Hob)) {
+ if (IsHobNeed (Hob)) {
+ // Add this hob to payload HOB
+ AddNewHob (&Hob);
+ }
+
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ }
+
+ BuildFitLoadablesFvHob (DxeFv);
+
+ //
+ // Create guid hob for acpi board information
+ //
+ GuidHob = GetFirstGuidHob (&gUniversalPayloadAcpiTableGuid);
+ if (GuidHob != NULL) {
+ AcpiTable = (UNIVERSAL_PAYLOAD_ACPI_TABLE *)GET_GUID_HOB_DATA (GuidHob);
+ GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid);
+ if (GuidHob == NULL) {
+ AcpiBoardInfo = BuildHobFromAcpi ((UINT64)AcpiTable->Rsdp);
+ ASSERT (AcpiBoardInfo != NULL);
+ }
+ }
+
+ //
+ // Update DXE FV information to first fv hob in the hob list, which
+ // is the empty FvHob created before.
+ //
+ FvHob = GetFirstHob (EFI_HOB_TYPE_FV);
+ FvHob->BaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)*DxeFv;
+ FvHob->Length = (*DxeFv)->FvLength;
+ return EFI_SUCCESS;
+}
+
+/**
+ Entry point to the C language phase of UEFI payload.
+ @param[in] BootloaderParameter The starting address of bootloader parameter block.
+ @retval It will not return if SUCCESS, and return error when passing bootloader parameter.
+**/
+EFI_STATUS
+EFIAPI
+_ModuleEntryPoint (
+ IN UINTN BootloaderParameter
+ )
+{
+ EFI_STATUS Status;
+ PHYSICAL_ADDRESS DxeCoreEntryPoint;
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_FIRMWARE_VOLUME_HEADER *DxeFv;
+
+ mHobList = (VOID *)BootloaderParameter;
+ DxeFv = NULL;
+ // Call constructor for all libraries
+ ProcessLibraryConstructorList ();
+
+ DEBUG ((DEBUG_INFO, "Entering Universal Payload...\n"));
+ DEBUG ((DEBUG_INFO, "sizeof(UINTN) = 0x%x\n", sizeof (UINTN)));
+
+ DEBUG_CODE (
+ //
+ // Dump the Hobs from boot loader
+ //
+ PrintHob (mHobList);
+ );
+
+ // Initialize floating point operating environment to be compliant with UEFI spec.
+ InitializeFloatingPointUnits ();
+
+ // Build HOB based on information from Bootloader
+ Status = BuildHobs (BootloaderParameter, &DxeFv);
+ ASSERT_EFI_ERROR (Status);
+
+ FixUpPcdDatabase (DxeFv);
+ Status = UniversalLoadDxeCore (DxeFv, &DxeCoreEntryPoint);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Mask off all legacy 8259 interrupt sources
+ //
+ IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF);
+ IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF);
+
+ Hob.HandoffInformationTable = (EFI_HOB_HANDOFF_INFO_TABLE *)GetFirstHob (EFI_HOB_TYPE_HANDOFF);
+ HandOffToDxeCore (DxeCoreEntryPoint, Hob);
+
+ // Should not get here
+ CpuDeadLoop ();
+ return EFI_SUCCESS;
+}
diff --git a/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
new file mode 100644
index 0000000000..a7d1a8c9e5
--- /dev/null
+++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
@@ -0,0 +1,98 @@
+## @file
+# This is the first module for UEFI payload.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FitUniversalPayloadEntry
+ FILE_GUID = CED5A8A9-B6EA-4D5A-8689-577EE88566CF
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ FitUniversalPayloadEntry.c
+ LoadDxeCore.c
+ MemoryAllocation.c
+ PrintHob.c
+ AcpiTable.c
+
+[Sources.Ia32]
+ X64/VirtualMemory.h
+ X64/VirtualMemory.c
+ Ia32/DxeLoadFunc.c
+ Ia32/IdtVectorAsm.nasm
+
+[Sources.X64]
+ X64/VirtualMemory.h
+ X64/VirtualMemory.c
+ X64/DxeLoadFunc.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ UefiPayloadPkg/UefiPayloadPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ BaseLib
+ SerialPortLib
+ IoLib
+ HobLib
+ PeCoffLib
+ CpuLib
+ FdtLib
+
+[Guids]
+ gEfiMemoryTypeInformationGuid
+ gEfiFirmwareFileSystem2Guid
+ gEfiGraphicsInfoHobGuid
+ gEfiGraphicsDeviceInfoHobGuid
+ gUefiAcpiBoardInfoGuid
+ gEfiSmbiosTableGuid
+ gUefiSerialPortInfoGuid
+ gUniversalPayloadExtraDataGuid
+ gUniversalPayloadBaseGuid
+ gPcdDataBaseHobGuid
+ gUniversalPayloadSmbiosTableGuid
+ gEfiHobMemoryAllocBspStoreGuid
+ gUniversalPayloadAcpiTableGuid
+ gUniversalPayloadPciRootBridgeInfoGuid
+ gUniversalPayloadSmbios3TableGuid
+
+[FeaturePcd.IA32]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES
+
+[FeaturePcd.X64]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables ## CONSUMES
+
+
+[Pcd.IA32,Pcd.X64]
+ gUefiPayloadPkgTokenSpaceGuid.PcdPcdDriverFile
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize ## CONSUMES
+
+ gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase
+ gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize
+ gUefiPayloadPkgTokenSpaceGuid.PcdSystemMemoryUefiRegionSize
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy ## SOMETIMES_CONSUMES
diff --git a/UefiPayloadPkg/UefiPayloadPkg.dec b/UefiPayloadPkg/UefiPayloadPkg.dec
index e2e4a79db3..2f1fd82487 100644
--- a/UefiPayloadPkg/UefiPayloadPkg.dec
+++ b/UefiPayloadPkg/UefiPayloadPkg.dec
@@ -24,6 +24,9 @@
#
gUefiPayloadPkgTokenSpaceGuid = {0x1d127ea, 0xf6f1, 0x4ef6, {0x94, 0x15, 0x8a, 0x0, 0x0, 0x93, 0xf8, 0x9d}}
+ ## Include/Guid/UniversalPayloadBase.h
+ gUniversalPayloadBaseGuid = { 0x03d4c61d, 0x2713, 0x4ec5, {0xa1, 0xcc, 0x88, 0x3b, 0xe9, 0xdc, 0x18, 0xe5 } }
+
#
# Gop Temp
#
diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc b/UefiPayloadPkg/UefiPayloadPkg.dsc
index 47812048dd..af9308ef8e 100644
--- a/UefiPayloadPkg/UefiPayloadPkg.dsc
+++ b/UefiPayloadPkg/UefiPayloadPkg.dsc
@@ -30,7 +30,6 @@
DEFINE PS2_KEYBOARD_ENABLE = FALSE
DEFINE RAM_DISK_ENABLE = FALSE
DEFINE SIO_BUS_ENABLE = FALSE
- DEFINE UNIVERSAL_PAYLOAD = FALSE
DEFINE SECURITY_STUB_ENABLE = TRUE
DEFINE SMM_SUPPORT = FALSE
DEFINE PLATFORM_BOOT_TIMEOUT = 3
@@ -44,6 +43,14 @@
DEFINE BOOTSPLASH_IMAGE = FALSE
DEFINE NVME_ENABLE = TRUE
DEFINE CAPSULE_SUPPORT = FALSE
+ #
+ # Setup Universal Payload
+ #
+ # ELF: Build UniversalPayload file as UniversalPayload.elf
+ # FIT: Build UniversalPayload file as UniversalPayload.fit
+ #
+ DEFINE UNIVERSAL_PAYLOAD = FALSE
+ DEFINE UNIVERSAL_PAYLOAD_FORMAT = ELF
#
# NULL: NullMemoryTestDxe
@@ -311,7 +318,7 @@
VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf
CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
-
+ FdtLib|MdePkg/Library/BaseFdtLib/BaseFdtLib.inf
[LibraryClasses.common]
!if $(BOOTSPLASH_IMAGE)
SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
@@ -600,14 +607,26 @@
!if "IA32" in "$(ARCH)"
[Components.IA32]
!if $(UNIVERSAL_PAYLOAD) == TRUE
- UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
+ !if $(UNIVERSAL_PAYLOAD_FORMAT) == "ELF"
+ UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
+ !elseif $(UNIVERSAL_PAYLOAD_FORMAT) == "FIT"
+ UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
+ !else
+ UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
+ !endif
!else
UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
!endif
!else
[Components.X64]
!if $(UNIVERSAL_PAYLOAD) == TRUE
- UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
+ !if $(UNIVERSAL_PAYLOAD_FORMAT) == "ELF"
+ UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
+ !elseif $(UNIVERSAL_PAYLOAD_FORMAT) == "FIT"
+ UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
+ !else
+ UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
+ !endif
!else
UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
!endif
diff --git a/UefiPayloadPkg/UniversalPayloadBuild.py b/UefiPayloadPkg/UniversalPayloadBuild.py
index 47f37b3377..9a83fc9e44 100644
--- a/UefiPayloadPkg/UniversalPayloadBuild.py
+++ b/UefiPayloadPkg/UniversalPayloadBuild.py
@@ -10,10 +10,22 @@ import subprocess
import os
import shutil
import sys
+import pathlib
from ctypes import *
-from Tools.ElfFv import ReplaceFv
+
sys.dont_write_bytecode = True
+class bcolors:
+ HEADER = '\033[95m'
+ OKBLUE = '\033[94m'
+ OKCYAN = '\033[96m'
+ OKGREEN = '\033[92m'
+ WARNING = '\033[93m'
+ FAIL = '\033[91m'
+ ENDC = '\033[0m'
+ BOLD = '\033[1m'
+ UNDERLINE = '\033[4m'
+
class UPLD_INFO_HEADER(LittleEndianStructure):
_pack_ = 1
_fields_ = [
@@ -36,40 +48,114 @@ class UPLD_INFO_HEADER(LittleEndianStructure):
self.ImageId = b'UEFI'
self.ProducerId = b'INTEL'
-def BuildUniversalPayload(Args):
- def RunCommand(cmd):
- print(cmd)
- p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,cwd=os.environ['WORKSPACE'])
- while True:
- line = p.stdout.readline()
- if not line:
- break
- print(line.strip().decode(errors='ignore'))
-
- p.communicate()
- if p.returncode != 0:
- print("- Failed - error happened when run command: %s"%cmd)
- raise Exception("ERROR: when run command: %s"%cmd)
+def ValidateSpecRevision (Argument):
+ try:
+ (MajorStr, MinorStr) = Argument.split('.')
+ except:
+ raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
+ #
+ # Spec Revision Bits 15 : 8 - Major Version. Bits 7 : 0 - Minor Version.
+ #
+ if len(MinorStr) > 0 and len(MinorStr) < 3:
+ try:
+ Minor = int(MinorStr, 16) if len(MinorStr) == 2 else (int(MinorStr, 16) << 4)
+ except:
+ raise argparse.ArgumentTypeError ('{} Minor version of SpecRevision is not a valid integer value.'.format (Argument))
+ else:
+ raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
+
+ if len(MajorStr) > 0 and len(MajorStr) < 3:
+ try:
+ Major = int(MajorStr, 16)
+ except:
+ raise argparse.ArgumentTypeError ('{} Major version of SpecRevision is not a valid integer value.'.format (Argument))
+ else:
+ raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
+
+ return int('0x{0:02x}{1:02x}'.format(Major, Minor), 0)
+
+def Validate32BitInteger (Argument):
+ try:
+ Value = int (Argument, 0)
+ except:
+ raise argparse.ArgumentTypeError ('{} is not a valid integer value.'.format (Argument))
+ if Value < 0:
+ raise argparse.ArgumentTypeError ('{} is a negative value.'.format (Argument))
+ if Value > 0xffffffff:
+ raise argparse.ArgumentTypeError ('{} is larger than 32-bits.'.format (Argument))
+ return Value
+def ValidateAddFv (Argument):
+ Value = Argument.split ("=")
+ if len (Value) != 2:
+ raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
+ if Value[0][-3:] != "_fv":
+ raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
+ if Value[1][-3:].lower () != ".fv":
+ raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
+ if os.path.exists (Value[1]) == False:
+ raise argparse.ArgumentTypeError ('File {} is not found.'.format (Value[1]))
+ return Value
+
+def RunCommand(cmd):
+ print(cmd)
+ p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,cwd=os.environ['WORKSPACE'])
+ while True:
+ line = p.stdout.readline()
+ if not line:
+ break
+ print(line.strip().decode(errors='ignore'))
+
+ p.communicate()
+ if p.returncode != 0:
+ print("- Failed - error happened when run command: %s"%cmd)
+ raise Exception("ERROR: when run command: %s"%cmd)
+
+def BuildUniversalPayload(Args):
BuildTarget = Args.Target
ToolChain = Args.ToolChain
Quiet = "--quiet" if Args.Quiet else ""
- ElfToolChain = 'CLANGDWARF'
- BuildDir = os.path.join(os.environ['WORKSPACE'], os.path.normpath("Build/UefiPayloadPkgX64"))
- BuildModule = ""
- BuildArch = ""
+ if Args.Fit == True:
+ PayloadEntryToolChain = ToolChain
+ Args.Macro.append("UNIVERSAL_PAYLOAD_FORMAT=FIT")
+ UpldEntryFile = "FitUniversalPayloadEntry"
+ else:
+ PayloadEntryToolChain = 'CLANGDWARF'
+ Args.Macro.append("UNIVERSAL_PAYLOAD_FORMAT=ELF")
+ UpldEntryFile = "UniversalPayloadEntry"
+
+ BuildDir = os.path.join(os.environ['WORKSPACE'], os.path.normpath("Build/UefiPayloadPkgX64"))
if Args.Arch == 'X64':
BuildArch = "X64"
- EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ElfToolChain), os.path.normpath("X64/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll"))
+ FitArch = "x86_64"
+ ObjCopyFlag = "elf64-x86-64"
+ EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, PayloadEntryToolChain), os.path.normpath("X64/UefiPayloadPkg/UefiPayloadEntry/{}/DEBUG/{}.dll".format (UpldEntryFile, UpldEntryFile)))
else:
BuildArch = "IA32 -a X64"
- EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ElfToolChain), os.path.normpath("IA32/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll"))
+ FitArch = "x86"
+ ObjCopyFlag = "elf32-i386"
+ EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, PayloadEntryToolChain), os.path.normpath("IA32/UefiPayloadPkg/UefiPayloadEntry/{}/DEBUG/{}.dll".format (UpldEntryFile, UpldEntryFile)))
+ EntryModuleInf = os.path.normpath("UefiPayloadPkg/UefiPayloadEntry/{}.inf".format (UpldEntryFile))
DscPath = os.path.normpath("UefiPayloadPkg/UefiPayloadPkg.dsc")
+ DxeFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv"))
+ BdsFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv"))
+ NetworkFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv"))
+ PayloadReportPath = os.path.join(BuildDir, "UefiUniversalPayload.txt")
ModuleReportPath = os.path.join(BuildDir, "UefiUniversalPayloadEntry.txt")
UpldInfoFile = os.path.join(BuildDir, "UniversalPayloadInfo.bin")
+ if "CLANG_BIN" in os.environ:
+ LlvmObjcopyPath = os.path.join(os.environ["CLANG_BIN"], "llvm-objcopy")
+ else:
+ LlvmObjcopyPath = "llvm-objcopy"
+ try:
+ RunCommand('"%s" --version'%LlvmObjcopyPath)
+ except:
+ print("- Failed - Please check if LLVM is installed or if CLANG_BIN is set correctly")
+ sys.exit(1)
+
Pcds = ""
if (Args.pcd != None):
for PcdItem in Args.pcd:
@@ -84,7 +170,6 @@ def BuildUniversalPayload(Args):
# Building DXE core and DXE drivers as DXEFV.
#
if Args.BuildEntryOnly == False:
- PayloadReportPath = os.path.join(BuildDir, "UefiUniversalPayload.txt")
BuildPayload = "build -p {} -b {} -a X64 -t {} -y {} {}".format (DscPath, BuildTarget, ToolChain, PayloadReportPath, Quiet)
BuildPayload += Pcds
BuildPayload += Defines
@@ -93,94 +178,138 @@ def BuildUniversalPayload(Args):
# Building Universal Payload entry.
#
if Args.PreBuildUplBinary is None:
- EntryModuleInf = os.path.normpath("UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf")
- BuildModule = "build -p {} -b {} -a {} -m {} -t {} -y {} {}".format (DscPath, BuildTarget, BuildArch, EntryModuleInf, ElfToolChain, ModuleReportPath, Quiet)
+ BuildModule = "build -p {} -b {} -a {} -m {} -t {} -y {} {}".format (DscPath, BuildTarget, BuildArch, EntryModuleInf, PayloadEntryToolChain, ModuleReportPath, Quiet)
BuildModule += Pcds
BuildModule += Defines
RunCommand(BuildModule)
if Args.PreBuildUplBinary is not None:
- EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.elf")
+ if Args.Fit == False:
+ EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.elf")
+ else:
+ EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.fit")
shutil.copy (os.path.abspath(Args.PreBuildUplBinary), EntryOutputDir)
#
- # Buid Universal Payload Information Section ".upld_info"
+ # Build Universal Payload Information Section ".upld_info"
#
- upld_info_hdr = UPLD_INFO_HEADER()
- upld_info_hdr.SpecRevision = Args.SpecRevision
- upld_info_hdr.Revision = Args.Revision
- upld_info_hdr.ProducerId = Args.ProducerId.encode()[:16]
- upld_info_hdr.ImageId = Args.ImageId.encode()[:16]
- upld_info_hdr.Attribute |= 1 if BuildTarget == "DEBUG" else 0
- fp = open(UpldInfoFile, 'wb')
- fp.write(bytearray(upld_info_hdr))
- fp.close()
+ if Args.Fit == False:
+ upld_info_hdr = UPLD_INFO_HEADER()
+ upld_info_hdr.SpecRevision = Args.SpecRevision
+ upld_info_hdr.Revision = Args.Revision
+ upld_info_hdr.ProducerId = Args.ProducerId.encode()[:16]
+ upld_info_hdr.ImageId = Args.ImageId.encode()[:16]
+ upld_info_hdr.Attribute |= 1 if BuildTarget == "DEBUG" else 0
+ fp = open(UpldInfoFile, 'wb')
+ fp.write(bytearray(upld_info_hdr))
+ fp.close()
+
+ if Args.BuildEntryOnly == False:
+ import Tools.ElfFv as ElfFv
+ ElfFv.ReplaceFv (EntryOutputDir, UpldInfoFile, '.upld_info', Alignment = 4)
+ if Args.Fit == False:
+ shutil.copy (EntryOutputDir, os.path.join(BuildDir, 'UniversalPayload.elf'))
+ else:
+ shutil.copy (EntryOutputDir, os.path.join(BuildDir, 'UniversalPayload.fit'))
MultiFvList = []
if Args.BuildEntryOnly == False:
MultiFvList = [
- ['uefi_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv")) ],
- ['bds_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv")) ],
- ['network_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv")) ],
+ ['uefi_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv")) ],
+ ['bds_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv")) ],
+ ['network_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv"))],
]
- AddSectionName = '.upld_info'
- ReplaceFv (EntryOutputDir, UpldInfoFile, AddSectionName, Alignment = 4)
- if Args.PreBuildUplBinary is None:
- shutil.copy (EntryOutputDir, os.path.join(BuildDir, 'UniversalPayload.elf'))
- return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.elf')
+ if Args.Fit == True:
+ import Tools.MkFitImage as MkFitImage
+ import pefile
+ fit_image_info_header = MkFitImage.FIT_IMAGE_INFO_HEADER()
+ fit_image_info_header.Description = 'Uefi Universal Payload'
+ fit_image_info_header.UplVersion = Args.SpecRevision
+ fit_image_info_header.Type = 'flat-binary'
+ fit_image_info_header.Arch = FitArch
+ fit_image_info_header.Compression = 'none'
+ fit_image_info_header.Revision = Args.Revision
+ fit_image_info_header.BuildType = Args.Target.lower()
+ fit_image_info_header.Capabilities = None
+ fit_image_info_header.Producer = Args.ProducerId.lower()
+ fit_image_info_header.ImageId = Args.ImageId.lower()
+ fit_image_info_header.Binary = os.path.join(BuildDir, 'UniversalPayload.fit')
+ fit_image_info_header.TargetPath = os.path.join(BuildDir, 'UniversalPayload.fit')
+ fit_image_info_header.UefifvPath = DxeFvOutputDir
+ fit_image_info_header.BdsfvPath = BdsFvOutputDir
+ fit_image_info_header.NetworkfvPath = NetworkFvOutputDir
+ fit_image_info_header.DataOffset = 0x1000
+ fit_image_info_header.LoadAddr = Args.LoadAddress
+ fit_image_info_header.Project = 'tianocore'
+
+ TargetRebaseFile = fit_image_info_header.Binary.replace (pathlib.Path(fit_image_info_header.Binary).suffix, ".pecoff")
+ TargetRebaseEntryFile = fit_image_info_header.Binary.replace (pathlib.Path(fit_image_info_header.Binary).suffix, ".entry")
+
-def main():
- def ValidateSpecRevision (Argument):
- try:
- (MajorStr, MinorStr) = Argument.split('.')
- except:
- raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
#
- # Spec Revision Bits 15 : 8 - Major Version. Bits 7 : 0 - Minor Version.
+ # Rebase PECOFF to load address
#
- if len(MinorStr) > 0 and len(MinorStr) < 3:
- try:
- Minor = int(MinorStr, 16) if len(MinorStr) == 2 else (int(MinorStr, 16) << 4)
- except:
- raise argparse.ArgumentTypeError ('{} Minor version of SpecRevision is not a valid integer value.'.format (Argument))
- else:
- raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
+ RunCommand (
+ "GenFw -e SEC -o {} {}".format (
+ TargetRebaseFile,
+ fit_image_info_header.Binary
+ ))
+ RunCommand (
+ "GenFw --rebase 0x{:02X} -o {} {} ".format (
+ fit_image_info_header.LoadAddr + fit_image_info_header.DataOffset,
+ TargetRebaseFile,
+ TargetRebaseFile,
+ ))
- if len(MajorStr) > 0 and len(MajorStr) < 3:
- try:
- Major = int(MajorStr, 16)
- except:
- raise argparse.ArgumentTypeError ('{} Major version of SpecRevision is not a valid integer value.'.format (Argument))
- else:
- raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
+ #
+ # Open PECOFF relocation table binary.
+ #
+ RelocBinary = b''
+ PeCoff = pefile.PE (TargetRebaseFile)
+ for reloc in PeCoff.DIRECTORY_ENTRY_BASERELOC:
+ for entry in reloc.entries:
+ if (entry.type == 0):
+ continue
+ Type = entry.type
+ Offset = entry.rva + fit_image_info_header.DataOffset
+ RelocBinary += Type.to_bytes (8, 'little') + Offset.to_bytes (8, 'little')
+ RelocBinary += b'\x00' * (0x1000 - (len(RelocBinary) % 0x1000))
- return int('0x{0:02x}{1:02x}'.format(Major, Minor), 0)
+ #
+ # Output UniversalPayload.entry
+ #
+ TempBinary = open (TargetRebaseFile, 'rb')
+ TianoBinary = TempBinary.read ()
+ TempBinary.close ()
- def Validate32BitInteger (Argument):
- try:
- Value = int (Argument, 0)
- except:
- raise argparse.ArgumentTypeError ('{} is not a valid integer value.'.format (Argument))
- if Value < 0:
- raise argparse.ArgumentTypeError ('{} is a negative value.'.format (Argument))
- if Value > 0xffffffff:
- raise argparse.ArgumentTypeError ('{} is larger than 32-bits.'.format (Argument))
- return Value
-
- def ValidateAddFv (Argument):
- Value = Argument.split ("=")
- if len (Value) != 2:
- raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
- if Value[0][-3:] != "_fv":
- raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
- if Value[1][-3:].lower () != ".fv":
- raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
- if os.path.exists (Value[1]) == False:
- raise argparse.ArgumentTypeError ('File {} is not found.'.format (Value[1]))
- return Value
+ TianoEntryBinary = TianoBinary + RelocBinary
+ TianoEntryBinary += (b'\x00' * (0x1000 - (len(TianoBinary) % 0x1000)))
+ TianoEntryBinarySize = len (TianoEntryBinary)
+
+ TempBinary = open(TargetRebaseEntryFile, "wb")
+ TempBinary.truncate()
+ TempBinary.write(TianoEntryBinary)
+ TempBinary.close()
+
+ #
+ # Calculate entry and update relocation table start address and data-size.
+ #
+ fit_image_info_header.Entry = PeCoff.OPTIONAL_HEADER.ImageBase + PeCoff.OPTIONAL_HEADER.AddressOfEntryPoint
+ fit_image_info_header.RelocStart = fit_image_info_header.DataOffset + len(TianoBinary)
+ fit_image_info_header.DataSize = TianoEntryBinarySize
+ fit_image_info_header.Binary = TargetRebaseEntryFile
+
+ if MkFitImage.MakeFitImage(fit_image_info_header) is True:
+ print('\nSuccessfully build Fit Image')
+ else:
+ sys.exit(1)
+ return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.fit')
+ else:
+ return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.elf')
+def main():
parser = argparse.ArgumentParser(description='For building Universal Payload')
parser.add_argument('-t', '--ToolChain')
parser.add_argument('-b', '--Target', default='DEBUG')
@@ -192,13 +321,16 @@ def main():
parser.add_argument("-s", "--SpecRevision", type=ValidateSpecRevision, default ='0.7', help='Indicates compliance with a revision of this specification in the BCD format.')
parser.add_argument("-r", "--Revision", type=Validate32BitInteger, default ='0x0000010105', help='Revision of the Payload binary. Major.Minor.Revision.Build')
parser.add_argument("-o", "--ProducerId", default ='INTEL', help='A null-terminated OEM-supplied string that identifies the payload producer (16 bytes maximal).')
+ parser.add_argument("-e", "--BuildEntryOnly", action='store_true', help='Build UniversalPayload Entry file')
+ parser.add_argument("-pb", "--PreBuildUplBinary", default=None, help='Specify the UniversalPayload file')
parser.add_argument("-sk", "--SkipBuild", action='store_true', help='Skip UniversalPayload build')
parser.add_argument("-af", "--AddFv", type=ValidateAddFv, action='append', help='Add or replace specific FV into payload, Ex: uefi_fv=XXX.fv')
- command_group = parser.add_mutually_exclusive_group()
- command_group.add_argument("-e", "--BuildEntryOnly", action='store_true', help='Build UniversalPayload Entry file')
- command_group.add_argument("-pb", "--PreBuildUplBinary", default=None, help='Specify the UniversalPayload file')
+ parser.add_argument("-f", "--Fit", action='store_true', help='Build UniversalPayload file as UniversalPayload.fit', default=False)
+ parser.add_argument('-l', "--LoadAddress", type=int, help='Specify payload load address', default =0x000800000)
+
args = parser.parse_args()
+
MultiFvList = []
UniversalPayloadBinary = args.PreBuildUplBinary
if (args.SkipBuild == False):
@@ -208,12 +340,24 @@ def main():
for (SectionName, SectionFvFile) in args.AddFv:
MultiFvList.append ([SectionName, SectionFvFile])
+ def ReplaceFv (UplBinary, SectionFvFile, SectionName):
+ print (bcolors.OKGREEN + "Patch {}={} into {}".format (SectionName, SectionFvFile, UplBinary) + bcolors.ENDC)
+ if (args.Fit == False):
+ import Tools.ElfFv as ElfFv
+ return ElfFv.ReplaceFv (UplBinary, SectionFvFile, '.upld.{}'.format (SectionName))
+ else:
+ import Tools.MkFitImage as MkFitImage
+ return MkFitImage.ReplaceFv (UplBinary, SectionFvFile, SectionName)
+
if (UniversalPayloadBinary != None):
for (SectionName, SectionFvFile) in MultiFvList:
if os.path.exists (SectionFvFile) == False:
continue
- print ("Patch {}={} into {}".format (SectionName, SectionFvFile, UniversalPayloadBinary))
- ReplaceFv (UniversalPayloadBinary, SectionFvFile, '.upld.{}'.format (SectionName))
+
+ status = ReplaceFv (UniversalPayloadBinary, SectionFvFile, SectionName.replace ("_", "-"))
+ if status != 0:
+ print (bcolors.FAIL + "[Fail] Patch {}={}".format (SectionName, SectionFvFile) + bcolors.ENDC)
+ return status
print ("\nSuccessfully build Universal Payload")
--
2.39.1.windows.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#108699): https://edk2.groups.io/g/devel/message/108699
Mute This Topic: https://groups.io/mt/101375948/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [edk2-devel] [PATCH v2 2/2] UefiPayloadPkg: Add FIT support
2023-09-15 8:58 ` [edk2-devel] [PATCH v2 2/2] UefiPayloadPkg: Add FIT support brucex.wang
2023-09-15 9:02 ` Guo, Gua
@ 2023-09-15 9:06 ` Lu, James
1 sibling, 0 replies; 10+ messages in thread
From: Lu, James @ 2023-09-15 9:06 UTC (permalink / raw)
To: Wang, BruceX, devel@edk2.groups.io; +Cc: Dong, Guo, Rhodes, Sean, Guo, Gua
Reviewed-by: James Lu <james.lu@intel.com>
Thanks,
James
-----Original Message-----
From: Wang, BruceX <brucex.wang@intel.com>
Sent: Friday, September 15, 2023 4:58 PM
To: devel@edk2.groups.io
Cc: Wang, BruceX <brucex.wang@intel.com>; Dong, Guo <guo.dong@intel.com>; Rhodes, Sean <sean@starlabs.systems>; Lu, James <james.lu@intel.com>; Guo, Gua <gua.guo@intel.com>
Subject: [PATCH v2 2/2] UefiPayloadPkg: Add FIT support
From: "Brucex.Wang" <brucex.wang@intel.com>
Provide Fit format for UniversalPayload, developer can use argument
"--Fit" to build UniversalPayload.fit
Cc: Guo Dong <guo.dong@intel.com>
Cc: Sean Rhodes <sean@starlabs.systems>
Cc: James Lu <james.lu@intel.com>
Cc: Gua Guo <gua.guo@intel.com>
Signed-off-by: BruceX Wang <brucex.wang@intel.com>
---
.../Include/Guid/UniversalPayloadBase.h | 21 +
UefiPayloadPkg/PayloadLoaderPeim/FitLib.h | 60 ++
.../PayloadLoaderPeim/FitLib/FitLib.c | 127 ++++
.../PayloadLoaderPeim/FitPayloadLoaderPeim.c | 150 ++++
.../FitPayloadLoaderPeim.inf | 59 ++
UefiPayloadPkg/Readme.md | 191 +++++
UefiPayloadPkg/Tools/MkFitImage.py | 272 ++++++++
.../FitUniversalPayloadEntry.c | 654 ++++++++++++++++++
.../FitUniversalPayloadEntry.inf | 98 +++
UefiPayloadPkg/UefiPayloadPkg.dec | 3 +
UefiPayloadPkg/UefiPayloadPkg.dsc | 27 +-
UefiPayloadPkg/UniversalPayloadBuild.py | 328 ++++++---
12 files changed, 1894 insertions(+), 96 deletions(-)
create mode 100644 UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
create mode 100644 UefiPayloadPkg/Readme.md
create mode 100644 UefiPayloadPkg/Tools/MkFitImage.py
create mode 100644 UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
create mode 100644 UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
diff --git a/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
new file mode 100644
index 0000000000..31c9ec0bfb
--- /dev/null
+++ b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
@@ -0,0 +1,21 @@
+/** @file
+ Universal Payload general definitions.
+
+Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Revision Reference:
+ - Universal Payload Specification 0.75 (https://universalpayload.github.io/documentation/)
+**/
+
+#ifndef UNIVERSAL_PAYLOAD_BASE_H_
+#define UNIVERSAL_PAYLOAD_BASE_H_
+
+extern GUID gUniversalPayloadBaseGuid;
+
+typedef struct {
+ UNIVERSAL_PAYLOAD_GENERIC_HEADER Header;
+ EFI_PHYSICAL_ADDRESS Entry;
+} UNIVERSAL_PAYLOAD_BASE;
+
+#endif // UNIVERSAL_PAYLOAD_BASE_H_
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h b/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
new file mode 100644
index 0000000000..0514d675a6
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
@@ -0,0 +1,60 @@
+/** @file
+ FIT Load Image Support
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef FIT_LIB_H_
+#define FIT_LIB_H_
+
+#include <PiPei.h>
+#include <Library/DebugLib.h>
+#include <Library/FdtLib.h>
+
+typedef struct {
+ UINT64 RelocateType;
+ UINT64 Offset;
+} FIT_RELOCATE_ITEM;
+
+typedef struct {
+ EFI_PHYSICAL_ADDRESS ImageBase;
+ EFI_PHYSICAL_ADDRESS PayloadBaseAddress;
+ UINT64 PayloadSize;
+ UINTN PayloadEntryOffset;
+ UINTN PayloadEntrySize;
+ EFI_PHYSICAL_ADDRESS PayloadEntryPoint;
+ UINTN RelocateTableOffset;
+ UINTN RelocateTableCount;
+ EFI_PHYSICAL_ADDRESS PayloadLoadAddress;
+} FIT_IMAGE_CONTEXT;
+
+typedef struct {
+ UINT8 *Name;
+ UINT32 Offset;
+} PROPERTY_DATA;
+
+#define IMAGE_BASE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, ImageBase)
+#define PAYLOAD_BASE_ADDR_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadBaseAddress)
+#define PAYLOAD_BASE_SIZE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadSize)
+#define PAYLOAD_ENTRY_OFFSET_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntryOffset)
+#define PAYLOAD_ENTRY_SIZE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntrySize)
+#define PAYLOAD_ENTRY_POINT_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntryPoint)
+#define RELOCATE_TABLE_OFFSET_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, RelocateTableOffset)
+#define RELOCATE_TABLE_COUNT_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, RelocateTableCount)
+#define PAYLOAD_LOAD_ADDR_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadLoadAddress)
+
+/**
+ Parse the FIT image info.
+ @param[in] ImageBase Memory address of an image.
+ @param[out] Context The FIT image context pointer.
+ @retval EFI_UNSUPPORTED Unsupported binary type.
+ @retval EFI_SUCCESS FIT binary is loaded successfully.
+**/
+EFI_STATUS
+EFIAPI
+ParseFitImage (
+ IN VOID *ImageBase,
+ OUT FIT_IMAGE_CONTEXT *Context
+ );
+
+#endif
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c b/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
new file mode 100644
index 0000000000..9d1d8a4f61
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
@@ -0,0 +1,127 @@
+/** @file
+ FIT Load Image Support
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "FitLib.h"
+
+PROPERTY_DATA PropertyData32List[] = {
+ { "data-offset", PAYLOAD_ENTRY_OFFSET_OFFSET },
+ { "data-size", PAYLOAD_ENTRY_SIZE_OFFSET },
+ { "reloc-start", RELOCATE_TABLE_OFFSET_OFFSET }
+};
+
+PROPERTY_DATA PropertyData64List[] = {
+ { "entry-start", PAYLOAD_ENTRY_POINT_OFFSET },
+ { "load", PAYLOAD_LOAD_ADDR_OFFSET }
+};
+
+/**
+ Parse the target firmware image info in FIT.
+ @param[in] Fdt Memory address of a fdt.
+ @param[in] Firmware Target name of an image.
+ @param[out] Context The FIT image context pointer.
+ @retval EFI_NOT_FOUND FIT node dose not find.
+ @retval EFI_SUCCESS FIT binary is loaded successfully.
+**/
+EFI_STATUS
+EFIAPI
+FitParseFirmwarePropertyData (
+ IN VOID *Fdt,
+ IN CHAR8 *Firmware,
+ OUT FIT_IMAGE_CONTEXT *Context
+ )
+{
+ CONST FDT_PROPERTY *PropertyPtr;
+ INT32 ImageNode;
+ INT32 TianoNode;
+ INT32 TempLen;
+ UINT32 *Data32;
+ UINT64 *Data64;
+ UINT32 *ContextOffset32;
+ UINT64 *ContextOffset64;
+ INT32 Index;
+
+ ImageNode = FdtSubnodeOffsetNameLen (Fdt, 0, "images", (INT32)AsciiStrLen ("images"));
+ if (ImageNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ TianoNode = FdtSubnodeOffsetNameLen (Fdt, ImageNode, Firmware, (INT32)AsciiStrLen (Firmware));
+ if (TianoNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ for (Index = 0; Index < sizeof (PropertyData32List) / sizeof (PROPERTY_DATA); Index++) {
+ PropertyPtr = FdtGetProperty (Fdt, TianoNode, PropertyData32List[Index].Name, &TempLen);
+ Data32 = (UINT32 *)(PropertyPtr->Data);
+ ContextOffset32 = (UINT32 *)((UINTN)Context + PropertyData32List[Index].Offset);
+ *ContextOffset32 = Fdt32ToCpu (*Data32);
+ }
+
+ for (Index = 0; Index < sizeof (PropertyData64List)/sizeof (PROPERTY_DATA); Index++) {
+ PropertyPtr = FdtGetProperty (Fdt, TianoNode, PropertyData64List[Index].Name, &TempLen);
+ Data64 = (UINT64 *)(PropertyPtr->Data);
+ ContextOffset64 = (UINT64 *)((UINTN)Context + PropertyData64List[Index].Offset);
+ *ContextOffset64 = Fdt64ToCpu (*Data64);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Parse the FIT image info.
+ @param[in] ImageBase Memory address of an image.
+ @param[out] Context The FIT image context pointer.
+ @retval EFI_UNSUPPORTED Unsupported binary type.
+ @retval EFI_SUCCESS FIT binary is loaded successfully.
+**/
+EFI_STATUS
+EFIAPI
+ParseFitImage (
+ IN VOID *ImageBase,
+ OUT FIT_IMAGE_CONTEXT *Context
+ )
+{
+ VOID *Fdt;
+ INT32 ConfigNode;
+ INT32 Config1Node;
+ CONST FDT_PROPERTY *PropertyPtr;
+ INT32 TempLen;
+ UINT32 *Data32;
+ UINT64 Value;
+ EFI_STATUS Status;
+ UINTN UplSize;
+ CHAR8 *Firmware;
+
+ Status = FdtCheckHeader (ImageBase);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Fdt = ImageBase;
+ PropertyPtr = FdtGetProperty (Fdt, 0, "size", &TempLen);
+ Data32 = (UINT32 *)(PropertyPtr->Data);
+ UplSize = Value = Fdt32ToCpu (*Data32);
+ ConfigNode = FdtSubnodeOffsetNameLen (Fdt, 0, "configurations", (INT32)AsciiStrLen ("configurations"));
+ if (ConfigNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ Config1Node = FdtSubnodeOffsetNameLen (Fdt, ConfigNode, "conf-1", (INT32)AsciiStrLen ("conf-1"));
+ if (Config1Node <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ PropertyPtr = FdtGetProperty (Fdt, Config1Node, "firmware", &TempLen);
+ Firmware = (CHAR8 *)(PropertyPtr->Data);
+
+ FitParseFirmwarePropertyData (Fdt, Firmware, Context);
+
+ Context->ImageBase = (EFI_PHYSICAL_ADDRESS)ImageBase;
+ Context->PayloadSize = UplSize;
+ Context->RelocateTableCount = (Context->PayloadEntrySize - (Context->RelocateTableOffset - Context->PayloadEntryOffset)) / sizeof (FIT_RELOCATE_ITEM);
+
+ return EFI_SUCCESS;
+}
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
new file mode 100644
index 0000000000..3c5dacbb65
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
@@ -0,0 +1,150 @@
+/** @file
+ ELF Load Image Support
+Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiPei.h>
+#include <UniversalPayload/UniversalPayload.h>
+#include <Guid/UniversalPayloadBase.h>
+#include <UniversalPayload/ExtraData.h>
+
+#include <Ppi/LoadFile.h>
+
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+
+#include "FitLib.h"
+
+/**
+ The wrapper function of PeiLoadImageLoadImage().
+ @param This - Pointer to EFI_PEI_LOAD_FILE_PPI.
+ @param FileHandle - Pointer to the FFS file header of the image.
+ @param ImageAddressArg - Pointer to PE/TE image.
+ @param ImageSizeArg - Size of PE/TE image.
+ @param EntryPoint - Pointer to entry point of specified image file for output.
+ @param AuthenticationState - Pointer to attestation authentication state of image.
+ @return Status of PeiLoadImageLoadImage().
+**/
+EFI_STATUS
+EFIAPI
+PeiLoadFileLoadPayload (
+ IN CONST EFI_PEI_LOAD_FILE_PPI *This,
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL,
+ OUT UINT64 *ImageSizeArg OPTIONAL,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
+ OUT UINT32 *AuthenticationState
+ )
+{
+ EFI_STATUS Status;
+ FIT_IMAGE_CONTEXT Context;
+ UINTN Instance;
+ VOID *Binary;
+ FIT_RELOCATE_ITEM *RelocateTable;
+ UNIVERSAL_PAYLOAD_BASE *PayloadBase;
+ UINTN Length;
+ UINTN Delta;
+ UINTN Index;
+
+ Instance = 0;
+ do {
+ Status = PeiServicesFfsFindSectionData3 (EFI_SECTION_RAW, Instance++, FileHandle, &Binary, AuthenticationState);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ZeroMem (&Context, sizeof (Context));
+ Status = ParseFitImage (Binary, &Context);
+ } while (EFI_ERROR (Status));
+
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "Before Rebase Payload File Base: 0x%08x, File Size: 0x%08X, EntryPoint: 0x%08x\n",
+ Context.PayloadBaseAddress,
+ Context.PayloadSize,
+ Context.PayloadEntryPoint
+ ));
+ Context.PayloadBaseAddress = (EFI_PHYSICAL_ADDRESS)AllocatePages (EFI_SIZE_TO_PAGES (Context.PayloadSize));
+
+ RelocateTable = (FIT_RELOCATE_ITEM *)(UINTN)(Context.PayloadBaseAddress + Context.RelocateTableOffset);
+ CopyMem ((VOID *)Context.PayloadBaseAddress, Binary, Context.PayloadSize);
+
+ if (Context.PayloadBaseAddress > Context.PayloadLoadAddress) {
+ Delta = Context.PayloadBaseAddress - Context.PayloadLoadAddress;
+ Context.PayloadEntryPoint += Delta;
+ for (Index = 0; Index < Context.RelocateTableCount; Index++) {
+ if ((RelocateTable[Index].RelocateType == 10) || (RelocateTable[Index].RelocateType == 3)) {
+ *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) = *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) + Delta;
+ }
+ }
+ } else {
+ Delta = Context.PayloadLoadAddress - Context.PayloadBaseAddress;
+ Context.PayloadEntryPoint -= Delta;
+ for (Index = 0; Index < Context.RelocateTableCount; Index++) {
+ if ((RelocateTable[Index].RelocateType == 10) || (RelocateTable[Index].RelocateType == 3)) {
+ *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) = *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) - Delta;
+ }
+ }
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "After Rebase Payload File Base: 0x%08x, File Size: 0x%08X, EntryPoint: 0x%08x\n",
+ Context.PayloadBaseAddress,
+ Context.PayloadSize,
+ Context.PayloadEntryPoint
+ ));
+
+ Length = sizeof (UNIVERSAL_PAYLOAD_BASE);
+ PayloadBase = BuildGuidHob (
+ &gUniversalPayloadBaseGuid,
+ Length
+ );
+ PayloadBase->Entry = (EFI_PHYSICAL_ADDRESS)Context.ImageBase;
+
+ *ImageAddressArg = Context.PayloadBaseAddress;
+ *ImageSizeArg = Context.PayloadSize;
+ *EntryPoint = Context.PayloadEntryPoint;
+
+ return EFI_SUCCESS;
+}
+
+EFI_PEI_LOAD_FILE_PPI mPeiLoadFilePpi = {
+ PeiLoadFileLoadPayload
+};
+
+EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiLoadFilePpiGuid,
+ &mPeiLoadFilePpi
+};
+
+/**
+ Install Pei Load File PPI.
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+ @retval EFI_SUCESS The entry point executes successfully.
+ @retval Others Some error occurs during the execution of this function.
+**/
+EFI_STATUS
+EFIAPI
+InitializeFitPayloadLoaderPeim (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PeiServicesInstallPpi (&gPpiLoadFilePpiList);
+
+ return Status;
+}
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
new file mode 100644
index 0000000000..acb0e09f68
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
@@ -0,0 +1,59 @@
+## @file
+# Produce LoadFile PPI for payload loading.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FitPayloadLoaderPeim
+ FILE_GUID = 55AC82C8-FC17-4C56-BCDA-990BB0A73E41
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InitializeFitPayloadLoaderPeim
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ FitPayloadLoaderPeim.c
+ FitLib.h
+ FitLib/FitLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ PcAtChipsetPkg/PcAtChipsetPkg.dec
+ UefiPayloadPkg/UefiPayloadPkg.dec
+
+[LibraryClasses]
+ PcdLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ PeiServicesLib
+ HobLib
+ BaseLib
+ PeimEntryPoint
+ DebugLib
+ FdtLib
+
+[Ppis]
+ gEfiPeiLoadFilePpiGuid ## PRODUCES
+
+[Pcd]
+ gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister
+ gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister
+
+[Guids]
+ gUniversalPayloadExtraDataGuid ## PRODUCES
+ gUniversalPayloadBaseGuid ## PRODUCES
+
+[Depex]
+ TRUE
diff --git a/UefiPayloadPkg/Readme.md b/UefiPayloadPkg/Readme.md
new file mode 100644
index 0000000000..616a5dd467
--- /dev/null
+++ b/UefiPayloadPkg/Readme.md
@@ -0,0 +1,191 @@
+# UefiPayloadPkg
+Provide UEFI Universal Payload for different bootloader to generate EFI environment
+
+# Spec
+
+UniversalPayload URL: https://universalscalablefirmware.github.io/documentation/2_universal_payload.html
+
+ELF Format URL: https://refspecs.linuxfoundation.org/elf/elf.pdf
+
+FIT Format URL: https://universalpayload.github.io/spec/chapter2-payload-image-format.html
+
+# Uefi UniversalPayload Format
+ | Binary Format | HandOffPayload - HOB |
+ |---------------|----------------------|
+ | ELF | V (Default) |
+ | FIT | V |
+
+# Binary Format
+ - ELF
+ ```
+ + +-----------------------+
+ | | UniversalPayloadEntry | <----------- UefiPayloadPkg\UefiPayloadEntry\UniversalPayloadEntry.c:_ModuleEntryPoint (HOB)
+ | +-----------------------+
+ | | .upld_info | patch it directly
+ ELF Format | +-----------------------+
+ | | .upld.uefi_fv | patch it directly
+ | +-----------------------+
+ | | .upld.bds_fv | patch it directly
+ | +-----------------------+
+ | | .upld.<afpx>_fv | patch it directly
+ + +-----------------------+
+ ```
+
+ - FIT
+ ```
+ + +-----------------------+
+ FIT Data | | FIT Header | <----------- Generate by pylibfdt
+ + +-----------------------+
+ PECOFF Format | | UniversalPayloadEntry | <----------- UefiPayloadPkg\UefiPayloadEntry\FitUniversalPayloadEntry.c:_ModuleEntryPoint (HOB)
+ + +-----------------------+
+ Relocate Data | | reloc-start |
+ + +-----------------------+
+ | | uefi_fv | patch it directly
+ | +-----------------------+
+ Multi Binary | | bds_fv | patch it directly
+ | +-----------------------+
+ | | afp_xxx_fv | patch it directly
+ | +-----------------------+
+ | | afp_xxx_fv | patch it directly
+ + +-----------------------+
+ ```
+
+# Environment
+ - ELF
+ ```
+ Download and install https://github.com/llvm/llvm-project/releases/tag/llvmorg-10.0.1
+ ```
+ - FIT
+ - Windows
+ ```powershell
+ Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
+ choco install dtc-msys2
+ pip3 install pefile
+ pip3 install swig
+ pip3 install pylibfdt
+ ```
+ - Ubuntu
+ ```bash
+ sudo apt install -y u-boot-tools
+ pip3 install pefile
+ pip3 install swig
+ pip3 install pylibfdt
+ ```
+# How to build UEFI UniversalPayload
+ - Windows
+ - edksetup Rebuild
+ - Linux
+ - make -C BaseTools
+ - source edksetup.sh
+
+ - UniversalPayload.elf
+ - python UefiPayloadPkg/UniversalPayloadBuild.py -t <TOOL_CHAIN_TAG>
+ - llvm-objdump -h Build/UefiPayloadPkgX64/UniversalPayload.elf
+
+ - UniversalPayload.fit
+ - python UefiPayloadPkg/UniversalPayloadBuild.py -t <TOOL_CHAIN_TAG> --Fit
+ - fdtdump Build/UefiPayloadPkgX64/UniversalPayload.fit
+
+# Edk2boot + UefiUniversalPayload
+ELF Edk2boot use below way to support compress and sign.
+
+- ELF Behavior - Edk2boot + UefiUniversalPayload.elf
+ ```
+ Boot Flow
+ +-------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+-------------------+
+ | Platform Init | Universal Loader Interface | OS |
+ +-------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+-------------------+
+ HOBs
+ SEC -> PEI -> DXE -> DXE IPL -> UefiPayloadPkg\PayloadLoaderPeim\PayloadLoaderPeim.c ------------------------------------------------------------------------------------> Load UniversalPayload.elf -> Operation System
+
+
+ | Platform Initialize - Edk2 | UniversalPayload - Edk2 |
+ +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
+
+ Binary Format
+
+ +-------------------+
+ | BIOS.rom |
+ +-------------------+
+ | Other Firmware |
+ +-------------------+
+ | ... | FMMT UniversalPayloadBuild.py
+ +-------------------+<----------------+-----------------------+ GenFfs +-----------------------+ Rsa2048Sha256 Sign +-----------------------+ LzmaCompress +----------------------+ GenSec +--------------------------------+
+ | | | EDK2 FFS Header |<-----------| Rsa2048Sha256 Hash |<--------------------| UniversalPayload.lzma |<--------------| EDK2 SEC Header |<--------| UniversalPayload.elf |
+ | RAW Data | +-----------------------+ +-----------------------+ +-----------------------+ +----------------------+ +--------------------------------+
+ | | | Rsa2048Sha256 Hash | | UniversalPayload.lzma | | UniversalPayload.elf | | upld_info |
+ | | +-----------------------+ +-----------------------+ +----------------------+ +--------------------------------+
+ | | | UniversalPayload.lzma | | upld_info | | upld.uefi_fv |
+ +-------------------+<----------------+-----------------------+ +----------------------+ +--------------------------------+
+ | ... | | upld.uefi_fv | | upld.bds_fv |
+ +-------------------+ +----------------------+ +--------------------------------+
+ | Other Firmware | | upld.bds_fv | | upld.AFP1 |
+ +-------------------+ +----------------------+ +--------------------------------+
+ | upld.AFP1 | | upld.AFP2 |
+ +----------------------+ +--------------------------------+
+ | upld.AFP2 | | ... |
+ +----------------------+ +--------------------------------+
+ | ... | | upld.AFPn |
+ +----------------------+ +--------------------------------+
+ | upld.AFPn |
+ +----------------------+
+ ```
+
+FIT Edk2boot use below way to support compress and sign
+- FIT Behavior - Edk2boot + UefiUniversalPayload.fit
+ ```
+ Boot Flow
+ +-------------------------------------------------------------------------------------+------------------------------------------------------------------------+-------------------+
+ | Platform Init | Universal Loader Interface | OS |
+ +-------------------------------------------------------------------------------------+------------------------------------------------------------------------+-------------------+
+ HOBs
+ SEC -> PEI -> DXE -> DXE IPL -> *UefiPayloadPkg\PayloadLoaderPeim\PayloadLoaderPeim.c ----------------------------------------------> Load UniversalPayload.fit -> Operation System
+
+ Binary Format
+
+ | Platform Initialize - Edk2 | UniversalPayload - Edk2 (UniversalPayloadBuild.py --Fit) |
+ +---------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
+
+ +-------------------+
+ | BIOS.rom |
+ +-------------------+
+ | Other Firmware |
+ +-------------------+
+ | ... | FMMT UniversalPayloadBuild.py --Fit tianocore -> data-offset
+ +-------------------+<----------------+--------------------------------+ GenFfs +--------------------------------+ GenSec +--------------------------------+ tianocore -> reloc-start +--------------------------+
+ | | | EDK2 FFS Header |<--------| EDK2 SEC Header |<--------| FIT Header |<-------------------------| UniversalPayload.pecoff |
+ | | +--------------------------------+ +--------------------------------+ | description = "Uefi Payload"; | +--------------------------+
+ | | | EDK2 SEC Header | | FIT Header | | ... |
+ | RAW Data | +--------------------------------+ | | | images { | uefi-fv -> data-offset +--------------------------+
+ | | | FIT Header | | | | tianocore {...}; |<-------------------------| uefi_fv |
+ | | | | +--------------------------------+ | uefi-fv {...}; | bds-fv -> data-offset +--------------------------+
+ | | | | | tianocore -> data | | bds-fv {...}; |<-------------------------| bds_fv |
+ | | +--------------------------------+ +--------------------------------+ | afp1-fv {...}; | AFP1 -> data-offset +--------------------------+
+ | | | tianocore -> data | | tianocore -> reloc-start | | ... |<-------------------------| AFP1 |
+ | | +--------------------------------+ +--------------------------------+ | afpn-fv {...}; | AFP2 -> data-offset +--------------------------+
+ | | | tianocore -> reloc-start | | uefi-fv -> data | | } |<-------------------------| AFP2 |
+ | | +--------------------------------+ +--------------------------------+ | configurations { | ... +--------------------------+
+ | | | uefi-fv -> data | | bds-fv -> data | | conf-1 {...} |<-------------------------| ... |
+ | | +--------------------------------+ +--------------------------------+ | } | AFPn -> data-offset +--------------------------+
+ | | | bds-fv -> data | | AFP1-fv -> data | | |<-------------------------| AFPn |
+ | | +--------------------------------+ +--------------------------------+ | | +--------------------------+
+ | | | AFP1-fv -> data | | AFP2-fv -> data | | |
+ | | +--------------------------------+ +--------------------------------+ +--------------------------------+
+ | | | AFP2-fv -> data | | ... | | tianocore -> data |
+ | | +--------------------------------+ +--------------------------------+ +--------------------------------+
+ | | | ... | | AFPn-fv -> data | | tianocore -> reloc-start |
+ | | +--------------------------------+ +--------------------------------+ +--------------------------------+
+ | | | AFPn-fv -> data | | uefi-fv -> data |
+ +-------------------+<----------------+--------------------------------+ +--------------------------------+
+ | ... | | bds-fv -> data |
+ +-------------------+ +--------------------------------+
+ | Other Firmware | | AFP1-fv -> data |
+ +-------------------+ +--------------------------------+
+ | AFP2-fv -> data |
+ +--------------------------------+
+ | ... |
+ +--------------------------------+
+ | AFPn-fv -> data |
+ +--------------------------------+
+
+ ```
diff --git a/UefiPayloadPkg/Tools/MkFitImage.py b/UefiPayloadPkg/Tools/MkFitImage.py
new file mode 100644
index 0000000000..82ab933d6d
--- /dev/null
+++ b/UefiPayloadPkg/Tools/MkFitImage.py
@@ -0,0 +1,272 @@
+## @file
+# This file is a script to build fit image.
+# It generate a dtb header and combine a binary file after this header.
+#
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+from os.path import exists
+import libfdt
+from ctypes import *
+import time
+
+class FIT_IMAGE_INFO_HEADER:
+ """Class for user setting data to use MakeFitImage()
+ """
+ _pack_ = 1
+ _fields_ = [
+ ('Compatible', str),
+ ('UplVersion', int),
+ ('Description', str),
+ ('Type', str),
+ ('Arch', str),
+ ('Compression', str),
+ ('Revision', int),
+ ('BuildType', str),
+ ('Capabilities', str),
+ ('Producer', str),
+ ('ImageId', str),
+ ('DataOffset', int),
+ ('DataSize', int),
+ ('RelocStart', int),
+ ('LoadAddr', int),
+ ('Entry', int),
+ ('Binary', str),
+ ('TargetPath', str),
+ ('UefifvPath', str),
+ ('BdsfvPath', str),
+ ('NetworkfvPath', str),
+ ('Project', str),
+ ]
+
+ def __init__(self):
+ self.Compatible = 'universal-payload'
+ self.UplVersion = 0x0100
+ self.TargetPath = 'mkimage.fit'
+
+def CreatFdt(Fdt):
+ FdtEmptyTree = libfdt.fdt_create_empty_tree(Fdt, len(Fdt))
+ if FdtEmptyTree != 0:
+ print('\n- Failed - Create Fdt failed!')
+ return False
+ return True
+
+def BuildConfNode(Fdt, ParentNode, MultiImage):
+ ConfNode1 = libfdt.fdt_add_subnode(Fdt, ParentNode, 'conf-1')
+
+ libfdt.fdt_setprop(Fdt, ConfNode1, 'require-fit', b'', 0)
+ libfdt.fdt_setprop(Fdt, ConfNode1, 'firmware', bytes('tianocore', 'utf-8'), len('tianocore') + 1)
+
+def BuildFvImageNode(Fdt, InfoHeader, ParentNode, DataOffset, DataSize, Description):
+ libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-size', DataSize)
+ libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-offset', DataOffset)
+ libfdt.fdt_setprop(Fdt, ParentNode, 'compression', bytes('none', 'utf-8'), len('none') + 1)
+ libfdt.fdt_setprop(Fdt, ParentNode, 'project ', bytes('tianocore', 'utf-8'), len('tianocore') + 1)
+ libfdt.fdt_setprop(Fdt, ParentNode, 'arch', bytes('x86_64', 'utf-8'), len('x86_64') + 1)
+ libfdt.fdt_setprop(Fdt, ParentNode, 'type', bytes('flat-binary', 'utf-8'), len('flat-binary') + 1)
+ libfdt.fdt_setprop(Fdt, ParentNode, 'description', bytes(Description, 'utf-8'), len(Description) + 1)
+
+def BuildTianoImageNode(Fdt, InfoHeader, ParentNode, DataOffset, DataSize, Description):
+ #
+ # Set 'load' and 'data-offset' to reserve the memory first.
+ # They would be set again when Fdt completes or this function parses target binary file.
+ #
+ if InfoHeader.LoadAddr is not None:
+ libfdt.fdt_setprop_u64(Fdt, ParentNode, 'load', InfoHeader.LoadAddr)
+ if InfoHeader.Entry is not None:
+ libfdt.fdt_setprop_u64(Fdt, ParentNode, 'entry-start', InfoHeader.Entry)
+ if InfoHeader.RelocStart is not None:
+ libfdt.fdt_setprop_u32(Fdt, ParentNode, 'reloc-start', InfoHeader.RelocStart)
+ if InfoHeader.DataSize is not None:
+ libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-size', DataSize)
+ if InfoHeader.DataOffset is not None:
+ libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-offset', DataOffset)
+ if InfoHeader.Producer is not None:
+ libfdt.fdt_setprop(Fdt, ParentNode, 'producer ', bytes(InfoHeader.Producer, 'utf-8'), len(InfoHeader.Producer) + 1)
+ if InfoHeader.Capabilities is not None:
+ CapStrs = ','.join(InfoHeader.Capabilities)
+ libfdt.fdt_setprop(Fdt, ParentNode, 'capabilities ', bytes(CapStrs, 'utf-8'), len(CapStrs) + 1)
+ if InfoHeader.Type is not None:
+ libfdt.fdt_setprop(Fdt, ParentNode, 'type ', bytes(InfoHeader.Type, 'utf-8'), len(InfoHeader.Type) + 1)
+ if InfoHeader.Arch is not None:
+ libfdt.fdt_setprop(Fdt, ParentNode, 'arch ', bytes(InfoHeader.Arch, 'utf-8'), len(InfoHeader.Arch) + 1)
+ if InfoHeader.Project is not None:
+ libfdt.fdt_setprop(Fdt, ParentNode, 'project ', bytes(InfoHeader.Project, 'utf-8'), len(InfoHeader.Project) + 1)
+ if InfoHeader.Description is not None:
+ libfdt.fdt_setprop(Fdt, ParentNode, 'description', bytes(Description, 'utf-8'), len(Description) + 1)
+
+#
+# The subnode would be inserted from bottom to top of structure block.
+#
+def BuildFitImage(Fdt, InfoHeader):
+ MultiImage = [
+ ["tianocore", InfoHeader.Binary, BuildTianoImageNode , InfoHeader.Description, None, 0 ],
+ ["uefi-fv", InfoHeader.UefifvPath, BuildFvImageNode, "UEFI Firmware Volume", None, 0 ],
+ ["bds-fv", InfoHeader.BdsfvPath, BuildFvImageNode , "BDS Firmware Volume", None, 0 ],
+ ["network-fv", InfoHeader.NetworkfvPath, BuildFvImageNode , "Network Firmware Volume", None, 0 ],
+ ]
+
+ #
+ # Set basic information
+ #
+ libfdt.fdt_setprop_u32(Fdt, 0, 'build-revision ', InfoHeader.Revision)
+ libfdt.fdt_setprop_u32(Fdt, 0, 'spec-version', InfoHeader.UplVersion)
+
+ #
+ # Build configurations node
+ #
+ ConfNode = libfdt.fdt_add_subnode(Fdt, 0, 'configurations')
+ BuildConfNode(Fdt, ConfNode, MultiImage)
+
+ # Build image
+ DataOffset = InfoHeader.DataOffset
+ for Index in range (0, len (MultiImage)):
+ _, Path, _, _, _, _ = MultiImage[Index]
+ if exists(Path) == 1:
+ TempBinary = open(Path, 'rb')
+ BinaryData = TempBinary.read()
+ TempBinary.close()
+ MultiImage[Index][-2] = BinaryData
+ MultiImage[Index][-1] = DataOffset
+ DataOffset += len (BinaryData)
+ libfdt.fdt_setprop_u32(Fdt, 0, 'size', DataOffset)
+ posix_time = int(time.time())
+ libfdt.fdt_setprop_u32(Fdt, 0, 'timestamp', posix_time)
+ DescriptionFit = 'Uefi OS Loader'
+ libfdt.fdt_setprop(Fdt, 0, 'description', bytes(DescriptionFit, 'utf-8'), len(DescriptionFit) + 1)
+
+ ImageNode = libfdt.fdt_add_subnode(Fdt, 0, 'images')
+ for Item in reversed (MultiImage):
+ Name, Path, BuildFvNode, Description, BinaryData, DataOffset = Item
+ FvNode = libfdt.fdt_add_subnode(Fdt, ImageNode, Name)
+ BuildFvNode (Fdt, InfoHeader, FvNode, DataOffset, len(BinaryData), Description)
+
+ #
+ # Create new image file and combine all binary.
+ #
+ DtbFile = open(InfoHeader.TargetPath, "wb")
+ DtbFile.truncate()
+ DtbFile.write(Fdt)
+ for Item in MultiImage:
+ _, _, _, _, BinaryData, _ = Item
+ DtbFile.write(BinaryData)
+ DtbFile.close()
+
+ return True
+
+def MakeFitImage(InfoHeader):
+ #
+ # Allocate fdt byte array.
+ #
+ Fdt = bytearray(InfoHeader.DataOffset)
+
+ #
+ # Create fdt empty tree.
+ #
+ if CreatFdt(Fdt) is False:
+ return False
+
+ #
+ # Parse args to build fit image.
+ #
+ return BuildFitImage(Fdt, InfoHeader)
+
+def ReplaceFv (UplBinary, SectionFvFile, SectionName):
+ try:
+ #
+ # Get Original Multi Fv
+ #
+ with open (UplBinary, "rb") as File:
+ Dtb = File.read ()
+ Fit = libfdt.Fdt (Dtb)
+ NewFitHeader = bytearray(Dtb[0:Fit.totalsize()])
+ FitSize = len(Dtb)
+
+ LoadablesList = []
+ ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'images')
+ FvNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, 'uefi-fv')
+ NodeDepth = libfdt.fdt_node_depth (NewFitHeader, ImagesNode)
+ node_name = libfdt.fdt_get_name(NewFitHeader, FvNode)
+ FvNode = libfdt.fdt_next_node(NewFitHeader, FvNode, NodeDepth)
+
+ while node_name[0][-2:] == 'fv':
+ LoadablesList.append (node_name[0])
+ node_name = libfdt.fdt_get_name(NewFitHeader, FvNode[0])
+ FvNode = libfdt.fdt_next_node(NewFitHeader, FvNode[0], NodeDepth)
+ #
+ # Get current Fit Binary FV data
+ #
+ MultiFvList = []
+ for Item in LoadablesList:
+ ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, Item)
+ ImageOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big')
+ ImageSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-size')[0], 'big')
+ MultiFvList.append ([Item, Dtb[ImageOffset:ImageOffset + ImageSize]])
+
+ IsFvExist = False
+ for Index in range (0, len (MultiFvList)):
+ if MultiFvList[Index][0] == SectionName:
+ with open (SectionFvFile, 'rb') as File:
+ MultiFvList[Index][1] = File.read ()
+ ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, SectionName)
+ ImageSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-size')[0], 'big')
+ ReplaceOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big')
+ OffsetDelta = len(MultiFvList[Index][1]) - ImageSize
+ FitSize += OffsetDelta
+ IsFvExist = True
+ libfdt.fdt_setprop_u32(NewFitHeader, ImageNode, 'data-size', len(MultiFvList[Index][1]))
+
+ #
+ # Update new fit header
+ #
+ ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'images')
+ if (IsFvExist == False):
+ with open (SectionFvFile, 'rb') as File:
+ SectionFvFileBinary = File.read ()
+ MultiFvList.append ([SectionName, SectionFvFileBinary])
+ FvNode = libfdt.fdt_add_subnode(NewFitHeader, ImagesNode, SectionName)
+ BuildFvImageNode (NewFitHeader, None, FvNode, FitSize, len(SectionFvFileBinary), SectionName + " Firmware Volume")
+ FitSize += len(SectionFvFileBinary)
+ else:
+ for Index in range (0, len (MultiFvList)):
+ ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, MultiFvList[Index][0])
+ ImageOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big')
+ if ImageOffset > ReplaceOffset:
+ libfdt.fdt_setprop_u32(NewFitHeader, ImageNode, 'data-offset', ImageOffset + OffsetDelta)
+
+ ConfNodes = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'configurations')
+ libfdt.fdt_setprop(NewFitHeader, ConfNodes, 'default ', bytes('conf-1', 'utf-8'), len('conf-1') + 1)
+ ConfNode = libfdt.fdt_subnode_offset(NewFitHeader, ConfNodes, 'conf-1')
+
+ libfdt.fdt_setprop_u32(NewFitHeader, 0, 'size', FitSize)
+
+ #
+ # Generate new fit image
+ #
+ ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'images')
+ TianoNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, 'tianocore')
+ TianoOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, TianoNode, 'data-offset')[0], 'big')
+ TianoSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, TianoNode, 'data-size')[0], 'big')
+ TianoBinary = Dtb[TianoOffset:TianoOffset + TianoSize]
+
+ print("\nGenerate new fit image:")
+ NewUplBinary = bytearray(FitSize)
+ print("Update fit header\t to 0x0\t\t ~ " + str(hex(len(NewFitHeader))))
+ NewUplBinary[:len(NewFitHeader)] = NewFitHeader
+ print("Update tiano image\t to " + str(hex(len(NewFitHeader))) + "\t ~ " + str(hex(len(NewFitHeader) + len(TianoBinary))))
+ NewUplBinary[len(NewFitHeader):len(NewFitHeader) + len(TianoBinary)] = TianoBinary
+ for Index in range (0, len (MultiFvList)):
+ ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, MultiFvList[Index][0])
+ ImageOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big')
+ ImageSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-size')[0], 'big')
+ NewUplBinary[ImageOffset:ImageOffset + ImageSize] = MultiFvList[Index][1]
+ print("Update " + MultiFvList[Index][0] + "\t\t to " + str(hex(ImageOffset)) + "\t ~ " + str(hex(ImageOffset + ImageSize)))
+
+ with open (UplBinary, "wb") as File:
+ File.write (NewUplBinary)
+
+ return 0
+ except Exception as Ex:
+ print(Ex)
+ return 1
diff --git a/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
new file mode 100644
index 0000000000..a53d988627
--- /dev/null
+++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
@@ -0,0 +1,654 @@
+/** @file
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "UefiPayloadEntry.h"
+#include <Library/FdtLib.h>
+#include <Guid/UniversalPayloadBase.h>
+
+#define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
+ EFI_RESOURCE_ATTRIBUTE_TESTED | \
+ EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \
+ EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \
+ EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \
+ EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED | \
+ EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
+ EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
+ EFI_RESOURCE_ATTRIBUTE_64_BIT_IO | \
+ EFI_RESOURCE_ATTRIBUTE_PERSISTENT )
+
+#define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
+ EFI_RESOURCE_ATTRIBUTE_TESTED )
+
+extern VOID *mHobList;
+
+CHAR8 *mLineBuffer = NULL;
+
+/**
+ Print all HOBs info from the HOB list.
+ @return The pointer to the HOB list.
+**/
+VOID
+PrintHob (
+ IN CONST VOID *HobStart
+ );
+
+/**
+ Find the first substring.
+ @param String Point to the string where to find the substring.
+ @param CharSet Point to the string to be found.
+**/
+UINTN
+EFIAPI
+AsciiStrSpn (
+ IN CHAR8 *String,
+ IN CHAR8 *CharSet
+ )
+{
+ UINTN Count;
+ CHAR8 *Str1;
+ CHAR8 *Str2;
+
+ Count = 0;
+
+ for (Str1 = String; *Str1 != L'\0'; Str1++) {
+ for (Str2 = CharSet; *Str2 != L'\0'; Str2++) {
+ if (*Str1 == *Str2) {
+ break;
+ }
+ }
+
+ if (*Str2 == L'\0') {
+ return Count;
+ }
+
+ Count++;
+ }
+
+ return Count;
+}
+
+/**
+ Searches a string for the first occurrence of a character contained in a
+ specified buffer.
+ @param String Point to the string where to find the substring.
+ @param CharSet Point to the string to be found.
+**/
+CHAR8 *
+EFIAPI
+AsciiStrBrk (
+ IN CHAR8 *String,
+ IN CHAR8 *CharSet
+ )
+{
+ CHAR8 *Str1;
+ CHAR8 *Str2;
+
+ for (Str1 = String; *Str1 != L'\0'; Str1++) {
+ for (Str2 = CharSet; *Str2 != L'\0'; Str2++) {
+ if (*Str1 == *Str2) {
+ return (CHAR8 *)Str1;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ Find the next token after one or more specified characters.
+ @param String Point to the string where to find the substring.
+ @param CharSet Point to the string to be found.
+**/
+CHAR8 *
+EFIAPI
+AsciiStrTokenLine (
+ IN CHAR8 *String OPTIONAL,
+ IN CHAR8 *CharSet
+ )
+{
+ CHAR8 *Begin;
+ CHAR8 *End;
+
+ Begin = (String == NULL) ? mLineBuffer : String;
+ if (Begin == NULL) {
+ return NULL;
+ }
+
+ Begin += AsciiStrSpn (Begin, CharSet);
+ if (*Begin == L'\0') {
+ mLineBuffer = NULL;
+ return NULL;
+ }
+
+ End = AsciiStrBrk (Begin, CharSet);
+ if ((End != NULL) && (*End != L'\0')) {
+ *End = L'\0';
+ End++;
+ }
+
+ mLineBuffer = End;
+ return Begin;
+}
+
+/**
+ Some bootloader may pass a pcd database, and UPL also contain a PCD database.
+ Dxe PCD driver has the assumption that the two PCD database can be catenated and
+ the local token number should be successive.
+ This function will fix up the UPL PCD database to meet that assumption.
+ @param[in] DxeFv The FV where to find the Universal PCD database.
+ @retval EFI_SUCCESS If it completed successfully.
+ @retval other Failed to fix up.
+**/
+EFI_STATUS
+FixUpPcdDatabase (
+ IN EFI_FIRMWARE_VOLUME_HEADER *DxeFv
+ )
+{
+ EFI_STATUS Status;
+ EFI_FFS_FILE_HEADER *FileHeader;
+ VOID *PcdRawData;
+ PEI_PCD_DATABASE *PeiDatabase;
+ PEI_PCD_DATABASE *UplDatabase;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ DYNAMICEX_MAPPING *ExMapTable;
+ UINTN Index;
+
+ GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);
+ if (GuidHob == NULL) {
+ //
+ // No fix-up is needed.
+ //
+ return EFI_SUCCESS;
+ }
+
+ PeiDatabase = (PEI_PCD_DATABASE *)GET_GUID_HOB_DATA (GuidHob);
+ DEBUG ((DEBUG_INFO, "Find the Pei PCD data base, the total local token number is %d\n", PeiDatabase->LocalTokenCount));
+
+ Status = FvFindFileByTypeGuid (DxeFv, EFI_FV_FILETYPE_DRIVER, PcdGetPtr (PcdPcdDriverFile), &FileHeader);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = FileFindSection (FileHeader, EFI_SECTION_RAW, &PcdRawData);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ UplDatabase = (PEI_PCD_DATABASE *)PcdRawData;
+ ExMapTable = (DYNAMICEX_MAPPING *)(UINTN)((UINTN)PcdRawData + UplDatabase->ExMapTableOffset);
+
+ for (Index = 0; Index < UplDatabase->ExTokenCount; Index++) {
+ ExMapTable[Index].TokenNumber += PeiDatabase->LocalTokenCount;
+ }
+
+ DEBUG ((DEBUG_INFO, "Fix up UPL PCD database successfully\n"));
+ return EFI_SUCCESS;
+}
+
+/**
+ Add HOB into HOB list
+ @param[in] Hob The HOB to be added into the HOB list.
+**/
+VOID
+AddNewHob (
+ IN EFI_PEI_HOB_POINTERS *Hob
+ )
+{
+ EFI_PEI_HOB_POINTERS NewHob;
+
+ if (Hob->Raw == NULL) {
+ return;
+ }
+
+ NewHob.Header = CreateHob (Hob->Header->HobType, Hob->Header->HobLength);
+
+ if (NewHob.Header != NULL) {
+ CopyMem (NewHob.Header + 1, Hob->Header + 1, Hob->Header->HobLength - sizeof (EFI_HOB_GENERIC_HEADER));
+ }
+}
+
+/**
+ Found the Resource Descriptor HOB that contains a range (Base, Top)
+ @param[in] HobList Hob start address
+ @param[in] Base Memory start address
+ @param[in] Top Memory end address.
+ @retval The pointer to the Resource Descriptor HOB.
+**/
+EFI_HOB_RESOURCE_DESCRIPTOR *
+FindResourceDescriptorByRange (
+ IN VOID *HobList,
+ IN EFI_PHYSICAL_ADDRESS Base,
+ IN EFI_PHYSICAL_ADDRESS Top
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
+
+ for (Hob.Raw = (UINT8 *)HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
+ //
+ // Skip all HOBs except Resource Descriptor HOBs
+ //
+ if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+ continue;
+ }
+
+ //
+ // Skip Resource Descriptor HOBs that do not describe tested system memory
+ //
+ ResourceHob = Hob.ResourceDescriptor;
+ if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
+ continue;
+ }
+
+ if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
+ continue;
+ }
+
+ //
+ // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
+ //
+ if (Base < ResourceHob->PhysicalStart) {
+ continue;
+ }
+
+ if (Top > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) {
+ continue;
+ }
+
+ return ResourceHob;
+ }
+
+ return NULL;
+}
+
+/**
+ Find the highest below 4G memory resource descriptor, except the input Resource Descriptor.
+ @param[in] HobList Hob start address
+ @param[in] MinimalNeededSize Minimal needed size.
+ @param[in] ExceptResourceHob Ignore this Resource Descriptor.
+ @retval The pointer to the Resource Descriptor HOB.
+**/
+EFI_HOB_RESOURCE_DESCRIPTOR *
+FindAnotherHighestBelow4GResourceDescriptor (
+ IN VOID *HobList,
+ IN UINTN MinimalNeededSize,
+ IN EFI_HOB_RESOURCE_DESCRIPTOR *ExceptResourceHob
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
+ EFI_HOB_RESOURCE_DESCRIPTOR *ReturnResourceHob;
+
+ ReturnResourceHob = NULL;
+
+ for (Hob.Raw = (UINT8 *)HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
+ //
+ // Skip all HOBs except Resource Descriptor HOBs
+ //
+ if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+ continue;
+ }
+
+ //
+ // Skip Resource Descriptor HOBs that do not describe tested system memory
+ //
+ ResourceHob = Hob.ResourceDescriptor;
+ if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
+ continue;
+ }
+
+ if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
+ continue;
+ }
+
+ //
+ // Skip if the Resource Descriptor HOB equals to ExceptResourceHob
+ //
+ if (ResourceHob == ExceptResourceHob) {
+ continue;
+ }
+
+ //
+ // Skip Resource Descriptor HOBs that are beyond 4G
+ //
+ if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > BASE_4GB) {
+ continue;
+ }
+
+ //
+ // Skip Resource Descriptor HOBs that are too small
+ //
+ if (ResourceHob->ResourceLength < MinimalNeededSize) {
+ continue;
+ }
+
+ //
+ // Return the topest Resource Descriptor
+ //
+ if (ReturnResourceHob == NULL) {
+ ReturnResourceHob = ResourceHob;
+ } else {
+ if (ReturnResourceHob->PhysicalStart < ResourceHob->PhysicalStart) {
+ ReturnResourceHob = ResourceHob;
+ }
+ }
+ }
+
+ return ReturnResourceHob;
+}
+
+/**
+ Check the HOB and decide if it is need inside Payload
+ Payload maintainer may make decision which HOB is need or needn't
+ Then add the check logic in the function.
+ @param[in] Hob The HOB to check
+ @retval TRUE If HOB is need inside Payload
+ @retval FALSE If HOB is needn't inside Payload
+**/
+BOOLEAN
+IsHobNeed (
+ EFI_PEI_HOB_POINTERS Hob
+ )
+{
+ if (Hob.Header->HobType == EFI_HOB_TYPE_HANDOFF) {
+ return FALSE;
+ }
+
+ if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
+ if (CompareGuid (&Hob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) {
+ return FALSE;
+ }
+ }
+
+ // Arrive here mean the HOB is need
+ return TRUE;
+}
+
+/**
+ It will build Fv HOBs based on information from bootloaders.
+ @param[out] DxeFv The pointer to the DXE FV in memory.
+ @retval EFI_SUCCESS If it completed successfully.
+ @retval EFI_NOT_FOUND If it failed to find node in fit image.
+ @retval Others If it failed to build required HOBs.
+**/
+EFI_STATUS
+BuildFitLoadablesFvHob (
+ OUT EFI_FIRMWARE_VOLUME_HEADER **DxeFv
+ )
+{
+ EFI_STATUS Status;
+ VOID *Fdt;
+ UINT8 *GuidHob;
+ UNIVERSAL_PAYLOAD_BASE *PayloadBase;
+ INT32 ConfigNode;
+ INT32 Config1Node;
+ INT32 ImageNode;
+ INT32 FvNode;
+ INT32 Depth;
+ CONST FDT_PROPERTY *PropertyPtr;
+ INT32 TempLen;
+ CONST CHAR8 *Fvname;
+ UINT32 DataOffset;
+ UINT32 DataSize;
+ UINT32 *Data32;
+
+ GuidHob = GetFirstGuidHob (&gUniversalPayloadBaseGuid);
+ if (GuidHob != NULL) {
+ PayloadBase = (UNIVERSAL_PAYLOAD_BASE *)GET_GUID_HOB_DATA (GuidHob);
+ Fdt = (VOID *)(UINTN)PayloadBase->Entry;
+ DEBUG ((DEBUG_INFO, "PayloadBase Entry = 0x%08x\n", PayloadBase->Entry));
+ }
+
+ Status = FdtCheckHeader (Fdt);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ ConfigNode = FdtSubnodeOffsetNameLen (Fdt, 0, "configurations", (INT32)AsciiStrLen ("configurations"));
+ if (ConfigNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ Config1Node = FdtSubnodeOffsetNameLen (Fdt, ConfigNode, "conf-1", (INT32)AsciiStrLen ("conf-1"));
+ if (Config1Node <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ ImageNode = FdtSubnodeOffsetNameLen (Fdt, 0, "images", (INT32)AsciiStrLen ("images"));
+ if (ImageNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ FvNode = FdtSubnodeOffsetNameLen (Fdt, ImageNode, "tianocore", (INT32)AsciiStrLen ("tianocore"));
+ Depth = FdtNodeDepth (Fdt, FvNode);
+ FvNode = FdtNextNode (Fdt, FvNode, &Depth);
+ Fvname = FdtGetName (Fdt, FvNode, &TempLen);
+ while ((AsciiStrCmp ((Fvname + AsciiStrLen (Fvname) - 2), "fv") == 0)) {
+ if (FvNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ PropertyPtr = FdtGetProperty (Fdt, FvNode, "data-offset", &TempLen);
+ Data32 = (UINT32 *)(PropertyPtr->Data);
+ DataOffset = SwapBytes32 (*Data32);
+
+ PropertyPtr = FdtGetProperty (Fdt, FvNode, "data-size", &TempLen);
+ Data32 = (UINT32 *)(PropertyPtr->Data);
+ DataSize = SwapBytes32 (*Data32);
+
+ if (AsciiStrCmp (Fvname, "uefi-fv") == 0) {
+ *DxeFv = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)PayloadBase->Entry + (UINTN)DataOffset);
+ ASSERT ((*DxeFv)->FvLength == DataSize);
+ } else {
+ BuildFvHob (((UINTN)PayloadBase->Entry + (UINTN)DataOffset), DataSize);
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "UPL Multiple fv[%a], Base=0x%08x, size=0x%08x\n",
+ Fvname,
+ ((UINTN)PayloadBase->Entry + (UINTN)DataOffset),
+ DataSize,
+ DataOffset
+ ));
+ Depth = FdtNodeDepth (Fdt, FvNode);
+ FvNode = FdtNextNode (Fdt, FvNode, &Depth);
+ Fvname = FdtGetName (Fdt, FvNode, &TempLen);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ It will build HOBs based on information from bootloaders.
+ @param[in] BootloaderParameter The starting memory address of bootloader parameter block.
+ @param[out] DxeFv The pointer to the DXE FV in memory.
+ @retval EFI_SUCCESS If it completed successfully.
+ @retval Others If it failed to build required HOBs.
+**/
+EFI_STATUS
+BuildHobs (
+ IN UINTN BootloaderParameter,
+ OUT EFI_FIRMWARE_VOLUME_HEADER **DxeFv
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ UINTN MinimalNeededSize;
+ EFI_PHYSICAL_ADDRESS FreeMemoryBottom;
+ EFI_PHYSICAL_ADDRESS FreeMemoryTop;
+ EFI_PHYSICAL_ADDRESS MemoryBottom;
+ EFI_PHYSICAL_ADDRESS MemoryTop;
+ EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob;
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
+ UINT8 *GuidHob;
+ EFI_HOB_FIRMWARE_VOLUME *FvHob;
+ UNIVERSAL_PAYLOAD_ACPI_TABLE *AcpiTable;
+ ACPI_BOARD_INFO *AcpiBoardInfo;
+ EFI_HOB_HANDOFF_INFO_TABLE *HobInfo;
+
+ Hob.Raw = (UINT8 *)BootloaderParameter;
+ MinimalNeededSize = FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
+
+ ASSERT (Hob.Raw != NULL);
+ ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryTop == Hob.HandoffInformationTable->EfiFreeMemoryTop);
+ ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryTop == Hob.HandoffInformationTable->EfiMemoryTop);
+ ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryBottom == Hob.HandoffInformationTable->EfiFreeMemoryBottom);
+ ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryBottom == Hob.HandoffInformationTable->EfiMemoryBottom);
+
+ //
+ // Try to find Resource Descriptor HOB that contains Hob range EfiMemoryBottom..EfiMemoryTop
+ //
+ PhitResourceHob = FindResourceDescriptorByRange (Hob.Raw, Hob.HandoffInformationTable->EfiMemoryBottom, Hob.HandoffInformationTable->EfiMemoryTop);
+ if (PhitResourceHob == NULL) {
+ //
+ // Boot loader's Phit Hob is not in an available Resource Descriptor, find another Resource Descriptor for new Phit Hob
+ //
+ ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, MinimalNeededSize, NULL);
+ if (ResourceHob == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ MemoryBottom = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize;
+ FreeMemoryBottom = MemoryBottom;
+ FreeMemoryTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength;
+ MemoryTop = FreeMemoryTop;
+ } else if (PhitResourceHob->PhysicalStart + PhitResourceHob->ResourceLength - Hob.HandoffInformationTable->EfiMemoryTop >= MinimalNeededSize) {
+ //
+ // New availiable Memory range in new hob is right above memory top in old hob.
+ //
+ MemoryBottom = Hob.HandoffInformationTable->EfiFreeMemoryTop;
+ FreeMemoryBottom = Hob.HandoffInformationTable->EfiMemoryTop;
+ FreeMemoryTop = FreeMemoryBottom + MinimalNeededSize;
+ MemoryTop = FreeMemoryTop;
+ } else if (Hob.HandoffInformationTable->EfiMemoryBottom - PhitResourceHob->PhysicalStart >= MinimalNeededSize) {
+ //
+ // New availiable Memory range in new hob is right below memory bottom in old hob.
+ //
+ MemoryBottom = Hob.HandoffInformationTable->EfiMemoryBottom - MinimalNeededSize;
+ FreeMemoryBottom = MemoryBottom;
+ FreeMemoryTop = Hob.HandoffInformationTable->EfiMemoryBottom;
+ MemoryTop = Hob.HandoffInformationTable->EfiMemoryTop;
+ } else {
+ //
+ // In the Resource Descriptor HOB contains boot loader Hob, there is no enough free memory size for payload hob
+ // Find another Resource Descriptor Hob
+ //
+ ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, MinimalNeededSize, PhitResourceHob);
+ if (ResourceHob == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ MemoryBottom = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize;
+ FreeMemoryBottom = MemoryBottom;
+ FreeMemoryTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength;
+ MemoryTop = FreeMemoryTop;
+ }
+
+ HobInfo = HobConstructor ((VOID *)(UINTN)MemoryBottom, (VOID *)(UINTN)MemoryTop, (VOID *)(UINTN)FreeMemoryBottom, (VOID *)(UINTN)FreeMemoryTop);
+ HobInfo->BootMode = Hob.HandoffInformationTable->BootMode;
+ //
+ // From now on, mHobList will point to the new Hob range.
+ //
+
+ //
+ // Create an empty FvHob for the DXE FV that contains DXE core.
+ //
+ BuildFvHob ((EFI_PHYSICAL_ADDRESS)0, 0);
+ //
+ // Since payload created new Hob, move all hobs except PHIT from boot loader hob list.
+ //
+ while (!END_OF_HOB_LIST (Hob)) {
+ if (IsHobNeed (Hob)) {
+ // Add this hob to payload HOB
+ AddNewHob (&Hob);
+ }
+
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ }
+
+ BuildFitLoadablesFvHob (DxeFv);
+
+ //
+ // Create guid hob for acpi board information
+ //
+ GuidHob = GetFirstGuidHob (&gUniversalPayloadAcpiTableGuid);
+ if (GuidHob != NULL) {
+ AcpiTable = (UNIVERSAL_PAYLOAD_ACPI_TABLE *)GET_GUID_HOB_DATA (GuidHob);
+ GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid);
+ if (GuidHob == NULL) {
+ AcpiBoardInfo = BuildHobFromAcpi ((UINT64)AcpiTable->Rsdp);
+ ASSERT (AcpiBoardInfo != NULL);
+ }
+ }
+
+ //
+ // Update DXE FV information to first fv hob in the hob list, which
+ // is the empty FvHob created before.
+ //
+ FvHob = GetFirstHob (EFI_HOB_TYPE_FV);
+ FvHob->BaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)*DxeFv;
+ FvHob->Length = (*DxeFv)->FvLength;
+ return EFI_SUCCESS;
+}
+
+/**
+ Entry point to the C language phase of UEFI payload.
+ @param[in] BootloaderParameter The starting address of bootloader parameter block.
+ @retval It will not return if SUCCESS, and return error when passing bootloader parameter.
+**/
+EFI_STATUS
+EFIAPI
+_ModuleEntryPoint (
+ IN UINTN BootloaderParameter
+ )
+{
+ EFI_STATUS Status;
+ PHYSICAL_ADDRESS DxeCoreEntryPoint;
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_FIRMWARE_VOLUME_HEADER *DxeFv;
+
+ mHobList = (VOID *)BootloaderParameter;
+ DxeFv = NULL;
+ // Call constructor for all libraries
+ ProcessLibraryConstructorList ();
+
+ DEBUG ((DEBUG_INFO, "Entering Universal Payload...\n"));
+ DEBUG ((DEBUG_INFO, "sizeof(UINTN) = 0x%x\n", sizeof (UINTN)));
+
+ DEBUG_CODE (
+ //
+ // Dump the Hobs from boot loader
+ //
+ PrintHob (mHobList);
+ );
+
+ // Initialize floating point operating environment to be compliant with UEFI spec.
+ InitializeFloatingPointUnits ();
+
+ // Build HOB based on information from Bootloader
+ Status = BuildHobs (BootloaderParameter, &DxeFv);
+ ASSERT_EFI_ERROR (Status);
+
+ FixUpPcdDatabase (DxeFv);
+ Status = UniversalLoadDxeCore (DxeFv, &DxeCoreEntryPoint);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Mask off all legacy 8259 interrupt sources
+ //
+ IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF);
+ IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF);
+
+ Hob.HandoffInformationTable = (EFI_HOB_HANDOFF_INFO_TABLE *)GetFirstHob (EFI_HOB_TYPE_HANDOFF);
+ HandOffToDxeCore (DxeCoreEntryPoint, Hob);
+
+ // Should not get here
+ CpuDeadLoop ();
+ return EFI_SUCCESS;
+}
diff --git a/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
new file mode 100644
index 0000000000..a7d1a8c9e5
--- /dev/null
+++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
@@ -0,0 +1,98 @@
+## @file
+# This is the first module for UEFI payload.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FitUniversalPayloadEntry
+ FILE_GUID = CED5A8A9-B6EA-4D5A-8689-577EE88566CF
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ FitUniversalPayloadEntry.c
+ LoadDxeCore.c
+ MemoryAllocation.c
+ PrintHob.c
+ AcpiTable.c
+
+[Sources.Ia32]
+ X64/VirtualMemory.h
+ X64/VirtualMemory.c
+ Ia32/DxeLoadFunc.c
+ Ia32/IdtVectorAsm.nasm
+
+[Sources.X64]
+ X64/VirtualMemory.h
+ X64/VirtualMemory.c
+ X64/DxeLoadFunc.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ UefiPayloadPkg/UefiPayloadPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ BaseLib
+ SerialPortLib
+ IoLib
+ HobLib
+ PeCoffLib
+ CpuLib
+ FdtLib
+
+[Guids]
+ gEfiMemoryTypeInformationGuid
+ gEfiFirmwareFileSystem2Guid
+ gEfiGraphicsInfoHobGuid
+ gEfiGraphicsDeviceInfoHobGuid
+ gUefiAcpiBoardInfoGuid
+ gEfiSmbiosTableGuid
+ gUefiSerialPortInfoGuid
+ gUniversalPayloadExtraDataGuid
+ gUniversalPayloadBaseGuid
+ gPcdDataBaseHobGuid
+ gUniversalPayloadSmbiosTableGuid
+ gEfiHobMemoryAllocBspStoreGuid
+ gUniversalPayloadAcpiTableGuid
+ gUniversalPayloadPciRootBridgeInfoGuid
+ gUniversalPayloadSmbios3TableGuid
+
+[FeaturePcd.IA32]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES
+
+[FeaturePcd.X64]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables ## CONSUMES
+
+
+[Pcd.IA32,Pcd.X64]
+ gUefiPayloadPkgTokenSpaceGuid.PcdPcdDriverFile
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize ## CONSUMES
+
+ gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase
+ gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize
+ gUefiPayloadPkgTokenSpaceGuid.PcdSystemMemoryUefiRegionSize
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy ## SOMETIMES_CONSUMES
diff --git a/UefiPayloadPkg/UefiPayloadPkg.dec b/UefiPayloadPkg/UefiPayloadPkg.dec
index e2e4a79db3..2f1fd82487 100644
--- a/UefiPayloadPkg/UefiPayloadPkg.dec
+++ b/UefiPayloadPkg/UefiPayloadPkg.dec
@@ -24,6 +24,9 @@
#
gUefiPayloadPkgTokenSpaceGuid = {0x1d127ea, 0xf6f1, 0x4ef6, {0x94, 0x15, 0x8a, 0x0, 0x0, 0x93, 0xf8, 0x9d}}
+ ## Include/Guid/UniversalPayloadBase.h
+ gUniversalPayloadBaseGuid = { 0x03d4c61d, 0x2713, 0x4ec5, {0xa1, 0xcc, 0x88, 0x3b, 0xe9, 0xdc, 0x18, 0xe5 } }
+
#
# Gop Temp
#
diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc b/UefiPayloadPkg/UefiPayloadPkg.dsc
index 47812048dd..af9308ef8e 100644
--- a/UefiPayloadPkg/UefiPayloadPkg.dsc
+++ b/UefiPayloadPkg/UefiPayloadPkg.dsc
@@ -30,7 +30,6 @@
DEFINE PS2_KEYBOARD_ENABLE = FALSE
DEFINE RAM_DISK_ENABLE = FALSE
DEFINE SIO_BUS_ENABLE = FALSE
- DEFINE UNIVERSAL_PAYLOAD = FALSE
DEFINE SECURITY_STUB_ENABLE = TRUE
DEFINE SMM_SUPPORT = FALSE
DEFINE PLATFORM_BOOT_TIMEOUT = 3
@@ -44,6 +43,14 @@
DEFINE BOOTSPLASH_IMAGE = FALSE
DEFINE NVME_ENABLE = TRUE
DEFINE CAPSULE_SUPPORT = FALSE
+ #
+ # Setup Universal Payload
+ #
+ # ELF: Build UniversalPayload file as UniversalPayload.elf
+ # FIT: Build UniversalPayload file as UniversalPayload.fit
+ #
+ DEFINE UNIVERSAL_PAYLOAD = FALSE
+ DEFINE UNIVERSAL_PAYLOAD_FORMAT = ELF
#
# NULL: NullMemoryTestDxe
@@ -311,7 +318,7 @@
VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf
CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
-
+ FdtLib|MdePkg/Library/BaseFdtLib/BaseFdtLib.inf
[LibraryClasses.common]
!if $(BOOTSPLASH_IMAGE)
SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
@@ -600,14 +607,26 @@
!if "IA32" in "$(ARCH)"
[Components.IA32]
!if $(UNIVERSAL_PAYLOAD) == TRUE
- UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
+ !if $(UNIVERSAL_PAYLOAD_FORMAT) == "ELF"
+ UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
+ !elseif $(UNIVERSAL_PAYLOAD_FORMAT) == "FIT"
+ UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
+ !else
+ UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
+ !endif
!else
UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
!endif
!else
[Components.X64]
!if $(UNIVERSAL_PAYLOAD) == TRUE
- UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
+ !if $(UNIVERSAL_PAYLOAD_FORMAT) == "ELF"
+ UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
+ !elseif $(UNIVERSAL_PAYLOAD_FORMAT) == "FIT"
+ UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
+ !else
+ UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
+ !endif
!else
UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
!endif
diff --git a/UefiPayloadPkg/UniversalPayloadBuild.py b/UefiPayloadPkg/UniversalPayloadBuild.py
index 47f37b3377..9a83fc9e44 100644
--- a/UefiPayloadPkg/UniversalPayloadBuild.py
+++ b/UefiPayloadPkg/UniversalPayloadBuild.py
@@ -10,10 +10,22 @@ import subprocess
import os
import shutil
import sys
+import pathlib
from ctypes import *
-from Tools.ElfFv import ReplaceFv
+
sys.dont_write_bytecode = True
+class bcolors:
+ HEADER = '\033[95m'
+ OKBLUE = '\033[94m'
+ OKCYAN = '\033[96m'
+ OKGREEN = '\033[92m'
+ WARNING = '\033[93m'
+ FAIL = '\033[91m'
+ ENDC = '\033[0m'
+ BOLD = '\033[1m'
+ UNDERLINE = '\033[4m'
+
class UPLD_INFO_HEADER(LittleEndianStructure):
_pack_ = 1
_fields_ = [
@@ -36,40 +48,114 @@ class UPLD_INFO_HEADER(LittleEndianStructure):
self.ImageId = b'UEFI'
self.ProducerId = b'INTEL'
-def BuildUniversalPayload(Args):
- def RunCommand(cmd):
- print(cmd)
- p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,cwd=os.environ['WORKSPACE'])
- while True:
- line = p.stdout.readline()
- if not line:
- break
- print(line.strip().decode(errors='ignore'))
-
- p.communicate()
- if p.returncode != 0:
- print("- Failed - error happened when run command: %s"%cmd)
- raise Exception("ERROR: when run command: %s"%cmd)
+def ValidateSpecRevision (Argument):
+ try:
+ (MajorStr, MinorStr) = Argument.split('.')
+ except:
+ raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
+ #
+ # Spec Revision Bits 15 : 8 - Major Version. Bits 7 : 0 - Minor Version.
+ #
+ if len(MinorStr) > 0 and len(MinorStr) < 3:
+ try:
+ Minor = int(MinorStr, 16) if len(MinorStr) == 2 else (int(MinorStr, 16) << 4)
+ except:
+ raise argparse.ArgumentTypeError ('{} Minor version of SpecRevision is not a valid integer value.'.format (Argument))
+ else:
+ raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
+
+ if len(MajorStr) > 0 and len(MajorStr) < 3:
+ try:
+ Major = int(MajorStr, 16)
+ except:
+ raise argparse.ArgumentTypeError ('{} Major version of SpecRevision is not a valid integer value.'.format (Argument))
+ else:
+ raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
+
+ return int('0x{0:02x}{1:02x}'.format(Major, Minor), 0)
+
+def Validate32BitInteger (Argument):
+ try:
+ Value = int (Argument, 0)
+ except:
+ raise argparse.ArgumentTypeError ('{} is not a valid integer value.'.format (Argument))
+ if Value < 0:
+ raise argparse.ArgumentTypeError ('{} is a negative value.'.format (Argument))
+ if Value > 0xffffffff:
+ raise argparse.ArgumentTypeError ('{} is larger than 32-bits.'.format (Argument))
+ return Value
+def ValidateAddFv (Argument):
+ Value = Argument.split ("=")
+ if len (Value) != 2:
+ raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
+ if Value[0][-3:] != "_fv":
+ raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
+ if Value[1][-3:].lower () != ".fv":
+ raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
+ if os.path.exists (Value[1]) == False:
+ raise argparse.ArgumentTypeError ('File {} is not found.'.format (Value[1]))
+ return Value
+
+def RunCommand(cmd):
+ print(cmd)
+ p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,cwd=os.environ['WORKSPACE'])
+ while True:
+ line = p.stdout.readline()
+ if not line:
+ break
+ print(line.strip().decode(errors='ignore'))
+
+ p.communicate()
+ if p.returncode != 0:
+ print("- Failed - error happened when run command: %s"%cmd)
+ raise Exception("ERROR: when run command: %s"%cmd)
+
+def BuildUniversalPayload(Args):
BuildTarget = Args.Target
ToolChain = Args.ToolChain
Quiet = "--quiet" if Args.Quiet else ""
- ElfToolChain = 'CLANGDWARF'
- BuildDir = os.path.join(os.environ['WORKSPACE'], os.path.normpath("Build/UefiPayloadPkgX64"))
- BuildModule = ""
- BuildArch = ""
+ if Args.Fit == True:
+ PayloadEntryToolChain = ToolChain
+ Args.Macro.append("UNIVERSAL_PAYLOAD_FORMAT=FIT")
+ UpldEntryFile = "FitUniversalPayloadEntry"
+ else:
+ PayloadEntryToolChain = 'CLANGDWARF'
+ Args.Macro.append("UNIVERSAL_PAYLOAD_FORMAT=ELF")
+ UpldEntryFile = "UniversalPayloadEntry"
+
+ BuildDir = os.path.join(os.environ['WORKSPACE'], os.path.normpath("Build/UefiPayloadPkgX64"))
if Args.Arch == 'X64':
BuildArch = "X64"
- EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ElfToolChain), os.path.normpath("X64/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll"))
+ FitArch = "x86_64"
+ ObjCopyFlag = "elf64-x86-64"
+ EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, PayloadEntryToolChain), os.path.normpath("X64/UefiPayloadPkg/UefiPayloadEntry/{}/DEBUG/{}.dll".format (UpldEntryFile, UpldEntryFile)))
else:
BuildArch = "IA32 -a X64"
- EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ElfToolChain), os.path.normpath("IA32/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll"))
+ FitArch = "x86"
+ ObjCopyFlag = "elf32-i386"
+ EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, PayloadEntryToolChain), os.path.normpath("IA32/UefiPayloadPkg/UefiPayloadEntry/{}/DEBUG/{}.dll".format (UpldEntryFile, UpldEntryFile)))
+ EntryModuleInf = os.path.normpath("UefiPayloadPkg/UefiPayloadEntry/{}.inf".format (UpldEntryFile))
DscPath = os.path.normpath("UefiPayloadPkg/UefiPayloadPkg.dsc")
+ DxeFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv"))
+ BdsFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv"))
+ NetworkFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv"))
+ PayloadReportPath = os.path.join(BuildDir, "UefiUniversalPayload.txt")
ModuleReportPath = os.path.join(BuildDir, "UefiUniversalPayloadEntry.txt")
UpldInfoFile = os.path.join(BuildDir, "UniversalPayloadInfo.bin")
+ if "CLANG_BIN" in os.environ:
+ LlvmObjcopyPath = os.path.join(os.environ["CLANG_BIN"], "llvm-objcopy")
+ else:
+ LlvmObjcopyPath = "llvm-objcopy"
+ try:
+ RunCommand('"%s" --version'%LlvmObjcopyPath)
+ except:
+ print("- Failed - Please check if LLVM is installed or if CLANG_BIN is set correctly")
+ sys.exit(1)
+
Pcds = ""
if (Args.pcd != None):
for PcdItem in Args.pcd:
@@ -84,7 +170,6 @@ def BuildUniversalPayload(Args):
# Building DXE core and DXE drivers as DXEFV.
#
if Args.BuildEntryOnly == False:
- PayloadReportPath = os.path.join(BuildDir, "UefiUniversalPayload.txt")
BuildPayload = "build -p {} -b {} -a X64 -t {} -y {} {}".format (DscPath, BuildTarget, ToolChain, PayloadReportPath, Quiet)
BuildPayload += Pcds
BuildPayload += Defines
@@ -93,94 +178,138 @@ def BuildUniversalPayload(Args):
# Building Universal Payload entry.
#
if Args.PreBuildUplBinary is None:
- EntryModuleInf = os.path.normpath("UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf")
- BuildModule = "build -p {} -b {} -a {} -m {} -t {} -y {} {}".format (DscPath, BuildTarget, BuildArch, EntryModuleInf, ElfToolChain, ModuleReportPath, Quiet)
+ BuildModule = "build -p {} -b {} -a {} -m {} -t {} -y {} {}".format (DscPath, BuildTarget, BuildArch, EntryModuleInf, PayloadEntryToolChain, ModuleReportPath, Quiet)
BuildModule += Pcds
BuildModule += Defines
RunCommand(BuildModule)
if Args.PreBuildUplBinary is not None:
- EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.elf")
+ if Args.Fit == False:
+ EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.elf")
+ else:
+ EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.fit")
shutil.copy (os.path.abspath(Args.PreBuildUplBinary), EntryOutputDir)
#
- # Buid Universal Payload Information Section ".upld_info"
+ # Build Universal Payload Information Section ".upld_info"
#
- upld_info_hdr = UPLD_INFO_HEADER()
- upld_info_hdr.SpecRevision = Args.SpecRevision
- upld_info_hdr.Revision = Args.Revision
- upld_info_hdr.ProducerId = Args.ProducerId.encode()[:16]
- upld_info_hdr.ImageId = Args.ImageId.encode()[:16]
- upld_info_hdr.Attribute |= 1 if BuildTarget == "DEBUG" else 0
- fp = open(UpldInfoFile, 'wb')
- fp.write(bytearray(upld_info_hdr))
- fp.close()
+ if Args.Fit == False:
+ upld_info_hdr = UPLD_INFO_HEADER()
+ upld_info_hdr.SpecRevision = Args.SpecRevision
+ upld_info_hdr.Revision = Args.Revision
+ upld_info_hdr.ProducerId = Args.ProducerId.encode()[:16]
+ upld_info_hdr.ImageId = Args.ImageId.encode()[:16]
+ upld_info_hdr.Attribute |= 1 if BuildTarget == "DEBUG" else 0
+ fp = open(UpldInfoFile, 'wb')
+ fp.write(bytearray(upld_info_hdr))
+ fp.close()
+
+ if Args.BuildEntryOnly == False:
+ import Tools.ElfFv as ElfFv
+ ElfFv.ReplaceFv (EntryOutputDir, UpldInfoFile, '.upld_info', Alignment = 4)
+ if Args.Fit == False:
+ shutil.copy (EntryOutputDir, os.path.join(BuildDir, 'UniversalPayload.elf'))
+ else:
+ shutil.copy (EntryOutputDir, os.path.join(BuildDir, 'UniversalPayload.fit'))
MultiFvList = []
if Args.BuildEntryOnly == False:
MultiFvList = [
- ['uefi_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv")) ],
- ['bds_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv")) ],
- ['network_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv")) ],
+ ['uefi_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv")) ],
+ ['bds_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv")) ],
+ ['network_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv"))],
]
- AddSectionName = '.upld_info'
- ReplaceFv (EntryOutputDir, UpldInfoFile, AddSectionName, Alignment = 4)
- if Args.PreBuildUplBinary is None:
- shutil.copy (EntryOutputDir, os.path.join(BuildDir, 'UniversalPayload.elf'))
- return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.elf')
+ if Args.Fit == True:
+ import Tools.MkFitImage as MkFitImage
+ import pefile
+ fit_image_info_header = MkFitImage.FIT_IMAGE_INFO_HEADER()
+ fit_image_info_header.Description = 'Uefi Universal Payload'
+ fit_image_info_header.UplVersion = Args.SpecRevision
+ fit_image_info_header.Type = 'flat-binary'
+ fit_image_info_header.Arch = FitArch
+ fit_image_info_header.Compression = 'none'
+ fit_image_info_header.Revision = Args.Revision
+ fit_image_info_header.BuildType = Args.Target.lower()
+ fit_image_info_header.Capabilities = None
+ fit_image_info_header.Producer = Args.ProducerId.lower()
+ fit_image_info_header.ImageId = Args.ImageId.lower()
+ fit_image_info_header.Binary = os.path.join(BuildDir, 'UniversalPayload.fit')
+ fit_image_info_header.TargetPath = os.path.join(BuildDir, 'UniversalPayload.fit')
+ fit_image_info_header.UefifvPath = DxeFvOutputDir
+ fit_image_info_header.BdsfvPath = BdsFvOutputDir
+ fit_image_info_header.NetworkfvPath = NetworkFvOutputDir
+ fit_image_info_header.DataOffset = 0x1000
+ fit_image_info_header.LoadAddr = Args.LoadAddress
+ fit_image_info_header.Project = 'tianocore'
+
+ TargetRebaseFile = fit_image_info_header.Binary.replace (pathlib.Path(fit_image_info_header.Binary).suffix, ".pecoff")
+ TargetRebaseEntryFile = fit_image_info_header.Binary.replace (pathlib.Path(fit_image_info_header.Binary).suffix, ".entry")
+
-def main():
- def ValidateSpecRevision (Argument):
- try:
- (MajorStr, MinorStr) = Argument.split('.')
- except:
- raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
#
- # Spec Revision Bits 15 : 8 - Major Version. Bits 7 : 0 - Minor Version.
+ # Rebase PECOFF to load address
#
- if len(MinorStr) > 0 and len(MinorStr) < 3:
- try:
- Minor = int(MinorStr, 16) if len(MinorStr) == 2 else (int(MinorStr, 16) << 4)
- except:
- raise argparse.ArgumentTypeError ('{} Minor version of SpecRevision is not a valid integer value.'.format (Argument))
- else:
- raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
+ RunCommand (
+ "GenFw -e SEC -o {} {}".format (
+ TargetRebaseFile,
+ fit_image_info_header.Binary
+ ))
+ RunCommand (
+ "GenFw --rebase 0x{:02X} -o {} {} ".format (
+ fit_image_info_header.LoadAddr + fit_image_info_header.DataOffset,
+ TargetRebaseFile,
+ TargetRebaseFile,
+ ))
- if len(MajorStr) > 0 and len(MajorStr) < 3:
- try:
- Major = int(MajorStr, 16)
- except:
- raise argparse.ArgumentTypeError ('{} Major version of SpecRevision is not a valid integer value.'.format (Argument))
- else:
- raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
+ #
+ # Open PECOFF relocation table binary.
+ #
+ RelocBinary = b''
+ PeCoff = pefile.PE (TargetRebaseFile)
+ for reloc in PeCoff.DIRECTORY_ENTRY_BASERELOC:
+ for entry in reloc.entries:
+ if (entry.type == 0):
+ continue
+ Type = entry.type
+ Offset = entry.rva + fit_image_info_header.DataOffset
+ RelocBinary += Type.to_bytes (8, 'little') + Offset.to_bytes (8, 'little')
+ RelocBinary += b'\x00' * (0x1000 - (len(RelocBinary) % 0x1000))
- return int('0x{0:02x}{1:02x}'.format(Major, Minor), 0)
+ #
+ # Output UniversalPayload.entry
+ #
+ TempBinary = open (TargetRebaseFile, 'rb')
+ TianoBinary = TempBinary.read ()
+ TempBinary.close ()
- def Validate32BitInteger (Argument):
- try:
- Value = int (Argument, 0)
- except:
- raise argparse.ArgumentTypeError ('{} is not a valid integer value.'.format (Argument))
- if Value < 0:
- raise argparse.ArgumentTypeError ('{} is a negative value.'.format (Argument))
- if Value > 0xffffffff:
- raise argparse.ArgumentTypeError ('{} is larger than 32-bits.'.format (Argument))
- return Value
-
- def ValidateAddFv (Argument):
- Value = Argument.split ("=")
- if len (Value) != 2:
- raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
- if Value[0][-3:] != "_fv":
- raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
- if Value[1][-3:].lower () != ".fv":
- raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
- if os.path.exists (Value[1]) == False:
- raise argparse.ArgumentTypeError ('File {} is not found.'.format (Value[1]))
- return Value
+ TianoEntryBinary = TianoBinary + RelocBinary
+ TianoEntryBinary += (b'\x00' * (0x1000 - (len(TianoBinary) % 0x1000)))
+ TianoEntryBinarySize = len (TianoEntryBinary)
+
+ TempBinary = open(TargetRebaseEntryFile, "wb")
+ TempBinary.truncate()
+ TempBinary.write(TianoEntryBinary)
+ TempBinary.close()
+
+ #
+ # Calculate entry and update relocation table start address and data-size.
+ #
+ fit_image_info_header.Entry = PeCoff.OPTIONAL_HEADER.ImageBase + PeCoff.OPTIONAL_HEADER.AddressOfEntryPoint
+ fit_image_info_header.RelocStart = fit_image_info_header.DataOffset + len(TianoBinary)
+ fit_image_info_header.DataSize = TianoEntryBinarySize
+ fit_image_info_header.Binary = TargetRebaseEntryFile
+
+ if MkFitImage.MakeFitImage(fit_image_info_header) is True:
+ print('\nSuccessfully build Fit Image')
+ else:
+ sys.exit(1)
+ return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.fit')
+ else:
+ return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.elf')
+def main():
parser = argparse.ArgumentParser(description='For building Universal Payload')
parser.add_argument('-t', '--ToolChain')
parser.add_argument('-b', '--Target', default='DEBUG')
@@ -192,13 +321,16 @@ def main():
parser.add_argument("-s", "--SpecRevision", type=ValidateSpecRevision, default ='0.7', help='Indicates compliance with a revision of this specification in the BCD format.')
parser.add_argument("-r", "--Revision", type=Validate32BitInteger, default ='0x0000010105', help='Revision of the Payload binary. Major.Minor.Revision.Build')
parser.add_argument("-o", "--ProducerId", default ='INTEL', help='A null-terminated OEM-supplied string that identifies the payload producer (16 bytes maximal).')
+ parser.add_argument("-e", "--BuildEntryOnly", action='store_true', help='Build UniversalPayload Entry file')
+ parser.add_argument("-pb", "--PreBuildUplBinary", default=None, help='Specify the UniversalPayload file')
parser.add_argument("-sk", "--SkipBuild", action='store_true', help='Skip UniversalPayload build')
parser.add_argument("-af", "--AddFv", type=ValidateAddFv, action='append', help='Add or replace specific FV into payload, Ex: uefi_fv=XXX.fv')
- command_group = parser.add_mutually_exclusive_group()
- command_group.add_argument("-e", "--BuildEntryOnly", action='store_true', help='Build UniversalPayload Entry file')
- command_group.add_argument("-pb", "--PreBuildUplBinary", default=None, help='Specify the UniversalPayload file')
+ parser.add_argument("-f", "--Fit", action='store_true', help='Build UniversalPayload file as UniversalPayload.fit', default=False)
+ parser.add_argument('-l', "--LoadAddress", type=int, help='Specify payload load address', default =0x000800000)
+
args = parser.parse_args()
+
MultiFvList = []
UniversalPayloadBinary = args.PreBuildUplBinary
if (args.SkipBuild == False):
@@ -208,12 +340,24 @@ def main():
for (SectionName, SectionFvFile) in args.AddFv:
MultiFvList.append ([SectionName, SectionFvFile])
+ def ReplaceFv (UplBinary, SectionFvFile, SectionName):
+ print (bcolors.OKGREEN + "Patch {}={} into {}".format (SectionName, SectionFvFile, UplBinary) + bcolors.ENDC)
+ if (args.Fit == False):
+ import Tools.ElfFv as ElfFv
+ return ElfFv.ReplaceFv (UplBinary, SectionFvFile, '.upld.{}'.format (SectionName))
+ else:
+ import Tools.MkFitImage as MkFitImage
+ return MkFitImage.ReplaceFv (UplBinary, SectionFvFile, SectionName)
+
if (UniversalPayloadBinary != None):
for (SectionName, SectionFvFile) in MultiFvList:
if os.path.exists (SectionFvFile) == False:
continue
- print ("Patch {}={} into {}".format (SectionName, SectionFvFile, UniversalPayloadBinary))
- ReplaceFv (UniversalPayloadBinary, SectionFvFile, '.upld.{}'.format (SectionName))
+
+ status = ReplaceFv (UniversalPayloadBinary, SectionFvFile, SectionName.replace ("_", "-"))
+ if status != 0:
+ print (bcolors.FAIL + "[Fail] Patch {}={}".format (SectionName, SectionFvFile) + bcolors.ENDC)
+ return status
print ("\nSuccessfully build Universal Payload")
--
2.39.1.windows.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#108701): https://edk2.groups.io/g/devel/message/108701
Mute This Topic: https://groups.io/mt/101375948/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [edk2-devel] [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function.
2023-09-15 8:58 ` [edk2-devel] [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function brucex.wang
2023-09-15 9:02 ` Guo, Gua
@ 2023-09-15 9:06 ` Lu, James
2023-09-15 9:09 ` Benny Lin
2 siblings, 0 replies; 10+ messages in thread
From: Lu, James @ 2023-09-15 9:06 UTC (permalink / raw)
To: Wang, BruceX, devel@edk2.groups.io; +Cc: Lin, Benny, Guo, Gua, Chiu, Chasel
Reviewed-by: James Lu <james.lu@intel.com>
Thanks,
James
-----Original Message-----
From: Wang, BruceX <brucex.wang@intel.com>
Sent: Friday, September 15, 2023 4:58 PM
To: devel@edk2.groups.io
Cc: Wang, BruceX <brucex.wang@intel.com>; Lin, Benny <benny.lin@intel.com>; Guo, Gua <gua.guo@intel.com>; Chiu, Chasel <chasel.chiu@intel.com>; Lu, James <james.lu@intel.com>
Subject: [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function.
From: "Brucex.Wang" <brucex.wang@intel.com>
Add FdtGetName() and FdtNodeDepth() function.
Cc: Benny Lin <benny.lin@intel.com>
Cc: Gua Guo <gua.guo@intel.com>
Cc: Chasel Chiu <chasel.chiu@intel.com>
Cc: James Lu <james.lu@intel.com>
Signed-off-by: BruceX Wang <brucex.wang@intel.com>
---
MdePkg/Include/Library/FdtLib.h | 34 +++++++++++++++++++++++++
MdePkg/Library/BaseFdtLib/FdtLib.c | 40 ++++++++++++++++++++++++++++++
2 files changed, 74 insertions(+)
diff --git a/MdePkg/Include/Library/FdtLib.h b/MdePkg/Include/Library/FdtLib.h index cf5ceba9e9..2bd926b5b4 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 (#108702): https://edk2.groups.io/g/devel/message/108702
Mute This Topic: https://groups.io/mt/101375949/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] 10+ messages in thread
* Re: [edk2-devel] [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function.
2023-09-15 8:58 ` [edk2-devel] [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function brucex.wang
2023-09-15 9:02 ` Guo, Gua
2023-09-15 9:06 ` Lu, James
@ 2023-09-15 9:09 ` Benny Lin
2 siblings, 0 replies; 10+ messages in thread
From: Benny Lin @ 2023-09-15 9:09 UTC (permalink / raw)
To: Wang, BruceX, devel@edk2.groups.io; +Cc: Guo, Gua, Chiu, Chasel, Lu, James
Reviewed-by: Benny Lin <benny.lin@intel.com>
-----Original Message-----
From: Wang, BruceX <brucex.wang@intel.com>
Sent: Friday, September 15, 2023 4:58 PM
To: devel@edk2.groups.io
Cc: Wang, BruceX <brucex.wang@intel.com>; Lin, Benny <benny.lin@intel.com>; Guo, Gua <gua.guo@intel.com>; Chiu, Chasel <chasel.chiu@intel.com>; Lu, James <james.lu@intel.com>
Subject: [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function.
From: "Brucex.Wang" <brucex.wang@intel.com>
Add FdtGetName() and FdtNodeDepth() function.
Cc: Benny Lin <benny.lin@intel.com>
Cc: Gua Guo <gua.guo@intel.com>
Cc: Chasel Chiu <chasel.chiu@intel.com>
Cc: James Lu <james.lu@intel.com>
Signed-off-by: BruceX Wang <brucex.wang@intel.com>
---
MdePkg/Include/Library/FdtLib.h | 34 +++++++++++++++++++++++++
MdePkg/Library/BaseFdtLib/FdtLib.c | 40 ++++++++++++++++++++++++++++++
2 files changed, 74 insertions(+)
diff --git a/MdePkg/Include/Library/FdtLib.h b/MdePkg/Include/Library/FdtLib.h index cf5ceba9e9..2bd926b5b4 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 (#108703): https://edk2.groups.io/g/devel/message/108703
Mute This Topic: https://groups.io/mt/101375949/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] 10+ messages in thread
* Re: [edk2-devel] [PATCH v2 2/2] UefiPayloadPkg: Add FIT support
2023-09-15 9:02 ` Guo, Gua
@ 2023-09-15 10:26 ` Sheng Lean Tan
2023-09-15 10:32 ` Sheng Lean Tan
0 siblings, 1 reply; 10+ messages in thread
From: Sheng Lean Tan @ 2023-09-15 10:26 UTC (permalink / raw)
To: devel, gua.guo; +Cc: Wang, BruceX, Dong, Guo, Rhodes, Sean, Lu, James
[-- Attachment #1: Type: text/plain, Size: 102196 bytes --]
Hi,
It looks good to me, but could you help to update these 2 parts:
1. the copyright year should be 2023 instead of 2021?
2. the correct UPL spec website should be universalpayload.github.io/spec
Thanks,
Sheng
On Fri, 15 Sept 2023 at 11:02, Guo, Gua <gua.guo@intel.com> wrote:
> Reviewed-by: Gua Guo <gua.guo@intel.com>
>
> -----Original Message-----
> From: Wang, BruceX <brucex.wang@intel.com>
> Sent: Friday, September 15, 2023 4:58 PM
> To: devel@edk2.groups.io
> Cc: Wang, BruceX <brucex.wang@intel.com>; Dong, Guo <guo.dong@intel.com>;
> Rhodes, Sean <sean@starlabs.systems>; Lu, James <james.lu@intel.com>;
> Guo, Gua <gua.guo@intel.com>
> Subject: [PATCH v2 2/2] UefiPayloadPkg: Add FIT support
>
> From: "Brucex.Wang" <brucex.wang@intel.com>
>
> Provide Fit format for UniversalPayload, developer can use argument
> "--Fit" to build UniversalPayload.fit
>
> Cc: Guo Dong <guo.dong@intel.com>
> Cc: Sean Rhodes <sean@starlabs.systems>
> Cc: James Lu <james.lu@intel.com>
> Cc: Gua Guo <gua.guo@intel.com>
>
> Signed-off-by: BruceX Wang <brucex.wang@intel.com>
> ---
> .../Include/Guid/UniversalPayloadBase.h | 21 +
> UefiPayloadPkg/PayloadLoaderPeim/FitLib.h | 60 ++
> .../PayloadLoaderPeim/FitLib/FitLib.c | 127 ++++
> .../PayloadLoaderPeim/FitPayloadLoaderPeim.c | 150 ++++
> .../FitPayloadLoaderPeim.inf | 59 ++
> UefiPayloadPkg/Readme.md | 191 +++++
> UefiPayloadPkg/Tools/MkFitImage.py | 272 ++++++++
> .../FitUniversalPayloadEntry.c | 654 ++++++++++++++++++
> .../FitUniversalPayloadEntry.inf | 98 +++
> UefiPayloadPkg/UefiPayloadPkg.dec | 3 +
> UefiPayloadPkg/UefiPayloadPkg.dsc | 27 +-
> UefiPayloadPkg/UniversalPayloadBuild.py | 328 ++++++---
> 12 files changed, 1894 insertions(+), 96 deletions(-)
> create mode 100644 UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
> create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
> create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
> create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
> create mode 100644
> UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
> create mode 100644 UefiPayloadPkg/Readme.md
> create mode 100644 UefiPayloadPkg/Tools/MkFitImage.py
> create mode 100644
> UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
> create mode 100644
> UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
>
> diff --git a/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
> b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
> new file mode 100644
> index 0000000000..31c9ec0bfb
> --- /dev/null
> +++ b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
> @@ -0,0 +1,21 @@
> +/** @file
>
> + Universal Payload general definitions.
>
> +
>
> +Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> + @par Revision Reference:
>
> + - Universal Payload Specification 0.75 (
> https://universalpayload.github.io/documentation/)
>
> +**/
>
> +
>
> +#ifndef UNIVERSAL_PAYLOAD_BASE_H_
>
> +#define UNIVERSAL_PAYLOAD_BASE_H_
>
> +
>
> +extern GUID gUniversalPayloadBaseGuid;
>
> +
>
> +typedef struct {
>
> + UNIVERSAL_PAYLOAD_GENERIC_HEADER Header;
>
> + EFI_PHYSICAL_ADDRESS Entry;
>
> +} UNIVERSAL_PAYLOAD_BASE;
>
> +
>
> +#endif // UNIVERSAL_PAYLOAD_BASE_H_
>
> diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
> b/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
> new file mode 100644
> index 0000000000..0514d675a6
> --- /dev/null
> +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
> @@ -0,0 +1,60 @@
> +/** @file
>
> + FIT Load Image Support
>
> +Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +**/
>
> +
>
> +#ifndef FIT_LIB_H_
>
> +#define FIT_LIB_H_
>
> +
>
> +#include <PiPei.h>
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/FdtLib.h>
>
> +
>
> +typedef struct {
>
> + UINT64 RelocateType;
>
> + UINT64 Offset;
>
> +} FIT_RELOCATE_ITEM;
>
> +
>
> +typedef struct {
>
> + EFI_PHYSICAL_ADDRESS ImageBase;
>
> + EFI_PHYSICAL_ADDRESS PayloadBaseAddress;
>
> + UINT64 PayloadSize;
>
> + UINTN PayloadEntryOffset;
>
> + UINTN PayloadEntrySize;
>
> + EFI_PHYSICAL_ADDRESS PayloadEntryPoint;
>
> + UINTN RelocateTableOffset;
>
> + UINTN RelocateTableCount;
>
> + EFI_PHYSICAL_ADDRESS PayloadLoadAddress;
>
> +} FIT_IMAGE_CONTEXT;
>
> +
>
> +typedef struct {
>
> + UINT8 *Name;
>
> + UINT32 Offset;
>
> +} PROPERTY_DATA;
>
> +
>
> +#define IMAGE_BASE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT,
> ImageBase)
>
> +#define PAYLOAD_BASE_ADDR_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT,
> PayloadBaseAddress)
>
> +#define PAYLOAD_BASE_SIZE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT,
> PayloadSize)
>
> +#define PAYLOAD_ENTRY_OFFSET_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT,
> PayloadEntryOffset)
>
> +#define PAYLOAD_ENTRY_SIZE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT,
> PayloadEntrySize)
>
> +#define PAYLOAD_ENTRY_POINT_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT,
> PayloadEntryPoint)
>
> +#define RELOCATE_TABLE_OFFSET_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT,
> RelocateTableOffset)
>
> +#define RELOCATE_TABLE_COUNT_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT,
> RelocateTableCount)
>
> +#define PAYLOAD_LOAD_ADDR_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT,
> PayloadLoadAddress)
>
> +
>
> +/**
>
> + Parse the FIT image info.
>
> + @param[in] ImageBase Memory address of an image.
>
> + @param[out] Context The FIT image context pointer.
>
> + @retval EFI_UNSUPPORTED Unsupported binary type.
>
> + @retval EFI_SUCCESS FIT binary is loaded successfully.
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +ParseFitImage (
>
> + IN VOID *ImageBase,
>
> + OUT FIT_IMAGE_CONTEXT *Context
>
> + );
>
> +
>
> +#endif
>
> diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
> b/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
> new file mode 100644
> index 0000000000..9d1d8a4f61
> --- /dev/null
> +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
> @@ -0,0 +1,127 @@
> +/** @file
>
> + FIT Load Image Support
>
> +Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +**/
>
> +
>
> +#include "FitLib.h"
>
> +
>
> +PROPERTY_DATA PropertyData32List[] = {
>
> + { "data-offset", PAYLOAD_ENTRY_OFFSET_OFFSET },
>
> + { "data-size", PAYLOAD_ENTRY_SIZE_OFFSET },
>
> + { "reloc-start", RELOCATE_TABLE_OFFSET_OFFSET }
>
> +};
>
> +
>
> +PROPERTY_DATA PropertyData64List[] = {
>
> + { "entry-start", PAYLOAD_ENTRY_POINT_OFFSET },
>
> + { "load", PAYLOAD_LOAD_ADDR_OFFSET }
>
> +};
>
> +
>
> +/**
>
> + Parse the target firmware image info in FIT.
>
> + @param[in] Fdt Memory address of a fdt.
>
> + @param[in] Firmware Target name of an image.
>
> + @param[out] Context The FIT image context pointer.
>
> + @retval EFI_NOT_FOUND FIT node dose not find.
>
> + @retval EFI_SUCCESS FIT binary is loaded successfully.
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +FitParseFirmwarePropertyData (
>
> + IN VOID *Fdt,
>
> + IN CHAR8 *Firmware,
>
> + OUT FIT_IMAGE_CONTEXT *Context
>
> + )
>
> +{
>
> + CONST FDT_PROPERTY *PropertyPtr;
>
> + INT32 ImageNode;
>
> + INT32 TianoNode;
>
> + INT32 TempLen;
>
> + UINT32 *Data32;
>
> + UINT64 *Data64;
>
> + UINT32 *ContextOffset32;
>
> + UINT64 *ContextOffset64;
>
> + INT32 Index;
>
> +
>
> + ImageNode = FdtSubnodeOffsetNameLen (Fdt, 0, "images",
> (INT32)AsciiStrLen ("images"));
>
> + if (ImageNode <= 0) {
>
> + return EFI_NOT_FOUND;
>
> + }
>
> +
>
> + TianoNode = FdtSubnodeOffsetNameLen (Fdt, ImageNode, Firmware,
> (INT32)AsciiStrLen (Firmware));
>
> + if (TianoNode <= 0) {
>
> + return EFI_NOT_FOUND;
>
> + }
>
> +
>
> + for (Index = 0; Index < sizeof (PropertyData32List) / sizeof
> (PROPERTY_DATA); Index++) {
>
> + PropertyPtr = FdtGetProperty (Fdt, TianoNode,
> PropertyData32List[Index].Name, &TempLen);
>
> + Data32 = (UINT32 *)(PropertyPtr->Data);
>
> + ContextOffset32 = (UINT32 *)((UINTN)Context +
> PropertyData32List[Index].Offset);
>
> + *ContextOffset32 = Fdt32ToCpu (*Data32);
>
> + }
>
> +
>
> + for (Index = 0; Index < sizeof (PropertyData64List)/sizeof
> (PROPERTY_DATA); Index++) {
>
> + PropertyPtr = FdtGetProperty (Fdt, TianoNode,
> PropertyData64List[Index].Name, &TempLen);
>
> + Data64 = (UINT64 *)(PropertyPtr->Data);
>
> + ContextOffset64 = (UINT64 *)((UINTN)Context +
> PropertyData64List[Index].Offset);
>
> + *ContextOffset64 = Fdt64ToCpu (*Data64);
>
> + }
>
> +
>
> + return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> + Parse the FIT image info.
>
> + @param[in] ImageBase Memory address of an image.
>
> + @param[out] Context The FIT image context pointer.
>
> + @retval EFI_UNSUPPORTED Unsupported binary type.
>
> + @retval EFI_SUCCESS FIT binary is loaded successfully.
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +ParseFitImage (
>
> + IN VOID *ImageBase,
>
> + OUT FIT_IMAGE_CONTEXT *Context
>
> + )
>
> +{
>
> + VOID *Fdt;
>
> + INT32 ConfigNode;
>
> + INT32 Config1Node;
>
> + CONST FDT_PROPERTY *PropertyPtr;
>
> + INT32 TempLen;
>
> + UINT32 *Data32;
>
> + UINT64 Value;
>
> + EFI_STATUS Status;
>
> + UINTN UplSize;
>
> + CHAR8 *Firmware;
>
> +
>
> + Status = FdtCheckHeader (ImageBase);
>
> + if (EFI_ERROR (Status)) {
>
> + return EFI_UNSUPPORTED;
>
> + }
>
> +
>
> + Fdt = ImageBase;
>
> + PropertyPtr = FdtGetProperty (Fdt, 0, "size", &TempLen);
>
> + Data32 = (UINT32 *)(PropertyPtr->Data);
>
> + UplSize = Value = Fdt32ToCpu (*Data32);
>
> + ConfigNode = FdtSubnodeOffsetNameLen (Fdt, 0, "configurations",
> (INT32)AsciiStrLen ("configurations"));
>
> + if (ConfigNode <= 0) {
>
> + return EFI_NOT_FOUND;
>
> + }
>
> +
>
> + Config1Node = FdtSubnodeOffsetNameLen (Fdt, ConfigNode, "conf-1",
> (INT32)AsciiStrLen ("conf-1"));
>
> + if (Config1Node <= 0) {
>
> + return EFI_NOT_FOUND;
>
> + }
>
> +
>
> + PropertyPtr = FdtGetProperty (Fdt, Config1Node, "firmware", &TempLen);
>
> + Firmware = (CHAR8 *)(PropertyPtr->Data);
>
> +
>
> + FitParseFirmwarePropertyData (Fdt, Firmware, Context);
>
> +
>
> + Context->ImageBase = (EFI_PHYSICAL_ADDRESS)ImageBase;
>
> + Context->PayloadSize = UplSize;
>
> + Context->RelocateTableCount = (Context->PayloadEntrySize -
> (Context->RelocateTableOffset - Context->PayloadEntryOffset)) / sizeof
> (FIT_RELOCATE_ITEM);
>
> +
>
> + return EFI_SUCCESS;
>
> +}
>
> diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
> b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
> new file mode 100644
> index 0000000000..3c5dacbb65
> --- /dev/null
> +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
> @@ -0,0 +1,150 @@
> +/** @file
>
> + ELF Load Image Support
>
> +Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +**/
>
> +
>
> +#include <PiPei.h>
>
> +#include <UniversalPayload/UniversalPayload.h>
>
> +#include <Guid/UniversalPayloadBase.h>
>
> +#include <UniversalPayload/ExtraData.h>
>
> +
>
> +#include <Ppi/LoadFile.h>
>
> +
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/HobLib.h>
>
> +#include <Library/PeiServicesLib.h>
>
> +#include <Library/MemoryAllocationLib.h>
>
> +#include <Library/BaseMemoryLib.h>
>
> +
>
> +#include "FitLib.h"
>
> +
>
> +/**
>
> + The wrapper function of PeiLoadImageLoadImage().
>
> + @param This - Pointer to EFI_PEI_LOAD_FILE_PPI.
>
> + @param FileHandle - Pointer to the FFS file header of the image.
>
> + @param ImageAddressArg - Pointer to PE/TE image.
>
> + @param ImageSizeArg - Size of PE/TE image.
>
> + @param EntryPoint - Pointer to entry point of specified image file
> for output.
>
> + @param AuthenticationState - Pointer to attestation authentication
> state of image.
>
> + @return Status of PeiLoadImageLoadImage().
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +PeiLoadFileLoadPayload (
>
> + IN CONST EFI_PEI_LOAD_FILE_PPI *This,
>
> + IN EFI_PEI_FILE_HANDLE FileHandle,
>
> + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL,
>
> + OUT UINT64 *ImageSizeArg OPTIONAL,
>
> + OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
>
> + OUT UINT32 *AuthenticationState
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + FIT_IMAGE_CONTEXT Context;
>
> + UINTN Instance;
>
> + VOID *Binary;
>
> + FIT_RELOCATE_ITEM *RelocateTable;
>
> + UNIVERSAL_PAYLOAD_BASE *PayloadBase;
>
> + UINTN Length;
>
> + UINTN Delta;
>
> + UINTN Index;
>
> +
>
> + Instance = 0;
>
> + do {
>
> + Status = PeiServicesFfsFindSectionData3 (EFI_SECTION_RAW, Instance++,
> FileHandle, &Binary, AuthenticationState);
>
> + if (EFI_ERROR (Status)) {
>
> + return Status;
>
> + }
>
> +
>
> + ZeroMem (&Context, sizeof (Context));
>
> + Status = ParseFitImage (Binary, &Context);
>
> + } while (EFI_ERROR (Status));
>
> +
>
> + if (EFI_ERROR (Status)) {
>
> + ASSERT_EFI_ERROR (Status);
>
> + return Status;
>
> + }
>
> +
>
> + DEBUG ((
>
> + DEBUG_INFO,
>
> + "Before Rebase Payload File Base: 0x%08x, File Size: 0x%08X,
> EntryPoint: 0x%08x\n",
>
> + Context.PayloadBaseAddress,
>
> + Context.PayloadSize,
>
> + Context.PayloadEntryPoint
>
> + ));
>
> + Context.PayloadBaseAddress = (EFI_PHYSICAL_ADDRESS)AllocatePages
> (EFI_SIZE_TO_PAGES (Context.PayloadSize));
>
> +
>
> + RelocateTable = (FIT_RELOCATE_ITEM *)(UINTN)(Context.PayloadBaseAddress
> + Context.RelocateTableOffset);
>
> + CopyMem ((VOID *)Context.PayloadBaseAddress, Binary,
> Context.PayloadSize);
>
> +
>
> + if (Context.PayloadBaseAddress > Context.PayloadLoadAddress) {
>
> + Delta = Context.PayloadBaseAddress -
> Context.PayloadLoadAddress;
>
> + Context.PayloadEntryPoint += Delta;
>
> + for (Index = 0; Index < Context.RelocateTableCount; Index++) {
>
> + if ((RelocateTable[Index].RelocateType == 10) ||
> (RelocateTable[Index].RelocateType == 3)) {
>
> + *((UINT64 *)(Context.PayloadBaseAddress +
> RelocateTable[Index].Offset)) = *((UINT64 *)(Context.PayloadBaseAddress +
> RelocateTable[Index].Offset)) + Delta;
>
> + }
>
> + }
>
> + } else {
>
> + Delta = Context.PayloadLoadAddress -
> Context.PayloadBaseAddress;
>
> + Context.PayloadEntryPoint -= Delta;
>
> + for (Index = 0; Index < Context.RelocateTableCount; Index++) {
>
> + if ((RelocateTable[Index].RelocateType == 10) ||
> (RelocateTable[Index].RelocateType == 3)) {
>
> + *((UINT64 *)(Context.PayloadBaseAddress +
> RelocateTable[Index].Offset)) = *((UINT64 *)(Context.PayloadBaseAddress +
> RelocateTable[Index].Offset)) - Delta;
>
> + }
>
> + }
>
> + }
>
> +
>
> + DEBUG ((
>
> + DEBUG_INFO,
>
> + "After Rebase Payload File Base: 0x%08x, File Size: 0x%08X,
> EntryPoint: 0x%08x\n",
>
> + Context.PayloadBaseAddress,
>
> + Context.PayloadSize,
>
> + Context.PayloadEntryPoint
>
> + ));
>
> +
>
> + Length = sizeof (UNIVERSAL_PAYLOAD_BASE);
>
> + PayloadBase = BuildGuidHob (
>
> + &gUniversalPayloadBaseGuid,
>
> + Length
>
> + );
>
> + PayloadBase->Entry = (EFI_PHYSICAL_ADDRESS)Context.ImageBase;
>
> +
>
> + *ImageAddressArg = Context.PayloadBaseAddress;
>
> + *ImageSizeArg = Context.PayloadSize;
>
> + *EntryPoint = Context.PayloadEntryPoint;
>
> +
>
> + return EFI_SUCCESS;
>
> +}
>
> +
>
> +EFI_PEI_LOAD_FILE_PPI mPeiLoadFilePpi = {
>
> + PeiLoadFileLoadPayload
>
> +};
>
> +
>
> +EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = {
>
> + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
>
> + &gEfiPeiLoadFilePpiGuid,
>
> + &mPeiLoadFilePpi
>
> +};
>
> +
>
> +/**
>
> + Install Pei Load File PPI.
>
> + @param FileHandle Handle of the file being invoked.
>
> + @param PeiServices Describes the list of possible PEI Services.
>
> + @retval EFI_SUCESS The entry point executes successfully.
>
> + @retval Others Some error occurs during the execution of this
> function.
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +InitializeFitPayloadLoaderPeim (
>
> + IN EFI_PEI_FILE_HANDLE FileHandle,
>
> + IN CONST EFI_PEI_SERVICES **PeiServices
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> +
>
> + Status = PeiServicesInstallPpi (&gPpiLoadFilePpiList);
>
> +
>
> + return Status;
>
> +}
>
> diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
> b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
> new file mode 100644
> index 0000000000..acb0e09f68
> --- /dev/null
> +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
> @@ -0,0 +1,59 @@
> +## @file
>
> +# Produce LoadFile PPI for payload loading.
>
> +#
>
> +# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
>
> +#
>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +#
>
> +##
>
> +
>
> +[Defines]
>
> + INF_VERSION = 0x00010005
>
> + BASE_NAME = FitPayloadLoaderPeim
>
> + FILE_GUID = 55AC82C8-FC17-4C56-BCDA-990BB0A73E41
>
> + MODULE_TYPE = PEIM
>
> + VERSION_STRING = 1.0
>
> +
>
> + ENTRY_POINT = InitializeFitPayloadLoaderPeim
>
> +
>
> +#
>
> +# The following information is for reference only and not required by the
> build tools.
>
> +#
>
> +# VALID_ARCHITECTURES = IA32 X64
>
> +#
>
> +
>
> +[Sources]
>
> + FitPayloadLoaderPeim.c
>
> + FitLib.h
>
> + FitLib/FitLib.c
>
> +
>
> +[Packages]
>
> + MdePkg/MdePkg.dec
>
> + MdeModulePkg/MdeModulePkg.dec
>
> + PcAtChipsetPkg/PcAtChipsetPkg.dec
>
> + UefiPayloadPkg/UefiPayloadPkg.dec
>
> +
>
> +[LibraryClasses]
>
> + PcdLib
>
> + MemoryAllocationLib
>
> + BaseMemoryLib
>
> + PeiServicesLib
>
> + HobLib
>
> + BaseLib
>
> + PeimEntryPoint
>
> + DebugLib
>
> + FdtLib
>
> +
>
> +[Ppis]
>
> + gEfiPeiLoadFilePpiGuid ## PRODUCES
>
> +
>
> +[Pcd]
>
> + gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister
>
> + gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister
>
> +
>
> +[Guids]
>
> + gUniversalPayloadExtraDataGuid ## PRODUCES
>
> + gUniversalPayloadBaseGuid ## PRODUCES
>
> +
>
> +[Depex]
>
> + TRUE
>
> diff --git a/UefiPayloadPkg/Readme.md b/UefiPayloadPkg/Readme.md
> new file mode 100644
> index 0000000000..616a5dd467
> --- /dev/null
> +++ b/UefiPayloadPkg/Readme.md
> @@ -0,0 +1,191 @@
> +# UefiPayloadPkg
>
> +Provide UEFI Universal Payload for different bootloader to generate EFI
> environment
>
> +
>
> +# Spec
>
> +
>
> +UniversalPayload URL:
> https://universalscalablefirmware.github.io/documentation/2_universal_payload.html
>
> +
>
> +ELF Format URL: https://refspecs.linuxfoundation.org/elf/elf.pdf
>
> +
>
> +FIT Format URL:
> https://universalpayload.github.io/spec/chapter2-payload-image-format.html
>
> +
>
> +# Uefi UniversalPayload Format
>
> + | Binary Format | HandOffPayload - HOB |
>
> + |---------------|----------------------|
>
> + | ELF | V (Default) |
>
> + | FIT | V |
>
> +
>
> +# Binary Format
>
> + - ELF
>
> + ```
>
> + + +-----------------------+
>
> + | | UniversalPayloadEntry | <-----------
> UefiPayloadPkg\UefiPayloadEntry\UniversalPayloadEntry.c:_ModuleEntryPoint
> (HOB)
>
> + | +-----------------------+
>
> + | | .upld_info | patch it directly
>
> + ELF Format | +-----------------------+
>
> + | | .upld.uefi_fv | patch it directly
>
> + | +-----------------------+
>
> + | | .upld.bds_fv | patch it directly
>
> + | +-----------------------+
>
> + | | .upld.<afpx>_fv | patch it directly
>
> + + +-----------------------+
>
> + ```
>
> +
>
> + - FIT
>
> + ```
>
> + + +-----------------------+
>
> + FIT Data | | FIT Header | <----------- Generate by
> pylibfdt
>
> + + +-----------------------+
>
> + PECOFF Format | | UniversalPayloadEntry | <-----------
> UefiPayloadPkg\UefiPayloadEntry\FitUniversalPayloadEntry.c:_ModuleEntryPoint
> (HOB)
>
> + + +-----------------------+
>
> + Relocate Data | | reloc-start |
>
> + + +-----------------------+
>
> + | | uefi_fv | patch it directly
>
> + | +-----------------------+
>
> + Multi Binary | | bds_fv | patch it directly
>
> + | +-----------------------+
>
> + | | afp_xxx_fv | patch it directly
>
> + | +-----------------------+
>
> + | | afp_xxx_fv | patch it directly
>
> + + +-----------------------+
>
> + ```
>
> +
>
> +# Environment
>
> + - ELF
>
> + ```
>
> + Download and install
> https://github.com/llvm/llvm-project/releases/tag/llvmorg-10.0.1
>
> + ```
>
> + - FIT
>
> + - Windows
>
> + ```powershell
>
> + Set-ExecutionPolicy Bypass -Scope Process -Force;
> [System.Net.ServicePointManager]::SecurityProtocol =
> [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex
> ((New-Object System.Net.WebClient).DownloadString('
> https://chocolatey.org/install.ps1'))
>
> + choco install dtc-msys2
>
> + pip3 install pefile
>
> + pip3 install swig
>
> + pip3 install pylibfdt
>
> + ```
>
> + - Ubuntu
>
> + ```bash
>
> + sudo apt install -y u-boot-tools
>
> + pip3 install pefile
>
> + pip3 install swig
>
> + pip3 install pylibfdt
>
> + ```
>
> +# How to build UEFI UniversalPayload
>
> + - Windows
>
> + - edksetup Rebuild
>
> + - Linux
>
> + - make -C BaseTools
>
> + - source edksetup.sh
>
> +
>
> + - UniversalPayload.elf
>
> + - python UefiPayloadPkg/UniversalPayloadBuild.py -t <TOOL_CHAIN_TAG>
>
> + - llvm-objdump -h Build/UefiPayloadPkgX64/UniversalPayload.elf
>
> +
>
> + - UniversalPayload.fit
>
> + - python UefiPayloadPkg/UniversalPayloadBuild.py -t <TOOL_CHAIN_TAG>
> --Fit
>
> + - fdtdump Build/UefiPayloadPkgX64/UniversalPayload.fit
>
> +
>
> +# Edk2boot + UefiUniversalPayload
>
> +ELF Edk2boot use below way to support compress and sign.
>
> +
>
> +- ELF Behavior - Edk2boot + UefiUniversalPayload.elf
>
> + ```
>
> + Boot Flow
>
> +
> +-------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+-------------------+
>
> + | Platform Init
> | Universal Loader Interface
> | OS |
>
> +
> +-------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+-------------------+
>
> +
>
> HOBs
>
> + SEC -> PEI -> DXE -> DXE IPL ->
> UefiPayloadPkg\PayloadLoaderPeim\PayloadLoaderPeim.c
> ------------------------------------------------------------------------------------>
> Load UniversalPayload.elf -> Operation System
>
> +
>
> +
>
> + | Platform Initialize - Edk2
>
> | UniversalPayload - Edk2
> |
>
> +
> +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+
>
> +
>
> + Binary Format
>
> +
>
> + +-------------------+
>
> + | BIOS.rom |
>
> + +-------------------+
>
> + | Other Firmware |
>
> + +-------------------+
>
> + | ... | FMMT
>
> UniversalPayloadBuild.py
>
> + +-------------------+<----------------+-----------------------+
> GenFfs +-----------------------+ Rsa2048Sha256 Sign
> +-----------------------+ LzmaCompress +----------------------+ GenSec
> +--------------------------------+
>
> + | | | EDK2 FFS Header
> |<-----------| Rsa2048Sha256 Hash |<--------------------|
> UniversalPayload.lzma |<--------------| EDK2 SEC Header |<--------|
> UniversalPayload.elf |
>
> + | RAW Data | +-----------------------+
> +-----------------------+
> +-----------------------+ +----------------------+
> +--------------------------------+
>
> + | | | Rsa2048Sha256 Hash |
> | UniversalPayload.lzma |
> | UniversalPayload.elf | | upld_info
> |
>
> + | | +-----------------------+
> +-----------------------+
> +----------------------+
> +--------------------------------+
>
> + | | | UniversalPayload.lzma |
>
> | upld_info | | upld.uefi_fv
> |
>
> + +-------------------+<----------------+-----------------------+
>
> +----------------------+
> +--------------------------------+
>
> + | ... |
>
> | upld.uefi_fv | | upld.bds_fv
> |
>
> + +-------------------+
>
> +----------------------+
> +--------------------------------+
>
> + | Other Firmware |
>
> | upld.bds_fv | | upld.AFP1
> |
>
> + +-------------------+
>
> +----------------------+
> +--------------------------------+
>
> +
>
> | upld.AFP1 | | upld.AFP2
> |
>
> +
>
> +----------------------+
> +--------------------------------+
>
> +
>
> | upld.AFP2 | | ...
> |
>
> +
>
> +----------------------+
> +--------------------------------+
>
> +
>
> | ... | | upld.AFPn
> |
>
> +
>
> +----------------------+
> +--------------------------------+
>
> +
>
> | upld.AFPn |
>
> +
>
> +----------------------+
>
> + ```
>
> +
>
> +FIT Edk2boot use below way to support compress and sign
>
> +- FIT Behavior - Edk2boot + UefiUniversalPayload.fit
>
> + ```
>
> + Boot Flow
>
> +
> +-------------------------------------------------------------------------------------+------------------------------------------------------------------------+-------------------+
>
> + | Platform Init
> | Universal Loader Interface
> | OS |
>
> +
> +-------------------------------------------------------------------------------------+------------------------------------------------------------------------+-------------------+
>
> +
> HOBs
>
> + SEC -> PEI -> DXE -> DXE IPL ->
> *UefiPayloadPkg\PayloadLoaderPeim\PayloadLoaderPeim.c
> ----------------------------------------------> Load UniversalPayload.fit
> -> Operation System
>
> +
>
> + Binary Format
>
> +
>
> + | Platform Initialize - Edk2
> | UniversalPayload -
> Edk2 (UniversalPayloadBuild.py --Fit) |
>
> +
> +---------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
>
> +
>
> + +-------------------+
>
> + | BIOS.rom |
>
> + +-------------------+
>
> + | Other Firmware |
>
> + +-------------------+
>
> + | ... | FMMT
>
> UniversalPayloadBuild.py --Fit tianocore -> data-offset
>
> +
> +-------------------+<----------------+--------------------------------+
> GenFfs +--------------------------------+ GenSec
> +--------------------------------+ tianocore -> reloc-start
> +--------------------------+
>
> + | | | EDK2 FFS Header
> |<--------| EDK2 SEC Header |<--------| FIT Header
> |<-------------------------| UniversalPayload.pecoff |
>
> + | |
> +--------------------------------+
> +--------------------------------+ | description = "Uefi
> Payload"; | +--------------------------+
>
> + | | | EDK2 SEC Header
> | | FIT Header | | ...
> |
>
> + | RAW Data |
> +--------------------------------+ |
> | | images { | uefi-fv -> data-offset
> +--------------------------+
>
> + | | | FIT Header
> | | | | tianocore {...};
> |<-------------------------| uefi_fv |
>
> + | | |
> | +--------------------------------+ | uefi-fv {...};
> | bds-fv -> data-offset +--------------------------+
>
> + | | |
> | | tianocore -> data | | bds-fv {...};
> |<-------------------------| bds_fv |
>
> + | |
> +--------------------------------+
> +--------------------------------+ | afp1-fv {...};
> | AFP1 -> data-offset +--------------------------+
>
> + | | | tianocore -> data
> | | tianocore -> reloc-start | | ...
> |<-------------------------| AFP1 |
>
> + | |
> +--------------------------------+
> +--------------------------------+ | afpn-fv {...};
> | AFP2 -> data-offset +--------------------------+
>
> + | | | tianocore -> reloc-start
> | | uefi-fv -> data | | }
> |<-------------------------| AFP2 |
>
> + | |
> +--------------------------------+
> +--------------------------------+ | configurations {
> | ... +--------------------------+
>
> + | | | uefi-fv -> data
> | | bds-fv -> data | | conf-1 {...}
> |<-------------------------| ... |
>
> + | |
> +--------------------------------+
> +--------------------------------+ | }
> | AFPn -> data-offset +--------------------------+
>
> + | | | bds-fv -> data
> | | AFP1-fv -> data | |
> |<-------------------------| AFPn |
>
> + | |
> +--------------------------------+
> +--------------------------------+ |
> | +--------------------------+
>
> + | | | AFP1-fv -> data
> | | AFP2-fv -> data | |
> |
>
> + | |
> +--------------------------------+
> +--------------------------------+
> +--------------------------------+
>
> + | | | AFP2-fv -> data
> | | ... | | tianocore -> data
> |
>
> + | |
> +--------------------------------+
> +--------------------------------+
> +--------------------------------+
>
> + | | | ...
> | | AFPn-fv -> data | | tianocore ->
> reloc-start |
>
> + | |
> +--------------------------------+
> +--------------------------------+
> +--------------------------------+
>
> + | | | AFPn-fv -> data
> | | uefi-fv -> data
> |
>
> +
> +-------------------+<----------------+--------------------------------+
>
> +--------------------------------+
>
> + | ... |
> | bds-fv -> data
> |
>
> + +-------------------+
>
> +--------------------------------+
>
> + | Other Firmware |
> | AFP1-fv -> data
> |
>
> + +-------------------+
>
> +--------------------------------+
>
> +
> | AFP2-fv -> data
> |
>
> +
>
> +--------------------------------+
>
> +
> | ...
> |
>
> +
>
> +--------------------------------+
>
> +
> | AFPn-fv -> data
> |
>
> +
>
> +--------------------------------+
>
> +
>
> + ```
>
> diff --git a/UefiPayloadPkg/Tools/MkFitImage.py
> b/UefiPayloadPkg/Tools/MkFitImage.py
> new file mode 100644
> index 0000000000..82ab933d6d
> --- /dev/null
> +++ b/UefiPayloadPkg/Tools/MkFitImage.py
> @@ -0,0 +1,272 @@
> +## @file
>
> +# This file is a script to build fit image.
>
> +# It generate a dtb header and combine a binary file after this header.
>
> +#
>
> +# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +##
>
> +
>
> +from os.path import exists
>
> +import libfdt
>
> +from ctypes import *
>
> +import time
>
> +
>
> +class FIT_IMAGE_INFO_HEADER:
>
> + """Class for user setting data to use MakeFitImage()
>
> + """
>
> + _pack_ = 1
>
> + _fields_ = [
>
> + ('Compatible', str),
>
> + ('UplVersion', int),
>
> + ('Description', str),
>
> + ('Type', str),
>
> + ('Arch', str),
>
> + ('Compression', str),
>
> + ('Revision', int),
>
> + ('BuildType', str),
>
> + ('Capabilities', str),
>
> + ('Producer', str),
>
> + ('ImageId', str),
>
> + ('DataOffset', int),
>
> + ('DataSize', int),
>
> + ('RelocStart', int),
>
> + ('LoadAddr', int),
>
> + ('Entry', int),
>
> + ('Binary', str),
>
> + ('TargetPath', str),
>
> + ('UefifvPath', str),
>
> + ('BdsfvPath', str),
>
> + ('NetworkfvPath', str),
>
> + ('Project', str),
>
> + ]
>
> +
>
> + def __init__(self):
>
> + self.Compatible = 'universal-payload'
>
> + self.UplVersion = 0x0100
>
> + self.TargetPath = 'mkimage.fit'
>
> +
>
> +def CreatFdt(Fdt):
>
> + FdtEmptyTree = libfdt.fdt_create_empty_tree(Fdt, len(Fdt))
>
> + if FdtEmptyTree != 0:
>
> + print('\n- Failed - Create Fdt failed!')
>
> + return False
>
> + return True
>
> +
>
> +def BuildConfNode(Fdt, ParentNode, MultiImage):
>
> + ConfNode1 = libfdt.fdt_add_subnode(Fdt, ParentNode, 'conf-1')
>
> +
>
> + libfdt.fdt_setprop(Fdt, ConfNode1, 'require-fit', b'', 0)
>
> + libfdt.fdt_setprop(Fdt, ConfNode1, 'firmware', bytes('tianocore',
> 'utf-8'), len('tianocore') + 1)
>
> +
>
> +def BuildFvImageNode(Fdt, InfoHeader, ParentNode, DataOffset, DataSize,
> Description):
>
> + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-size', DataSize)
>
> + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-offset', DataOffset)
>
> + libfdt.fdt_setprop(Fdt, ParentNode, 'compression', bytes('none',
> 'utf-8'), len('none') + 1)
>
> + libfdt.fdt_setprop(Fdt, ParentNode, 'project ',
> bytes('tianocore', 'utf-8'), len('tianocore') + 1)
>
> + libfdt.fdt_setprop(Fdt, ParentNode, 'arch', bytes('x86_64',
> 'utf-8'), len('x86_64') + 1)
>
> + libfdt.fdt_setprop(Fdt, ParentNode, 'type',
> bytes('flat-binary', 'utf-8'), len('flat-binary') + 1)
>
> + libfdt.fdt_setprop(Fdt, ParentNode, 'description',
> bytes(Description, 'utf-8'), len(Description) + 1)
>
> +
>
> +def BuildTianoImageNode(Fdt, InfoHeader, ParentNode, DataOffset,
> DataSize, Description):
>
> + #
>
> + # Set 'load' and 'data-offset' to reserve the memory first.
>
> + # They would be set again when Fdt completes or this function parses
> target binary file.
>
> + #
>
> + if InfoHeader.LoadAddr is not None:
>
> + libfdt.fdt_setprop_u64(Fdt, ParentNode, 'load',
> InfoHeader.LoadAddr)
>
> + if InfoHeader.Entry is not None:
>
> + libfdt.fdt_setprop_u64(Fdt, ParentNode, 'entry-start',
> InfoHeader.Entry)
>
> + if InfoHeader.RelocStart is not None:
>
> + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'reloc-start',
> InfoHeader.RelocStart)
>
> + if InfoHeader.DataSize is not None:
>
> + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-size', DataSize)
>
> + if InfoHeader.DataOffset is not None:
>
> + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-offset', DataOffset)
>
> + if InfoHeader.Producer is not None:
>
> + libfdt.fdt_setprop(Fdt, ParentNode, 'producer ',
> bytes(InfoHeader.Producer, 'utf-8'), len(InfoHeader.Producer) + 1)
>
> + if InfoHeader.Capabilities is not None:
>
> + CapStrs = ','.join(InfoHeader.Capabilities)
>
> + libfdt.fdt_setprop(Fdt, ParentNode, 'capabilities ',
> bytes(CapStrs, 'utf-8'), len(CapStrs) + 1)
>
> + if InfoHeader.Type is not None:
>
> + libfdt.fdt_setprop(Fdt, ParentNode, 'type ',
> bytes(InfoHeader.Type, 'utf-8'), len(InfoHeader.Type) + 1)
>
> + if InfoHeader.Arch is not None:
>
> + libfdt.fdt_setprop(Fdt, ParentNode, 'arch ',
> bytes(InfoHeader.Arch, 'utf-8'), len(InfoHeader.Arch) + 1)
>
> + if InfoHeader.Project is not None:
>
> + libfdt.fdt_setprop(Fdt, ParentNode, 'project ',
> bytes(InfoHeader.Project, 'utf-8'), len(InfoHeader.Project) + 1)
>
> + if InfoHeader.Description is not None:
>
> + libfdt.fdt_setprop(Fdt, ParentNode, 'description',
> bytes(Description, 'utf-8'), len(Description) + 1)
>
> +
>
> +#
>
> +# The subnode would be inserted from bottom to top of structure block.
>
> +#
>
> +def BuildFitImage(Fdt, InfoHeader):
>
> + MultiImage = [
>
> + ["tianocore", InfoHeader.Binary, BuildTianoImageNode ,
> InfoHeader.Description, None, 0 ],
>
> + ["uefi-fv", InfoHeader.UefifvPath, BuildFvImageNode,
> "UEFI Firmware Volume", None, 0 ],
>
> + ["bds-fv", InfoHeader.BdsfvPath, BuildFvImageNode ,
> "BDS Firmware Volume", None, 0 ],
>
> + ["network-fv", InfoHeader.NetworkfvPath, BuildFvImageNode ,
> "Network Firmware Volume", None, 0 ],
>
> + ]
>
> +
>
> + #
>
> + # Set basic information
>
> + #
>
> + libfdt.fdt_setprop_u32(Fdt, 0, 'build-revision ', InfoHeader.Revision)
>
> + libfdt.fdt_setprop_u32(Fdt, 0, 'spec-version', InfoHeader.UplVersion)
>
> +
>
> + #
>
> + # Build configurations node
>
> + #
>
> + ConfNode = libfdt.fdt_add_subnode(Fdt, 0, 'configurations')
>
> + BuildConfNode(Fdt, ConfNode, MultiImage)
>
> +
>
> + # Build image
>
> + DataOffset = InfoHeader.DataOffset
>
> + for Index in range (0, len (MultiImage)):
>
> + _, Path, _, _, _, _ = MultiImage[Index]
>
> + if exists(Path) == 1:
>
> + TempBinary = open(Path, 'rb')
>
> + BinaryData = TempBinary.read()
>
> + TempBinary.close()
>
> + MultiImage[Index][-2] = BinaryData
>
> + MultiImage[Index][-1] = DataOffset
>
> + DataOffset += len (BinaryData)
>
> + libfdt.fdt_setprop_u32(Fdt, 0, 'size', DataOffset)
>
> + posix_time = int(time.time())
>
> + libfdt.fdt_setprop_u32(Fdt, 0, 'timestamp', posix_time)
>
> + DescriptionFit = 'Uefi OS Loader'
>
> + libfdt.fdt_setprop(Fdt, 0, 'description', bytes(DescriptionFit,
> 'utf-8'), len(DescriptionFit) + 1)
>
> +
>
> + ImageNode = libfdt.fdt_add_subnode(Fdt, 0, 'images')
>
> + for Item in reversed (MultiImage):
>
> + Name, Path, BuildFvNode, Description, BinaryData, DataOffset =
> Item
>
> + FvNode = libfdt.fdt_add_subnode(Fdt, ImageNode, Name)
>
> + BuildFvNode (Fdt, InfoHeader, FvNode, DataOffset,
> len(BinaryData), Description)
>
> +
>
> + #
>
> + # Create new image file and combine all binary.
>
> + #
>
> + DtbFile = open(InfoHeader.TargetPath, "wb")
>
> + DtbFile.truncate()
>
> + DtbFile.write(Fdt)
>
> + for Item in MultiImage:
>
> + _, _, _, _, BinaryData, _ = Item
>
> + DtbFile.write(BinaryData)
>
> + DtbFile.close()
>
> +
>
> + return True
>
> +
>
> +def MakeFitImage(InfoHeader):
>
> + #
>
> + # Allocate fdt byte array.
>
> + #
>
> + Fdt = bytearray(InfoHeader.DataOffset)
>
> +
>
> + #
>
> + # Create fdt empty tree.
>
> + #
>
> + if CreatFdt(Fdt) is False:
>
> + return False
>
> +
>
> + #
>
> + # Parse args to build fit image.
>
> + #
>
> + return BuildFitImage(Fdt, InfoHeader)
>
> +
>
> +def ReplaceFv (UplBinary, SectionFvFile, SectionName):
>
> + try:
>
> + #
>
> + # Get Original Multi Fv
>
> + #
>
> + with open (UplBinary, "rb") as File:
>
> + Dtb = File.read ()
>
> + Fit = libfdt.Fdt (Dtb)
>
> + NewFitHeader = bytearray(Dtb[0:Fit.totalsize()])
>
> + FitSize = len(Dtb)
>
> +
>
> + LoadablesList = []
>
> + ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0,
> 'images')
>
> + FvNode = libfdt.fdt_subnode_offset(NewFitHeader,
> ImagesNode, 'uefi-fv')
>
> + NodeDepth = libfdt.fdt_node_depth (NewFitHeader, ImagesNode)
>
> + node_name = libfdt.fdt_get_name(NewFitHeader, FvNode)
>
> + FvNode = libfdt.fdt_next_node(NewFitHeader, FvNode,
> NodeDepth)
>
> +
>
> + while node_name[0][-2:] == 'fv':
>
> + LoadablesList.append (node_name[0])
>
> + node_name = libfdt.fdt_get_name(NewFitHeader, FvNode[0])
>
> + FvNode = libfdt.fdt_next_node(NewFitHeader, FvNode[0],
> NodeDepth)
>
> + #
>
> + # Get current Fit Binary FV data
>
> + #
>
> + MultiFvList = []
>
> + for Item in LoadablesList:
>
> + ImageNode = libfdt.fdt_subnode_offset(NewFitHeader,
> ImagesNode, Item)
>
> + ImageOffset = int.from_bytes (libfdt.fdt_getprop
> (NewFitHeader, ImageNode, 'data-offset')[0], 'big')
>
> + ImageSize = int.from_bytes (libfdt.fdt_getprop
> (NewFitHeader, ImageNode, 'data-size')[0], 'big')
>
> + MultiFvList.append ([Item, Dtb[ImageOffset:ImageOffset +
> ImageSize]])
>
> +
>
> + IsFvExist = False
>
> + for Index in range (0, len (MultiFvList)):
>
> + if MultiFvList[Index][0] == SectionName:
>
> + with open (SectionFvFile, 'rb') as File:
>
> + MultiFvList[Index][1] = File.read ()
>
> + ImageNode = libfdt.fdt_subnode_offset(NewFitHeader,
> ImagesNode, SectionName)
>
> + ImageSize = int.from_bytes (libfdt.fdt_getprop
> (NewFitHeader, ImageNode, 'data-size')[0], 'big')
>
> + ReplaceOffset = int.from_bytes (libfdt.fdt_getprop
> (NewFitHeader, ImageNode, 'data-offset')[0], 'big')
>
> + OffsetDelta = len(MultiFvList[Index][1]) - ImageSize
>
> + FitSize += OffsetDelta
>
> + IsFvExist = True
>
> + libfdt.fdt_setprop_u32(NewFitHeader, ImageNode,
> 'data-size', len(MultiFvList[Index][1]))
>
> +
>
> + #
>
> + # Update new fit header
>
> + #
>
> + ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'images')
>
> + if (IsFvExist == False):
>
> + with open (SectionFvFile, 'rb') as File:
>
> + SectionFvFileBinary = File.read ()
>
> + MultiFvList.append ([SectionName, SectionFvFileBinary])
>
> + FvNode = libfdt.fdt_add_subnode(NewFitHeader, ImagesNode,
> SectionName)
>
> + BuildFvImageNode (NewFitHeader, None, FvNode, FitSize,
> len(SectionFvFileBinary), SectionName + " Firmware Volume")
>
> + FitSize += len(SectionFvFileBinary)
>
> + else:
>
> + for Index in range (0, len (MultiFvList)):
>
> + ImageNode = libfdt.fdt_subnode_offset(NewFitHeader,
> ImagesNode, MultiFvList[Index][0])
>
> + ImageOffset = int.from_bytes (libfdt.fdt_getprop
> (NewFitHeader, ImageNode, 'data-offset')[0], 'big')
>
> + if ImageOffset > ReplaceOffset:
>
> + libfdt.fdt_setprop_u32(NewFitHeader, ImageNode,
> 'data-offset', ImageOffset + OffsetDelta)
>
> +
>
> + ConfNodes = libfdt.fdt_subnode_offset(NewFitHeader, 0,
> 'configurations')
>
> + libfdt.fdt_setprop(NewFitHeader, ConfNodes, 'default ',
> bytes('conf-1', 'utf-8'), len('conf-1') + 1)
>
> + ConfNode = libfdt.fdt_subnode_offset(NewFitHeader,
> ConfNodes, 'conf-1')
>
> +
>
> + libfdt.fdt_setprop_u32(NewFitHeader, 0, 'size', FitSize)
>
> +
>
> + #
>
> + # Generate new fit image
>
> + #
>
> + ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0,
> 'images')
>
> + TianoNode = libfdt.fdt_subnode_offset(NewFitHeader,
> ImagesNode, 'tianocore')
>
> + TianoOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader,
> TianoNode, 'data-offset')[0], 'big')
>
> + TianoSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader,
> TianoNode, 'data-size')[0], 'big')
>
> + TianoBinary = Dtb[TianoOffset:TianoOffset + TianoSize]
>
> +
>
> + print("\nGenerate new fit image:")
>
> + NewUplBinary = bytearray(FitSize)
>
> + print("Update fit header\t to 0x0\t\t ~ " +
> str(hex(len(NewFitHeader))))
>
> + NewUplBinary[:len(NewFitHeader)] = NewFitHeader
>
> + print("Update tiano image\t to " + str(hex(len(NewFitHeader))) +
> "\t ~ " + str(hex(len(NewFitHeader) + len(TianoBinary))))
>
> + NewUplBinary[len(NewFitHeader):len(NewFitHeader) +
> len(TianoBinary)] = TianoBinary
>
> + for Index in range (0, len (MultiFvList)):
>
> + ImageNode = libfdt.fdt_subnode_offset(NewFitHeader,
> ImagesNode, MultiFvList[Index][0])
>
> + ImageOffset = int.from_bytes (libfdt.fdt_getprop
> (NewFitHeader, ImageNode, 'data-offset')[0], 'big')
>
> + ImageSize = int.from_bytes (libfdt.fdt_getprop
> (NewFitHeader, ImageNode, 'data-size')[0], 'big')
>
> + NewUplBinary[ImageOffset:ImageOffset + ImageSize] =
> MultiFvList[Index][1]
>
> + print("Update " + MultiFvList[Index][0] + "\t\t to " +
> str(hex(ImageOffset)) + "\t ~ " + str(hex(ImageOffset + ImageSize)))
>
> +
>
> + with open (UplBinary, "wb") as File:
>
> + File.write (NewUplBinary)
>
> +
>
> + return 0
>
> + except Exception as Ex:
>
> + print(Ex)
>
> + return 1
>
> diff --git a/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
> b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
> new file mode 100644
> index 0000000000..a53d988627
> --- /dev/null
> +++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
> @@ -0,0 +1,654 @@
> +/** @file
>
> + Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +**/
>
> +
>
> +#include "UefiPayloadEntry.h"
>
> +#include <Library/FdtLib.h>
>
> +#include <Guid/UniversalPayloadBase.h>
>
> +
>
> +#define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT
> | \
>
> +
> EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
>
> + EFI_RESOURCE_ATTRIBUTE_TESTED
> | \
>
> +
> EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \
>
> +
> EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \
>
> +
> EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \
>
> +
> EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED | \
>
> + EFI_RESOURCE_ATTRIBUTE_16_BIT_IO
> | \
>
> + EFI_RESOURCE_ATTRIBUTE_32_BIT_IO
> | \
>
> + EFI_RESOURCE_ATTRIBUTE_64_BIT_IO
> | \
>
> + EFI_RESOURCE_ATTRIBUTE_PERSISTENT
> )
>
> +
>
> +#define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT |
> \
>
> + EFI_RESOURCE_ATTRIBUTE_INITIALIZED
> | \
>
> + EFI_RESOURCE_ATTRIBUTE_TESTED
> )
>
> +
>
> +extern VOID *mHobList;
>
> +
>
> +CHAR8 *mLineBuffer = NULL;
>
> +
>
> +/**
>
> + Print all HOBs info from the HOB list.
>
> + @return The pointer to the HOB list.
>
> +**/
>
> +VOID
>
> +PrintHob (
>
> + IN CONST VOID *HobStart
>
> + );
>
> +
>
> +/**
>
> + Find the first substring.
>
> + @param String Point to the string where to find the substring.
>
> + @param CharSet Point to the string to be found.
>
> +**/
>
> +UINTN
>
> +EFIAPI
>
> +AsciiStrSpn (
>
> + IN CHAR8 *String,
>
> + IN CHAR8 *CharSet
>
> + )
>
> +{
>
> + UINTN Count;
>
> + CHAR8 *Str1;
>
> + CHAR8 *Str2;
>
> +
>
> + Count = 0;
>
> +
>
> + for (Str1 = String; *Str1 != L'\0'; Str1++) {
>
> + for (Str2 = CharSet; *Str2 != L'\0'; Str2++) {
>
> + if (*Str1 == *Str2) {
>
> + break;
>
> + }
>
> + }
>
> +
>
> + if (*Str2 == L'\0') {
>
> + return Count;
>
> + }
>
> +
>
> + Count++;
>
> + }
>
> +
>
> + return Count;
>
> +}
>
> +
>
> +/**
>
> + Searches a string for the first occurrence of a character contained in a
>
> + specified buffer.
>
> + @param String Point to the string where to find the substring.
>
> + @param CharSet Point to the string to be found.
>
> +**/
>
> +CHAR8 *
>
> +EFIAPI
>
> +AsciiStrBrk (
>
> + IN CHAR8 *String,
>
> + IN CHAR8 *CharSet
>
> + )
>
> +{
>
> + CHAR8 *Str1;
>
> + CHAR8 *Str2;
>
> +
>
> + for (Str1 = String; *Str1 != L'\0'; Str1++) {
>
> + for (Str2 = CharSet; *Str2 != L'\0'; Str2++) {
>
> + if (*Str1 == *Str2) {
>
> + return (CHAR8 *)Str1;
>
> + }
>
> + }
>
> + }
>
> +
>
> + return NULL;
>
> +}
>
> +
>
> +/**
>
> + Find the next token after one or more specified characters.
>
> + @param String Point to the string where to find the substring.
>
> + @param CharSet Point to the string to be found.
>
> +**/
>
> +CHAR8 *
>
> +EFIAPI
>
> +AsciiStrTokenLine (
>
> + IN CHAR8 *String OPTIONAL,
>
> + IN CHAR8 *CharSet
>
> + )
>
> +{
>
> + CHAR8 *Begin;
>
> + CHAR8 *End;
>
> +
>
> + Begin = (String == NULL) ? mLineBuffer : String;
>
> + if (Begin == NULL) {
>
> + return NULL;
>
> + }
>
> +
>
> + Begin += AsciiStrSpn (Begin, CharSet);
>
> + if (*Begin == L'\0') {
>
> + mLineBuffer = NULL;
>
> + return NULL;
>
> + }
>
> +
>
> + End = AsciiStrBrk (Begin, CharSet);
>
> + if ((End != NULL) && (*End != L'\0')) {
>
> + *End = L'\0';
>
> + End++;
>
> + }
>
> +
>
> + mLineBuffer = End;
>
> + return Begin;
>
> +}
>
> +
>
> +/**
>
> + Some bootloader may pass a pcd database, and UPL also contain a PCD
> database.
>
> + Dxe PCD driver has the assumption that the two PCD database can be
> catenated and
>
> + the local token number should be successive.
>
> + This function will fix up the UPL PCD database to meet that assumption.
>
> + @param[in] DxeFv The FV where to find the Universal PCD
> database.
>
> + @retval EFI_SUCCESS If it completed successfully.
>
> + @retval other Failed to fix up.
>
> +**/
>
> +EFI_STATUS
>
> +FixUpPcdDatabase (
>
> + IN EFI_FIRMWARE_VOLUME_HEADER *DxeFv
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + EFI_FFS_FILE_HEADER *FileHeader;
>
> + VOID *PcdRawData;
>
> + PEI_PCD_DATABASE *PeiDatabase;
>
> + PEI_PCD_DATABASE *UplDatabase;
>
> + EFI_HOB_GUID_TYPE *GuidHob;
>
> + DYNAMICEX_MAPPING *ExMapTable;
>
> + UINTN Index;
>
> +
>
> + GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);
>
> + if (GuidHob == NULL) {
>
> + //
>
> + // No fix-up is needed.
>
> + //
>
> + return EFI_SUCCESS;
>
> + }
>
> +
>
> + PeiDatabase = (PEI_PCD_DATABASE *)GET_GUID_HOB_DATA (GuidHob);
>
> + DEBUG ((DEBUG_INFO, "Find the Pei PCD data base, the total local token
> number is %d\n", PeiDatabase->LocalTokenCount));
>
> +
>
> + Status = FvFindFileByTypeGuid (DxeFv, EFI_FV_FILETYPE_DRIVER, PcdGetPtr
> (PcdPcdDriverFile), &FileHeader);
>
> + ASSERT_EFI_ERROR (Status);
>
> + if (EFI_ERROR (Status)) {
>
> + return Status;
>
> + }
>
> +
>
> + Status = FileFindSection (FileHeader, EFI_SECTION_RAW, &PcdRawData);
>
> + ASSERT_EFI_ERROR (Status);
>
> + if (EFI_ERROR (Status)) {
>
> + return Status;
>
> + }
>
> +
>
> + UplDatabase = (PEI_PCD_DATABASE *)PcdRawData;
>
> + ExMapTable = (DYNAMICEX_MAPPING *)(UINTN)((UINTN)PcdRawData +
> UplDatabase->ExMapTableOffset);
>
> +
>
> + for (Index = 0; Index < UplDatabase->ExTokenCount; Index++) {
>
> + ExMapTable[Index].TokenNumber += PeiDatabase->LocalTokenCount;
>
> + }
>
> +
>
> + DEBUG ((DEBUG_INFO, "Fix up UPL PCD database successfully\n"));
>
> + return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> + Add HOB into HOB list
>
> + @param[in] Hob The HOB to be added into the HOB list.
>
> +**/
>
> +VOID
>
> +AddNewHob (
>
> + IN EFI_PEI_HOB_POINTERS *Hob
>
> + )
>
> +{
>
> + EFI_PEI_HOB_POINTERS NewHob;
>
> +
>
> + if (Hob->Raw == NULL) {
>
> + return;
>
> + }
>
> +
>
> + NewHob.Header = CreateHob (Hob->Header->HobType,
> Hob->Header->HobLength);
>
> +
>
> + if (NewHob.Header != NULL) {
>
> + CopyMem (NewHob.Header + 1, Hob->Header + 1, Hob->Header->HobLength -
> sizeof (EFI_HOB_GENERIC_HEADER));
>
> + }
>
> +}
>
> +
>
> +/**
>
> + Found the Resource Descriptor HOB that contains a range (Base, Top)
>
> + @param[in] HobList Hob start address
>
> + @param[in] Base Memory start address
>
> + @param[in] Top Memory end address.
>
> + @retval The pointer to the Resource Descriptor HOB.
>
> +**/
>
> +EFI_HOB_RESOURCE_DESCRIPTOR *
>
> +FindResourceDescriptorByRange (
>
> + IN VOID *HobList,
>
> + IN EFI_PHYSICAL_ADDRESS Base,
>
> + IN EFI_PHYSICAL_ADDRESS Top
>
> + )
>
> +{
>
> + EFI_PEI_HOB_POINTERS Hob;
>
> + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
>
> +
>
> + for (Hob.Raw = (UINT8 *)HobList; !END_OF_HOB_LIST (Hob); Hob.Raw =
> GET_NEXT_HOB (Hob)) {
>
> + //
>
> + // Skip all HOBs except Resource Descriptor HOBs
>
> + //
>
> + if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
>
> + continue;
>
> + }
>
> +
>
> + //
>
> + // Skip Resource Descriptor HOBs that do not describe tested system
> memory
>
> + //
>
> + ResourceHob = Hob.ResourceDescriptor;
>
> + if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
>
> + continue;
>
> + }
>
> +
>
> + if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) !=
> TESTED_MEMORY_ATTRIBUTES) {
>
> + continue;
>
> + }
>
> +
>
> + //
>
> + // Skip Resource Descriptor HOBs that do not contain the PHIT range
> EfiFreeMemoryBottom..EfiFreeMemoryTop
>
> + //
>
> + if (Base < ResourceHob->PhysicalStart) {
>
> + continue;
>
> + }
>
> +
>
> + if (Top > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength))
> {
>
> + continue;
>
> + }
>
> +
>
> + return ResourceHob;
>
> + }
>
> +
>
> + return NULL;
>
> +}
>
> +
>
> +/**
>
> + Find the highest below 4G memory resource descriptor, except the input
> Resource Descriptor.
>
> + @param[in] HobList Hob start address
>
> + @param[in] MinimalNeededSize Minimal needed size.
>
> + @param[in] ExceptResourceHob Ignore this Resource Descriptor.
>
> + @retval The pointer to the Resource Descriptor HOB.
>
> +**/
>
> +EFI_HOB_RESOURCE_DESCRIPTOR *
>
> +FindAnotherHighestBelow4GResourceDescriptor (
>
> + IN VOID *HobList,
>
> + IN UINTN MinimalNeededSize,
>
> + IN EFI_HOB_RESOURCE_DESCRIPTOR *ExceptResourceHob
>
> + )
>
> +{
>
> + EFI_PEI_HOB_POINTERS Hob;
>
> + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
>
> + EFI_HOB_RESOURCE_DESCRIPTOR *ReturnResourceHob;
>
> +
>
> + ReturnResourceHob = NULL;
>
> +
>
> + for (Hob.Raw = (UINT8 *)HobList; !END_OF_HOB_LIST (Hob); Hob.Raw =
> GET_NEXT_HOB (Hob)) {
>
> + //
>
> + // Skip all HOBs except Resource Descriptor HOBs
>
> + //
>
> + if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
>
> + continue;
>
> + }
>
> +
>
> + //
>
> + // Skip Resource Descriptor HOBs that do not describe tested system
> memory
>
> + //
>
> + ResourceHob = Hob.ResourceDescriptor;
>
> + if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
>
> + continue;
>
> + }
>
> +
>
> + if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) !=
> TESTED_MEMORY_ATTRIBUTES) {
>
> + continue;
>
> + }
>
> +
>
> + //
>
> + // Skip if the Resource Descriptor HOB equals to ExceptResourceHob
>
> + //
>
> + if (ResourceHob == ExceptResourceHob) {
>
> + continue;
>
> + }
>
> +
>
> + //
>
> + // Skip Resource Descriptor HOBs that are beyond 4G
>
> + //
>
> + if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) >
> BASE_4GB) {
>
> + continue;
>
> + }
>
> +
>
> + //
>
> + // Skip Resource Descriptor HOBs that are too small
>
> + //
>
> + if (ResourceHob->ResourceLength < MinimalNeededSize) {
>
> + continue;
>
> + }
>
> +
>
> + //
>
> + // Return the topest Resource Descriptor
>
> + //
>
> + if (ReturnResourceHob == NULL) {
>
> + ReturnResourceHob = ResourceHob;
>
> + } else {
>
> + if (ReturnResourceHob->PhysicalStart < ResourceHob->PhysicalStart) {
>
> + ReturnResourceHob = ResourceHob;
>
> + }
>
> + }
>
> + }
>
> +
>
> + return ReturnResourceHob;
>
> +}
>
> +
>
> +/**
>
> + Check the HOB and decide if it is need inside Payload
>
> + Payload maintainer may make decision which HOB is need or needn't
>
> + Then add the check logic in the function.
>
> + @param[in] Hob The HOB to check
>
> + @retval TRUE If HOB is need inside Payload
>
> + @retval FALSE If HOB is needn't inside Payload
>
> +**/
>
> +BOOLEAN
>
> +IsHobNeed (
>
> + EFI_PEI_HOB_POINTERS Hob
>
> + )
>
> +{
>
> + if (Hob.Header->HobType == EFI_HOB_TYPE_HANDOFF) {
>
> + return FALSE;
>
> + }
>
> +
>
> + if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
>
> + if (CompareGuid
> (&Hob.MemoryAllocationModule->MemoryAllocationHeader.Name,
> &gEfiHobMemoryAllocModuleGuid)) {
>
> + return FALSE;
>
> + }
>
> + }
>
> +
>
> + // Arrive here mean the HOB is need
>
> + return TRUE;
>
> +}
>
> +
>
> +/**
>
> + It will build Fv HOBs based on information from bootloaders.
>
> + @param[out] DxeFv The pointer to the DXE FV in memory.
>
> + @retval EFI_SUCCESS If it completed successfully.
>
> + @retval EFI_NOT_FOUND If it failed to find node in fit image.
>
> + @retval Others If it failed to build required HOBs.
>
> +**/
>
> +EFI_STATUS
>
> +BuildFitLoadablesFvHob (
>
> + OUT EFI_FIRMWARE_VOLUME_HEADER **DxeFv
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + VOID *Fdt;
>
> + UINT8 *GuidHob;
>
> + UNIVERSAL_PAYLOAD_BASE *PayloadBase;
>
> + INT32 ConfigNode;
>
> + INT32 Config1Node;
>
> + INT32 ImageNode;
>
> + INT32 FvNode;
>
> + INT32 Depth;
>
> + CONST FDT_PROPERTY *PropertyPtr;
>
> + INT32 TempLen;
>
> + CONST CHAR8 *Fvname;
>
> + UINT32 DataOffset;
>
> + UINT32 DataSize;
>
> + UINT32 *Data32;
>
> +
>
> + GuidHob = GetFirstGuidHob (&gUniversalPayloadBaseGuid);
>
> + if (GuidHob != NULL) {
>
> + PayloadBase = (UNIVERSAL_PAYLOAD_BASE *)GET_GUID_HOB_DATA (GuidHob);
>
> + Fdt = (VOID *)(UINTN)PayloadBase->Entry;
>
> + DEBUG ((DEBUG_INFO, "PayloadBase Entry = 0x%08x\n",
> PayloadBase->Entry));
>
> + }
>
> +
>
> + Status = FdtCheckHeader (Fdt);
>
> + if (EFI_ERROR (Status)) {
>
> + return EFI_UNSUPPORTED;
>
> + }
>
> +
>
> + ConfigNode = FdtSubnodeOffsetNameLen (Fdt, 0, "configurations",
> (INT32)AsciiStrLen ("configurations"));
>
> + if (ConfigNode <= 0) {
>
> + return EFI_NOT_FOUND;
>
> + }
>
> +
>
> + Config1Node = FdtSubnodeOffsetNameLen (Fdt, ConfigNode, "conf-1",
> (INT32)AsciiStrLen ("conf-1"));
>
> + if (Config1Node <= 0) {
>
> + return EFI_NOT_FOUND;
>
> + }
>
> +
>
> + ImageNode = FdtSubnodeOffsetNameLen (Fdt, 0, "images",
> (INT32)AsciiStrLen ("images"));
>
> + if (ImageNode <= 0) {
>
> + return EFI_NOT_FOUND;
>
> + }
>
> +
>
> + FvNode = FdtSubnodeOffsetNameLen (Fdt, ImageNode, "tianocore",
> (INT32)AsciiStrLen ("tianocore"));
>
> + Depth = FdtNodeDepth (Fdt, FvNode);
>
> + FvNode = FdtNextNode (Fdt, FvNode, &Depth);
>
> + Fvname = FdtGetName (Fdt, FvNode, &TempLen);
>
> + while ((AsciiStrCmp ((Fvname + AsciiStrLen (Fvname) - 2), "fv") == 0)) {
>
> + if (FvNode <= 0) {
>
> + return EFI_NOT_FOUND;
>
> + }
>
> +
>
> + PropertyPtr = FdtGetProperty (Fdt, FvNode, "data-offset", &TempLen);
>
> + Data32 = (UINT32 *)(PropertyPtr->Data);
>
> + DataOffset = SwapBytes32 (*Data32);
>
> +
>
> + PropertyPtr = FdtGetProperty (Fdt, FvNode, "data-size", &TempLen);
>
> + Data32 = (UINT32 *)(PropertyPtr->Data);
>
> + DataSize = SwapBytes32 (*Data32);
>
> +
>
> + if (AsciiStrCmp (Fvname, "uefi-fv") == 0) {
>
> + *DxeFv = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)PayloadBase->Entry +
> (UINTN)DataOffset);
>
> + ASSERT ((*DxeFv)->FvLength == DataSize);
>
> + } else {
>
> + BuildFvHob (((UINTN)PayloadBase->Entry + (UINTN)DataOffset),
> DataSize);
>
> + }
>
> +
>
> + DEBUG ((
>
> + DEBUG_INFO,
>
> + "UPL Multiple fv[%a], Base=0x%08x, size=0x%08x\n",
>
> + Fvname,
>
> + ((UINTN)PayloadBase->Entry + (UINTN)DataOffset),
>
> + DataSize,
>
> + DataOffset
>
> + ));
>
> + Depth = FdtNodeDepth (Fdt, FvNode);
>
> + FvNode = FdtNextNode (Fdt, FvNode, &Depth);
>
> + Fvname = FdtGetName (Fdt, FvNode, &TempLen);
>
> + }
>
> +
>
> + return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> + It will build HOBs based on information from bootloaders.
>
> + @param[in] BootloaderParameter The starting memory address of
> bootloader parameter block.
>
> + @param[out] DxeFv The pointer to the DXE FV in memory.
>
> + @retval EFI_SUCCESS If it completed successfully.
>
> + @retval Others If it failed to build required HOBs.
>
> +**/
>
> +EFI_STATUS
>
> +BuildHobs (
>
> + IN UINTN BootloaderParameter,
>
> + OUT EFI_FIRMWARE_VOLUME_HEADER **DxeFv
>
> + )
>
> +{
>
> + EFI_PEI_HOB_POINTERS Hob;
>
> + UINTN MinimalNeededSize;
>
> + EFI_PHYSICAL_ADDRESS FreeMemoryBottom;
>
> + EFI_PHYSICAL_ADDRESS FreeMemoryTop;
>
> + EFI_PHYSICAL_ADDRESS MemoryBottom;
>
> + EFI_PHYSICAL_ADDRESS MemoryTop;
>
> + EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob;
>
> + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
>
> + UINT8 *GuidHob;
>
> + EFI_HOB_FIRMWARE_VOLUME *FvHob;
>
> + UNIVERSAL_PAYLOAD_ACPI_TABLE *AcpiTable;
>
> + ACPI_BOARD_INFO *AcpiBoardInfo;
>
> + EFI_HOB_HANDOFF_INFO_TABLE *HobInfo;
>
> +
>
> + Hob.Raw = (UINT8 *)BootloaderParameter;
>
> + MinimalNeededSize = FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
>
> +
>
> + ASSERT (Hob.Raw != NULL);
>
> + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryTop ==
> Hob.HandoffInformationTable->EfiFreeMemoryTop);
>
> + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryTop ==
> Hob.HandoffInformationTable->EfiMemoryTop);
>
> + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryBottom ==
> Hob.HandoffInformationTable->EfiFreeMemoryBottom);
>
> + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryBottom ==
> Hob.HandoffInformationTable->EfiMemoryBottom);
>
> +
>
> + //
>
> + // Try to find Resource Descriptor HOB that contains Hob range
> EfiMemoryBottom..EfiMemoryTop
>
> + //
>
> + PhitResourceHob = FindResourceDescriptorByRange (Hob.Raw,
> Hob.HandoffInformationTable->EfiMemoryBottom,
> Hob.HandoffInformationTable->EfiMemoryTop);
>
> + if (PhitResourceHob == NULL) {
>
> + //
>
> + // Boot loader's Phit Hob is not in an available Resource Descriptor,
> find another Resource Descriptor for new Phit Hob
>
> + //
>
> + ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw,
> MinimalNeededSize, NULL);
>
> + if (ResourceHob == NULL) {
>
> + return EFI_NOT_FOUND;
>
> + }
>
> +
>
> + MemoryBottom = ResourceHob->PhysicalStart +
> ResourceHob->ResourceLength - MinimalNeededSize;
>
> + FreeMemoryBottom = MemoryBottom;
>
> + FreeMemoryTop = ResourceHob->PhysicalStart +
> ResourceHob->ResourceLength;
>
> + MemoryTop = FreeMemoryTop;
>
> + } else if (PhitResourceHob->PhysicalStart +
> PhitResourceHob->ResourceLength - Hob.HandoffInformationTable->EfiMemoryTop
> >= MinimalNeededSize) {
>
> + //
>
> + // New availiable Memory range in new hob is right above memory top
> in old hob.
>
> + //
>
> + MemoryBottom = Hob.HandoffInformationTable->EfiFreeMemoryTop;
>
> + FreeMemoryBottom = Hob.HandoffInformationTable->EfiMemoryTop;
>
> + FreeMemoryTop = FreeMemoryBottom + MinimalNeededSize;
>
> + MemoryTop = FreeMemoryTop;
>
> + } else if (Hob.HandoffInformationTable->EfiMemoryBottom -
> PhitResourceHob->PhysicalStart >= MinimalNeededSize) {
>
> + //
>
> + // New availiable Memory range in new hob is right below memory
> bottom in old hob.
>
> + //
>
> + MemoryBottom = Hob.HandoffInformationTable->EfiMemoryBottom -
> MinimalNeededSize;
>
> + FreeMemoryBottom = MemoryBottom;
>
> + FreeMemoryTop = Hob.HandoffInformationTable->EfiMemoryBottom;
>
> + MemoryTop = Hob.HandoffInformationTable->EfiMemoryTop;
>
> + } else {
>
> + //
>
> + // In the Resource Descriptor HOB contains boot loader Hob, there is
> no enough free memory size for payload hob
>
> + // Find another Resource Descriptor Hob
>
> + //
>
> + ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw,
> MinimalNeededSize, PhitResourceHob);
>
> + if (ResourceHob == NULL) {
>
> + return EFI_NOT_FOUND;
>
> + }
>
> +
>
> + MemoryBottom = ResourceHob->PhysicalStart +
> ResourceHob->ResourceLength - MinimalNeededSize;
>
> + FreeMemoryBottom = MemoryBottom;
>
> + FreeMemoryTop = ResourceHob->PhysicalStart +
> ResourceHob->ResourceLength;
>
> + MemoryTop = FreeMemoryTop;
>
> + }
>
> +
>
> + HobInfo = HobConstructor ((VOID *)(UINTN)MemoryBottom, (VOID
> *)(UINTN)MemoryTop, (VOID *)(UINTN)FreeMemoryBottom, (VOID
> *)(UINTN)FreeMemoryTop);
>
> + HobInfo->BootMode = Hob.HandoffInformationTable->BootMode;
>
> + //
>
> + // From now on, mHobList will point to the new Hob range.
>
> + //
>
> +
>
> + //
>
> + // Create an empty FvHob for the DXE FV that contains DXE core.
>
> + //
>
> + BuildFvHob ((EFI_PHYSICAL_ADDRESS)0, 0);
>
> + //
>
> + // Since payload created new Hob, move all hobs except PHIT from boot
> loader hob list.
>
> + //
>
> + while (!END_OF_HOB_LIST (Hob)) {
>
> + if (IsHobNeed (Hob)) {
>
> + // Add this hob to payload HOB
>
> + AddNewHob (&Hob);
>
> + }
>
> +
>
> + Hob.Raw = GET_NEXT_HOB (Hob);
>
> + }
>
> +
>
> + BuildFitLoadablesFvHob (DxeFv);
>
> +
>
> + //
>
> + // Create guid hob for acpi board information
>
> + //
>
> + GuidHob = GetFirstGuidHob (&gUniversalPayloadAcpiTableGuid);
>
> + if (GuidHob != NULL) {
>
> + AcpiTable = (UNIVERSAL_PAYLOAD_ACPI_TABLE *)GET_GUID_HOB_DATA
> (GuidHob);
>
> + GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid);
>
> + if (GuidHob == NULL) {
>
> + AcpiBoardInfo = BuildHobFromAcpi ((UINT64)AcpiTable->Rsdp);
>
> + ASSERT (AcpiBoardInfo != NULL);
>
> + }
>
> + }
>
> +
>
> + //
>
> + // Update DXE FV information to first fv hob in the hob list, which
>
> + // is the empty FvHob created before.
>
> + //
>
> + FvHob = GetFirstHob (EFI_HOB_TYPE_FV);
>
> + FvHob->BaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)*DxeFv;
>
> + FvHob->Length = (*DxeFv)->FvLength;
>
> + return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> + Entry point to the C language phase of UEFI payload.
>
> + @param[in] BootloaderParameter The starting address of bootloader
> parameter block.
>
> + @retval It will not return if SUCCESS, and return error when
> passing bootloader parameter.
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +_ModuleEntryPoint (
>
> + IN UINTN BootloaderParameter
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + PHYSICAL_ADDRESS DxeCoreEntryPoint;
>
> + EFI_PEI_HOB_POINTERS Hob;
>
> + EFI_FIRMWARE_VOLUME_HEADER *DxeFv;
>
> +
>
> + mHobList = (VOID *)BootloaderParameter;
>
> + DxeFv = NULL;
>
> + // Call constructor for all libraries
>
> + ProcessLibraryConstructorList ();
>
> +
>
> + DEBUG ((DEBUG_INFO, "Entering Universal Payload...\n"));
>
> + DEBUG ((DEBUG_INFO, "sizeof(UINTN) = 0x%x\n", sizeof (UINTN)));
>
> +
>
> + DEBUG_CODE (
>
> + //
>
> + // Dump the Hobs from boot loader
>
> + //
>
> + PrintHob (mHobList);
>
> + );
>
> +
>
> + // Initialize floating point operating environment to be compliant with
> UEFI spec.
>
> + InitializeFloatingPointUnits ();
>
> +
>
> + // Build HOB based on information from Bootloader
>
> + Status = BuildHobs (BootloaderParameter, &DxeFv);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + FixUpPcdDatabase (DxeFv);
>
> + Status = UniversalLoadDxeCore (DxeFv, &DxeCoreEntryPoint);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + //
>
> + // Mask off all legacy 8259 interrupt sources
>
> + //
>
> + IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF);
>
> + IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF);
>
> +
>
> + Hob.HandoffInformationTable = (EFI_HOB_HANDOFF_INFO_TABLE *)GetFirstHob
> (EFI_HOB_TYPE_HANDOFF);
>
> + HandOffToDxeCore (DxeCoreEntryPoint, Hob);
>
> +
>
> + // Should not get here
>
> + CpuDeadLoop ();
>
> + return EFI_SUCCESS;
>
> +}
>
> diff --git a/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
> b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
> new file mode 100644
> index 0000000000..a7d1a8c9e5
> --- /dev/null
> +++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
> @@ -0,0 +1,98 @@
> +## @file
>
> +# This is the first module for UEFI payload.
>
> +#
>
> +# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
>
> +#
>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +#
>
> +##
>
> +
>
> +[Defines]
>
> + INF_VERSION = 0x00010005
>
> + BASE_NAME = FitUniversalPayloadEntry
>
> + FILE_GUID = CED5A8A9-B6EA-4D5A-8689-577EE88566CF
>
> + MODULE_TYPE = SEC
>
> + VERSION_STRING = 1.0
>
> +
>
> +#
>
> +# The following information is for reference only and not required by the
> build tools.
>
> +#
>
> +# VALID_ARCHITECTURES = IA32 X64
>
> +#
>
> +
>
> +[Sources]
>
> + FitUniversalPayloadEntry.c
>
> + LoadDxeCore.c
>
> + MemoryAllocation.c
>
> + PrintHob.c
>
> + AcpiTable.c
>
> +
>
> +[Sources.Ia32]
>
> + X64/VirtualMemory.h
>
> + X64/VirtualMemory.c
>
> + Ia32/DxeLoadFunc.c
>
> + Ia32/IdtVectorAsm.nasm
>
> +
>
> +[Sources.X64]
>
> + X64/VirtualMemory.h
>
> + X64/VirtualMemory.c
>
> + X64/DxeLoadFunc.c
>
> +
>
> +[Packages]
>
> + MdePkg/MdePkg.dec
>
> + MdeModulePkg/MdeModulePkg.dec
>
> + UefiCpuPkg/UefiCpuPkg.dec
>
> + UefiPayloadPkg/UefiPayloadPkg.dec
>
> +
>
> +[LibraryClasses]
>
> + BaseMemoryLib
>
> + DebugLib
>
> + BaseLib
>
> + SerialPortLib
>
> + IoLib
>
> + HobLib
>
> + PeCoffLib
>
> + CpuLib
>
> + FdtLib
>
> +
>
> +[Guids]
>
> + gEfiMemoryTypeInformationGuid
>
> + gEfiFirmwareFileSystem2Guid
>
> + gEfiGraphicsInfoHobGuid
>
> + gEfiGraphicsDeviceInfoHobGuid
>
> + gUefiAcpiBoardInfoGuid
>
> + gEfiSmbiosTableGuid
>
> + gUefiSerialPortInfoGuid
>
> + gUniversalPayloadExtraDataGuid
>
> + gUniversalPayloadBaseGuid
>
> + gPcdDataBaseHobGuid
>
> + gUniversalPayloadSmbiosTableGuid
>
> + gEfiHobMemoryAllocBspStoreGuid
>
> + gUniversalPayloadAcpiTableGuid
>
> + gUniversalPayloadPciRootBridgeInfoGuid
>
> + gUniversalPayloadSmbios3TableGuid
>
> +
>
> +[FeaturePcd.IA32]
>
> + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ##
> CONSUMES
>
> +
>
> +[FeaturePcd.X64]
>
> + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables ##
> CONSUMES
>
> +
>
> +
>
> +[Pcd.IA32,Pcd.X64]
>
> + gUefiPayloadPkgTokenSpaceGuid.PcdPcdDriverFile
>
> + gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable
> ## SOMETIMES_CONSUMES
>
> + gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask
> ## CONSUMES
>
> + gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
> ## CONSUMES
>
> + gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask
> ## CONSUMES
>
> + gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard
> ## CONSUMES
>
> + gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase
> ## CONSUMES
>
> + gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize
> ## CONSUMES
>
> +
>
> + gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase
>
> + gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize
>
> + gUefiPayloadPkgTokenSpaceGuid.PcdSystemMemoryUefiRegionSize
>
> +
>
> + gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ##
> SOMETIMES_CONSUMES
>
> + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy ##
> SOMETIMES_CONSUMES
>
> + gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy ##
> SOMETIMES_CONSUMES
>
> diff --git a/UefiPayloadPkg/UefiPayloadPkg.dec
> b/UefiPayloadPkg/UefiPayloadPkg.dec
> index e2e4a79db3..2f1fd82487 100644
> --- a/UefiPayloadPkg/UefiPayloadPkg.dec
> +++ b/UefiPayloadPkg/UefiPayloadPkg.dec
> @@ -24,6 +24,9 @@
> #
>
> gUefiPayloadPkgTokenSpaceGuid = {0x1d127ea, 0xf6f1, 0x4ef6, {0x94,
> 0x15, 0x8a, 0x0, 0x0, 0x93, 0xf8, 0x9d}}
>
>
>
> + ## Include/Guid/UniversalPayloadBase.h
>
> + gUniversalPayloadBaseGuid = { 0x03d4c61d, 0x2713, 0x4ec5, {0xa1, 0xcc,
> 0x88, 0x3b, 0xe9, 0xdc, 0x18, 0xe5 } }
>
> +
>
> #
>
> # Gop Temp
>
> #
>
> diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc
> b/UefiPayloadPkg/UefiPayloadPkg.dsc
> index 47812048dd..af9308ef8e 100644
> --- a/UefiPayloadPkg/UefiPayloadPkg.dsc
> +++ b/UefiPayloadPkg/UefiPayloadPkg.dsc
> @@ -30,7 +30,6 @@
> DEFINE PS2_KEYBOARD_ENABLE = FALSE
>
> DEFINE RAM_DISK_ENABLE = FALSE
>
> DEFINE SIO_BUS_ENABLE = FALSE
>
> - DEFINE UNIVERSAL_PAYLOAD = FALSE
>
> DEFINE SECURITY_STUB_ENABLE = TRUE
>
> DEFINE SMM_SUPPORT = FALSE
>
> DEFINE PLATFORM_BOOT_TIMEOUT = 3
>
> @@ -44,6 +43,14 @@
> DEFINE BOOTSPLASH_IMAGE = FALSE
>
> DEFINE NVME_ENABLE = TRUE
>
> DEFINE CAPSULE_SUPPORT = FALSE
>
> + #
>
> + # Setup Universal Payload
>
> + #
>
> + # ELF: Build UniversalPayload file as UniversalPayload.elf
>
> + # FIT: Build UniversalPayload file as UniversalPayload.fit
>
> + #
>
> + DEFINE UNIVERSAL_PAYLOAD = FALSE
>
> + DEFINE UNIVERSAL_PAYLOAD_FORMAT = ELF
>
>
>
> #
>
> # NULL: NullMemoryTestDxe
>
> @@ -311,7 +318,7 @@
>
> VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf
>
> CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
>
>
> ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
>
> -
>
> + FdtLib|MdePkg/Library/BaseFdtLib/BaseFdtLib.inf
>
> [LibraryClasses.common]
>
> !if $(BOOTSPLASH_IMAGE)
>
> SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
>
> @@ -600,14 +607,26 @@
> !if "IA32" in "$(ARCH)"
>
> [Components.IA32]
>
> !if $(UNIVERSAL_PAYLOAD) == TRUE
>
> - UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
>
> + !if $(UNIVERSAL_PAYLOAD_FORMAT) == "ELF"
>
> + UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
>
> + !elseif $(UNIVERSAL_PAYLOAD_FORMAT) == "FIT"
>
> + UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
>
> + !else
>
> + UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
>
> + !endif
>
> !else
>
> UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
>
> !endif
>
> !else
>
> [Components.X64]
>
> !if $(UNIVERSAL_PAYLOAD) == TRUE
>
> - UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
>
> + !if $(UNIVERSAL_PAYLOAD_FORMAT) == "ELF"
>
> + UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
>
> + !elseif $(UNIVERSAL_PAYLOAD_FORMAT) == "FIT"
>
> + UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
>
> + !else
>
> + UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
>
> + !endif
>
> !else
>
> UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
>
> !endif
>
> diff --git a/UefiPayloadPkg/UniversalPayloadBuild.py
> b/UefiPayloadPkg/UniversalPayloadBuild.py
> index 47f37b3377..9a83fc9e44 100644
> --- a/UefiPayloadPkg/UniversalPayloadBuild.py
> +++ b/UefiPayloadPkg/UniversalPayloadBuild.py
> @@ -10,10 +10,22 @@ import subprocess
> import os
>
> import shutil
>
> import sys
>
> +import pathlib
>
> from ctypes import *
>
> -from Tools.ElfFv import ReplaceFv
>
> +
>
> sys.dont_write_bytecode = True
>
>
>
> +class bcolors:
>
> + HEADER = '\033[95m'
>
> + OKBLUE = '\033[94m'
>
> + OKCYAN = '\033[96m'
>
> + OKGREEN = '\033[92m'
>
> + WARNING = '\033[93m'
>
> + FAIL = '\033[91m'
>
> + ENDC = '\033[0m'
>
> + BOLD = '\033[1m'
>
> + UNDERLINE = '\033[4m'
>
> +
>
> class UPLD_INFO_HEADER(LittleEndianStructure):
>
> _pack_ = 1
>
> _fields_ = [
>
> @@ -36,40 +48,114 @@ class UPLD_INFO_HEADER(LittleEndianStructure):
> self.ImageId = b'UEFI'
>
> self.ProducerId = b'INTEL'
>
>
>
> -def BuildUniversalPayload(Args):
>
> - def RunCommand(cmd):
>
> - print(cmd)
>
> - p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
> stderr=subprocess.STDOUT,cwd=os.environ['WORKSPACE'])
>
> - while True:
>
> - line = p.stdout.readline()
>
> - if not line:
>
> - break
>
> - print(line.strip().decode(errors='ignore'))
>
> -
>
> - p.communicate()
>
> - if p.returncode != 0:
>
> - print("- Failed - error happened when run command: %s"%cmd)
>
> - raise Exception("ERROR: when run command: %s"%cmd)
>
> +def ValidateSpecRevision (Argument):
>
> + try:
>
> + (MajorStr, MinorStr) = Argument.split('.')
>
> + except:
>
> + raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision
> format (Major[8-bits].Minor[8-bits]).'.format (Argument))
>
> + #
>
> + # Spec Revision Bits 15 : 8 - Major Version. Bits 7 : 0 - Minor
> Version.
>
> + #
>
> + if len(MinorStr) > 0 and len(MinorStr) < 3:
>
> + try:
>
> + Minor = int(MinorStr, 16) if len(MinorStr) == 2 else
> (int(MinorStr, 16) << 4)
>
> + except:
>
> + raise argparse.ArgumentTypeError ('{} Minor version of
> SpecRevision is not a valid integer value.'.format (Argument))
>
> + else:
>
> + raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision
> format (Major[8-bits].Minor[8-bits]).'.format (Argument))
>
> +
>
> + if len(MajorStr) > 0 and len(MajorStr) < 3:
>
> + try:
>
> + Major = int(MajorStr, 16)
>
> + except:
>
> + raise argparse.ArgumentTypeError ('{} Major version of
> SpecRevision is not a valid integer value.'.format (Argument))
>
> + else:
>
> + raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision
> format (Major[8-bits].Minor[8-bits]).'.format (Argument))
>
> +
>
> + return int('0x{0:02x}{1:02x}'.format(Major, Minor), 0)
>
> +
>
> +def Validate32BitInteger (Argument):
>
> + try:
>
> + Value = int (Argument, 0)
>
> + except:
>
> + raise argparse.ArgumentTypeError ('{} is not a valid integer
> value.'.format (Argument))
>
> + if Value < 0:
>
> + raise argparse.ArgumentTypeError ('{} is a negative
> value.'.format (Argument))
>
> + if Value > 0xffffffff:
>
> + raise argparse.ArgumentTypeError ('{} is larger than
> 32-bits.'.format (Argument))
>
> + return Value
>
>
>
> +def ValidateAddFv (Argument):
>
> + Value = Argument.split ("=")
>
> + if len (Value) != 2:
>
> + raise argparse.ArgumentTypeError ('{} is incorrect format with
> "xxx_fv=xxx.fv"'.format (Argument))
>
> + if Value[0][-3:] != "_fv":
>
> + raise argparse.ArgumentTypeError ('{} is incorrect format with
> "xxx_fv=xxx.fv"'.format (Argument))
>
> + if Value[1][-3:].lower () != ".fv":
>
> + raise argparse.ArgumentTypeError ('{} is incorrect format with
> "xxx_fv=xxx.fv"'.format (Argument))
>
> + if os.path.exists (Value[1]) == False:
>
> + raise argparse.ArgumentTypeError ('File {} is not found.'.format
> (Value[1]))
>
> + return Value
>
> +
>
> +def RunCommand(cmd):
>
> + print(cmd)
>
> + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
> stderr=subprocess.STDOUT,cwd=os.environ['WORKSPACE'])
>
> + while True:
>
> + line = p.stdout.readline()
>
> + if not line:
>
> + break
>
> + print(line.strip().decode(errors='ignore'))
>
> +
>
> + p.communicate()
>
> + if p.returncode != 0:
>
> + print("- Failed - error happened when run command: %s"%cmd)
>
> + raise Exception("ERROR: when run command: %s"%cmd)
>
> +
>
> +def BuildUniversalPayload(Args):
>
> BuildTarget = Args.Target
>
> ToolChain = Args.ToolChain
>
> Quiet = "--quiet" if Args.Quiet else ""
>
> - ElfToolChain = 'CLANGDWARF'
>
> - BuildDir = os.path.join(os.environ['WORKSPACE'],
> os.path.normpath("Build/UefiPayloadPkgX64"))
>
> - BuildModule = ""
>
> - BuildArch = ""
>
>
>
> + if Args.Fit == True:
>
> + PayloadEntryToolChain = ToolChain
>
> + Args.Macro.append("UNIVERSAL_PAYLOAD_FORMAT=FIT")
>
> + UpldEntryFile = "FitUniversalPayloadEntry"
>
> + else:
>
> + PayloadEntryToolChain = 'CLANGDWARF'
>
> + Args.Macro.append("UNIVERSAL_PAYLOAD_FORMAT=ELF")
>
> + UpldEntryFile = "UniversalPayloadEntry"
>
> +
>
> + BuildDir = os.path.join(os.environ['WORKSPACE'],
> os.path.normpath("Build/UefiPayloadPkgX64"))
>
> if Args.Arch == 'X64':
>
> BuildArch = "X64"
>
> - EntryOutputDir = os.path.join(BuildDir, "{}_{}".format
> (BuildTarget, ElfToolChain),
> os.path.normpath("X64/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll"))
>
> + FitArch = "x86_64"
>
> + ObjCopyFlag = "elf64-x86-64"
>
> + EntryOutputDir = os.path.join(BuildDir, "{}_{}".format
> (BuildTarget, PayloadEntryToolChain),
> os.path.normpath("X64/UefiPayloadPkg/UefiPayloadEntry/{}/DEBUG/{}.dll".format
> (UpldEntryFile, UpldEntryFile)))
>
> else:
>
> BuildArch = "IA32 -a X64"
>
> - EntryOutputDir = os.path.join(BuildDir, "{}_{}".format
> (BuildTarget, ElfToolChain),
> os.path.normpath("IA32/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll"))
>
> + FitArch = "x86"
>
> + ObjCopyFlag = "elf32-i386"
>
> + EntryOutputDir = os.path.join(BuildDir, "{}_{}".format
> (BuildTarget, PayloadEntryToolChain),
> os.path.normpath("IA32/UefiPayloadPkg/UefiPayloadEntry/{}/DEBUG/{}.dll".format
> (UpldEntryFile, UpldEntryFile)))
>
>
>
> + EntryModuleInf =
> os.path.normpath("UefiPayloadPkg/UefiPayloadEntry/{}.inf".format
> (UpldEntryFile))
>
> DscPath = os.path.normpath("UefiPayloadPkg/UefiPayloadPkg.dsc")
>
> + DxeFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget,
> ToolChain), os.path.normpath("FV/DXEFV.Fv"))
>
> + BdsFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget,
> ToolChain), os.path.normpath("FV/BDSFV.Fv"))
>
> + NetworkFvOutputDir = os.path.join(BuildDir, "{}_{}".format
> (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv"))
>
> + PayloadReportPath = os.path.join(BuildDir, "UefiUniversalPayload.txt")
>
> ModuleReportPath = os.path.join(BuildDir,
> "UefiUniversalPayloadEntry.txt")
>
> UpldInfoFile = os.path.join(BuildDir, "UniversalPayloadInfo.bin")
>
>
>
> + if "CLANG_BIN" in os.environ:
>
> + LlvmObjcopyPath = os.path.join(os.environ["CLANG_BIN"],
> "llvm-objcopy")
>
> + else:
>
> + LlvmObjcopyPath = "llvm-objcopy"
>
> + try:
>
> + RunCommand('"%s" --version'%LlvmObjcopyPath)
>
> + except:
>
> + print("- Failed - Please check if LLVM is installed or if
> CLANG_BIN is set correctly")
>
> + sys.exit(1)
>
> +
>
> Pcds = ""
>
> if (Args.pcd != None):
>
> for PcdItem in Args.pcd:
>
> @@ -84,7 +170,6 @@ def BuildUniversalPayload(Args):
> # Building DXE core and DXE drivers as DXEFV.
>
> #
>
> if Args.BuildEntryOnly == False:
>
> - PayloadReportPath = os.path.join(BuildDir,
> "UefiUniversalPayload.txt")
>
> BuildPayload = "build -p {} -b {} -a X64 -t {} -y {} {}".format
> (DscPath, BuildTarget, ToolChain, PayloadReportPath, Quiet)
>
> BuildPayload += Pcds
>
> BuildPayload += Defines
>
> @@ -93,94 +178,138 @@ def BuildUniversalPayload(Args):
> # Building Universal Payload entry.
>
> #
>
> if Args.PreBuildUplBinary is None:
>
> - EntryModuleInf =
> os.path.normpath("UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf")
>
> - BuildModule = "build -p {} -b {} -a {} -m {} -t {} -y {}
> {}".format (DscPath, BuildTarget, BuildArch, EntryModuleInf, ElfToolChain,
> ModuleReportPath, Quiet)
>
> + BuildModule = "build -p {} -b {} -a {} -m {} -t {} -y {}
> {}".format (DscPath, BuildTarget, BuildArch, EntryModuleInf,
> PayloadEntryToolChain, ModuleReportPath, Quiet)
>
> BuildModule += Pcds
>
> BuildModule += Defines
>
> RunCommand(BuildModule)
>
>
>
> if Args.PreBuildUplBinary is not None:
>
> - EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.elf")
>
> + if Args.Fit == False:
>
> + EntryOutputDir = os.path.join(BuildDir,
> "UniversalPayload.elf")
>
> + else:
>
> + EntryOutputDir = os.path.join(BuildDir,
> "UniversalPayload.fit")
>
> shutil.copy (os.path.abspath(Args.PreBuildUplBinary),
> EntryOutputDir)
>
>
>
> #
>
> - # Buid Universal Payload Information Section ".upld_info"
>
> + # Build Universal Payload Information Section ".upld_info"
>
> #
>
> - upld_info_hdr = UPLD_INFO_HEADER()
>
> - upld_info_hdr.SpecRevision = Args.SpecRevision
>
> - upld_info_hdr.Revision = Args.Revision
>
> - upld_info_hdr.ProducerId = Args.ProducerId.encode()[:16]
>
> - upld_info_hdr.ImageId = Args.ImageId.encode()[:16]
>
> - upld_info_hdr.Attribute |= 1 if BuildTarget == "DEBUG" else 0
>
> - fp = open(UpldInfoFile, 'wb')
>
> - fp.write(bytearray(upld_info_hdr))
>
> - fp.close()
>
> + if Args.Fit == False:
>
> + upld_info_hdr = UPLD_INFO_HEADER()
>
> + upld_info_hdr.SpecRevision = Args.SpecRevision
>
> + upld_info_hdr.Revision = Args.Revision
>
> + upld_info_hdr.ProducerId = Args.ProducerId.encode()[:16]
>
> + upld_info_hdr.ImageId = Args.ImageId.encode()[:16]
>
> + upld_info_hdr.Attribute |= 1 if BuildTarget == "DEBUG" else 0
>
> + fp = open(UpldInfoFile, 'wb')
>
> + fp.write(bytearray(upld_info_hdr))
>
> + fp.close()
>
> +
>
> + if Args.BuildEntryOnly == False:
>
> + import Tools.ElfFv as ElfFv
>
> + ElfFv.ReplaceFv (EntryOutputDir, UpldInfoFile, '.upld_info',
> Alignment = 4)
>
> + if Args.Fit == False:
>
> + shutil.copy (EntryOutputDir, os.path.join(BuildDir,
> 'UniversalPayload.elf'))
>
> + else:
>
> + shutil.copy (EntryOutputDir, os.path.join(BuildDir,
> 'UniversalPayload.fit'))
>
>
>
> MultiFvList = []
>
> if Args.BuildEntryOnly == False:
>
> MultiFvList = [
>
> - ['uefi_fv', os.path.join(BuildDir, "{}_{}".format
> (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv")) ],
>
> - ['bds_fv', os.path.join(BuildDir, "{}_{}".format
> (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv")) ],
>
> - ['network_fv', os.path.join(BuildDir, "{}_{}".format
> (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv")) ],
>
> + ['uefi_fv', os.path.join(BuildDir, "{}_{}".format
> (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv")) ],
>
> + ['bds_fv', os.path.join(BuildDir, "{}_{}".format
> (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv")) ],
>
> + ['network_fv', os.path.join(BuildDir, "{}_{}".format
> (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv"))],
>
> ]
>
> - AddSectionName = '.upld_info'
>
> - ReplaceFv (EntryOutputDir, UpldInfoFile, AddSectionName,
> Alignment = 4)
>
>
>
> - if Args.PreBuildUplBinary is None:
>
> - shutil.copy (EntryOutputDir, os.path.join(BuildDir,
> 'UniversalPayload.elf'))
>
>
>
> - return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.elf')
>
> + if Args.Fit == True:
>
> + import Tools.MkFitImage as MkFitImage
>
> + import pefile
>
> + fit_image_info_header =
> MkFitImage.FIT_IMAGE_INFO_HEADER()
>
> + fit_image_info_header.Description = 'Uefi Universal Payload'
>
> + fit_image_info_header.UplVersion = Args.SpecRevision
>
> + fit_image_info_header.Type = 'flat-binary'
>
> + fit_image_info_header.Arch = FitArch
>
> + fit_image_info_header.Compression = 'none'
>
> + fit_image_info_header.Revision = Args.Revision
>
> + fit_image_info_header.BuildType = Args.Target.lower()
>
> + fit_image_info_header.Capabilities = None
>
> + fit_image_info_header.Producer = Args.ProducerId.lower()
>
> + fit_image_info_header.ImageId = Args.ImageId.lower()
>
> + fit_image_info_header.Binary = os.path.join(BuildDir,
> 'UniversalPayload.fit')
>
> + fit_image_info_header.TargetPath = os.path.join(BuildDir,
> 'UniversalPayload.fit')
>
> + fit_image_info_header.UefifvPath = DxeFvOutputDir
>
> + fit_image_info_header.BdsfvPath = BdsFvOutputDir
>
> + fit_image_info_header.NetworkfvPath = NetworkFvOutputDir
>
> + fit_image_info_header.DataOffset = 0x1000
>
> + fit_image_info_header.LoadAddr = Args.LoadAddress
>
> + fit_image_info_header.Project = 'tianocore'
>
> +
>
> + TargetRebaseFile = fit_image_info_header.Binary.replace
> (pathlib.Path(fit_image_info_header.Binary).suffix, ".pecoff")
>
> + TargetRebaseEntryFile = fit_image_info_header.Binary.replace
> (pathlib.Path(fit_image_info_header.Binary).suffix, ".entry")
>
> +
>
>
>
> -def main():
>
> - def ValidateSpecRevision (Argument):
>
> - try:
>
> - (MajorStr, MinorStr) = Argument.split('.')
>
> - except:
>
> - raise argparse.ArgumentTypeError ('{} is not a valid
> SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
>
> #
>
> - # Spec Revision Bits 15 : 8 - Major Version. Bits 7 : 0 - Minor
> Version.
>
> + # Rebase PECOFF to load address
>
> #
>
> - if len(MinorStr) > 0 and len(MinorStr) < 3:
>
> - try:
>
> - Minor = int(MinorStr, 16) if len(MinorStr) == 2 else
> (int(MinorStr, 16) << 4)
>
> - except:
>
> - raise argparse.ArgumentTypeError ('{} Minor version of
> SpecRevision is not a valid integer value.'.format (Argument))
>
> - else:
>
> - raise argparse.ArgumentTypeError ('{} is not a valid
> SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
>
> + RunCommand (
>
> + "GenFw -e SEC -o {} {}".format (
>
> + TargetRebaseFile,
>
> + fit_image_info_header.Binary
>
> + ))
>
> + RunCommand (
>
> + "GenFw --rebase 0x{:02X} -o {} {} ".format (
>
> + fit_image_info_header.LoadAddr +
> fit_image_info_header.DataOffset,
>
> + TargetRebaseFile,
>
> + TargetRebaseFile,
>
> + ))
>
>
>
> - if len(MajorStr) > 0 and len(MajorStr) < 3:
>
> - try:
>
> - Major = int(MajorStr, 16)
>
> - except:
>
> - raise argparse.ArgumentTypeError ('{} Major version of
> SpecRevision is not a valid integer value.'.format (Argument))
>
> - else:
>
> - raise argparse.ArgumentTypeError ('{} is not a valid
> SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument))
>
> + #
>
> + # Open PECOFF relocation table binary.
>
> + #
>
> + RelocBinary = b''
>
> + PeCoff = pefile.PE (TargetRebaseFile)
>
> + for reloc in PeCoff.DIRECTORY_ENTRY_BASERELOC:
>
> + for entry in reloc.entries:
>
> + if (entry.type == 0):
>
> + continue
>
> + Type = entry.type
>
> + Offset = entry.rva + fit_image_info_header.DataOffset
>
> + RelocBinary += Type.to_bytes (8, 'little') +
> Offset.to_bytes (8, 'little')
>
> + RelocBinary += b'\x00' * (0x1000 - (len(RelocBinary) % 0x1000))
>
>
>
> - return int('0x{0:02x}{1:02x}'.format(Major, Minor), 0)
>
> + #
>
> + # Output UniversalPayload.entry
>
> + #
>
> + TempBinary = open (TargetRebaseFile, 'rb')
>
> + TianoBinary = TempBinary.read ()
>
> + TempBinary.close ()
>
>
>
> - def Validate32BitInteger (Argument):
>
> - try:
>
> - Value = int (Argument, 0)
>
> - except:
>
> - raise argparse.ArgumentTypeError ('{} is not a valid integer
> value.'.format (Argument))
>
> - if Value < 0:
>
> - raise argparse.ArgumentTypeError ('{} is a negative
> value.'.format (Argument))
>
> - if Value > 0xffffffff:
>
> - raise argparse.ArgumentTypeError ('{} is larger than
> 32-bits.'.format (Argument))
>
> - return Value
>
> -
>
> - def ValidateAddFv (Argument):
>
> - Value = Argument.split ("=")
>
> - if len (Value) != 2:
>
> - raise argparse.ArgumentTypeError ('{} is incorrect format
> with "xxx_fv=xxx.fv"'.format (Argument))
>
> - if Value[0][-3:] != "_fv":
>
> - raise argparse.ArgumentTypeError ('{} is incorrect format
> with "xxx_fv=xxx.fv"'.format (Argument))
>
> - if Value[1][-3:].lower () != ".fv":
>
> - raise argparse.ArgumentTypeError ('{} is incorrect format
> with "xxx_fv=xxx.fv"'.format (Argument))
>
> - if os.path.exists (Value[1]) == False:
>
> - raise argparse.ArgumentTypeError ('File {} is not
> found.'.format (Value[1]))
>
> - return Value
>
> + TianoEntryBinary = TianoBinary + RelocBinary
>
> + TianoEntryBinary += (b'\x00' * (0x1000 - (len(TianoBinary) %
> 0x1000)))
>
> + TianoEntryBinarySize = len (TianoEntryBinary)
>
> +
>
> + TempBinary = open(TargetRebaseEntryFile, "wb")
>
> + TempBinary.truncate()
>
> + TempBinary.write(TianoEntryBinary)
>
> + TempBinary.close()
>
> +
>
> + #
>
> + # Calculate entry and update relocation table start address and
> data-size.
>
> + #
>
> + fit_image_info_header.Entry =
> PeCoff.OPTIONAL_HEADER.ImageBase +
> PeCoff.OPTIONAL_HEADER.AddressOfEntryPoint
>
> + fit_image_info_header.RelocStart =
> fit_image_info_header.DataOffset + len(TianoBinary)
>
> + fit_image_info_header.DataSize = TianoEntryBinarySize
>
> + fit_image_info_header.Binary = TargetRebaseEntryFile
>
> +
>
> + if MkFitImage.MakeFitImage(fit_image_info_header) is True:
>
> + print('\nSuccessfully build Fit Image')
>
> + else:
>
> + sys.exit(1)
>
> + return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.fit')
>
> + else:
>
> + return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.elf')
>
>
>
> +def main():
>
> parser = argparse.ArgumentParser(description='For building Universal
> Payload')
>
> parser.add_argument('-t', '--ToolChain')
>
> parser.add_argument('-b', '--Target', default='DEBUG')
>
> @@ -192,13 +321,16 @@ def main():
> parser.add_argument("-s", "--SpecRevision",
> type=ValidateSpecRevision, default ='0.7', help='Indicates compliance with
> a revision of this specification in the BCD format.')
>
> parser.add_argument("-r", "--Revision", type=Validate32BitInteger,
> default ='0x0000010105', help='Revision of the Payload binary.
> Major.Minor.Revision.Build')
>
> parser.add_argument("-o", "--ProducerId", default ='INTEL', help='A
> null-terminated OEM-supplied string that identifies the payload producer
> (16 bytes maximal).')
>
> + parser.add_argument("-e", "--BuildEntryOnly", action='store_true',
> help='Build UniversalPayload Entry file')
>
> + parser.add_argument("-pb", "--PreBuildUplBinary", default=None,
> help='Specify the UniversalPayload file')
>
> parser.add_argument("-sk", "--SkipBuild", action='store_true',
> help='Skip UniversalPayload build')
>
> parser.add_argument("-af", "--AddFv", type=ValidateAddFv,
> action='append', help='Add or replace specific FV into payload, Ex:
> uefi_fv=XXX.fv')
>
> - command_group = parser.add_mutually_exclusive_group()
>
> - command_group.add_argument("-e", "--BuildEntryOnly",
> action='store_true', help='Build UniversalPayload Entry file')
>
> - command_group.add_argument("-pb", "--PreBuildUplBinary",
> default=None, help='Specify the UniversalPayload file')
>
> + parser.add_argument("-f", "--Fit", action='store_true', help='Build
> UniversalPayload file as UniversalPayload.fit', default=False)
>
> + parser.add_argument('-l', "--LoadAddress", type=int, help='Specify
> payload load address', default =0x000800000)
>
> +
>
> args = parser.parse_args()
>
>
>
> +
>
> MultiFvList = []
>
> UniversalPayloadBinary = args.PreBuildUplBinary
>
> if (args.SkipBuild == False):
>
> @@ -208,12 +340,24 @@ def main():
> for (SectionName, SectionFvFile) in args.AddFv:
>
> MultiFvList.append ([SectionName, SectionFvFile])
>
>
>
> + def ReplaceFv (UplBinary, SectionFvFile, SectionName):
>
> + print (bcolors.OKGREEN + "Patch {}={} into {}".format
> (SectionName, SectionFvFile, UplBinary) + bcolors.ENDC)
>
> + if (args.Fit == False):
>
> + import Tools.ElfFv as ElfFv
>
> + return ElfFv.ReplaceFv (UplBinary, SectionFvFile,
> '.upld.{}'.format (SectionName))
>
> + else:
>
> + import Tools.MkFitImage as MkFitImage
>
> + return MkFitImage.ReplaceFv (UplBinary, SectionFvFile,
> SectionName)
>
> +
>
> if (UniversalPayloadBinary != None):
>
> for (SectionName, SectionFvFile) in MultiFvList:
>
> if os.path.exists (SectionFvFile) == False:
>
> continue
>
> - print ("Patch {}={} into {}".format (SectionName,
> SectionFvFile, UniversalPayloadBinary))
>
> - ReplaceFv (UniversalPayloadBinary, SectionFvFile,
> '.upld.{}'.format (SectionName))
>
> +
>
> + status = ReplaceFv (UniversalPayloadBinary, SectionFvFile,
> SectionName.replace ("_", "-"))
>
> + if status != 0:
>
> + print (bcolors.FAIL + "[Fail] Patch {}={}".format
> (SectionName, SectionFvFile) + bcolors.ENDC)
>
> + return status
>
>
>
> print ("\nSuccessfully build Universal Payload")
>
>
>
> --
> 2.39.1.windows.1
>
>
>
>
>
>
>
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#108704): https://edk2.groups.io/g/devel/message/108704
Mute This Topic: https://groups.io/mt/101375948/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
[-- Attachment #2: Type: text/html, Size: 138720 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [edk2-devel] [PATCH v2 2/2] UefiPayloadPkg: Add FIT support
2023-09-15 10:26 ` Sheng Lean Tan
@ 2023-09-15 10:32 ` Sheng Lean Tan
0 siblings, 0 replies; 10+ messages in thread
From: Sheng Lean Tan @ 2023-09-15 10:32 UTC (permalink / raw)
To: Sheng Lean Tan, devel
[-- Attachment #1: Type: text/plain, Size: 414 bytes --]
The spec version should be v.8 instead of v.75
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#108705): https://edk2.groups.io/g/devel/message/108705
Mute This Topic: https://groups.io/mt/101375948/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
[-- Attachment #2: Type: text/html, Size: 826 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2023-09-15 13:03 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-15 8:58 [edk2-devel] [PATCH v2 0/2] UefiPayloadPkg supports Fit brucex.wang
2023-09-15 8:58 ` [edk2-devel] [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function brucex.wang
2023-09-15 9:02 ` Guo, Gua
2023-09-15 9:06 ` Lu, James
2023-09-15 9:09 ` Benny Lin
2023-09-15 8:58 ` [edk2-devel] [PATCH v2 2/2] UefiPayloadPkg: Add FIT support brucex.wang
2023-09-15 9:02 ` Guo, Gua
2023-09-15 10:26 ` Sheng Lean Tan
2023-09-15 10:32 ` Sheng Lean Tan
2023-09-15 9:06 ` Lu, James
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox