summaryrefslogtreecommitdiffstats
path: root/UefiPayloadPkg/PayloadLoaderPeim
diff options
context:
space:
mode:
authorBrucex.Wang <brucex.wang@intel.com>2023-09-06 09:08:12 +0800
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2023-09-26 07:26:21 +0000
commit39f3c26e8c40e092baeb0ec4d0396498506e0a9e (patch)
tree8539da19689c5a274c41ac848c229e9b05ad7c85 /UefiPayloadPkg/PayloadLoaderPeim
parentd6b05375b42c0c3b617d2058ccd35b703fb46a23 (diff)
downloadedk2-39f3c26e8c40e092baeb0ec4d0396498506e0a9e.tar.gz
UefiPayloadPkg: Add FIT support
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> Reviewed-by: Gua Guo <gua.guo@intel.com> Signed-off-by: BruceX Wang <brucex.wang@intel.com>
Diffstat (limited to 'UefiPayloadPkg/PayloadLoaderPeim')
-rw-r--r--UefiPayloadPkg/PayloadLoaderPeim/FitLib.h60
-rw-r--r--UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c127
-rw-r--r--UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c150
-rw-r--r--UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf59
4 files changed, 396 insertions, 0 deletions
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h b/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
new file mode 100644
index 0000000000..6a93b41590
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
@@ -0,0 +1,60 @@
+/** @file
+ FIT Load Image Support
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef FIT_LIB_H_
+#define FIT_LIB_H_
+
+#include <PiPei.h>
+#include <Library/DebugLib.h>
+#include <Library/FdtLib.h>
+
+typedef struct {
+ UINT64 RelocateType;
+ UINT64 Offset;
+} FIT_RELOCATE_ITEM;
+
+typedef struct {
+ EFI_PHYSICAL_ADDRESS ImageBase;
+ EFI_PHYSICAL_ADDRESS PayloadBaseAddress;
+ UINT64 PayloadSize;
+ UINTN PayloadEntryOffset;
+ UINTN PayloadEntrySize;
+ EFI_PHYSICAL_ADDRESS PayloadEntryPoint;
+ UINTN RelocateTableOffset;
+ UINTN RelocateTableCount;
+ EFI_PHYSICAL_ADDRESS PayloadLoadAddress;
+} FIT_IMAGE_CONTEXT;
+
+typedef struct {
+ CHAR8 *Name;
+ UINT32 Offset;
+} PROPERTY_DATA;
+
+#define IMAGE_BASE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, ImageBase)
+#define PAYLOAD_BASE_ADDR_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadBaseAddress)
+#define PAYLOAD_BASE_SIZE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadSize)
+#define PAYLOAD_ENTRY_OFFSET_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntryOffset)
+#define PAYLOAD_ENTRY_SIZE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntrySize)
+#define PAYLOAD_ENTRY_POINT_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntryPoint)
+#define RELOCATE_TABLE_OFFSET_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, RelocateTableOffset)
+#define RELOCATE_TABLE_COUNT_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, RelocateTableCount)
+#define PAYLOAD_LOAD_ADDR_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadLoadAddress)
+
+/**
+ Parse the FIT image info.
+ @param[in] ImageBase Memory address of an image.
+ @param[out] Context The FIT image context pointer.
+ @retval EFI_UNSUPPORTED Unsupported binary type.
+ @retval EFI_SUCCESS FIT binary is loaded successfully.
+**/
+EFI_STATUS
+EFIAPI
+ParseFitImage (
+ IN VOID *ImageBase,
+ OUT FIT_IMAGE_CONTEXT *Context
+ );
+
+#endif
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c b/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
new file mode 100644
index 0000000000..9d1d8a4f61
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
@@ -0,0 +1,127 @@
+/** @file
+ FIT Load Image Support
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "FitLib.h"
+
+PROPERTY_DATA PropertyData32List[] = {
+ { "data-offset", PAYLOAD_ENTRY_OFFSET_OFFSET },
+ { "data-size", PAYLOAD_ENTRY_SIZE_OFFSET },
+ { "reloc-start", RELOCATE_TABLE_OFFSET_OFFSET }
+};
+
+PROPERTY_DATA PropertyData64List[] = {
+ { "entry-start", PAYLOAD_ENTRY_POINT_OFFSET },
+ { "load", PAYLOAD_LOAD_ADDR_OFFSET }
+};
+
+/**
+ Parse the target firmware image info in FIT.
+ @param[in] Fdt Memory address of a fdt.
+ @param[in] Firmware Target name of an image.
+ @param[out] Context The FIT image context pointer.
+ @retval EFI_NOT_FOUND FIT node dose not find.
+ @retval EFI_SUCCESS FIT binary is loaded successfully.
+**/
+EFI_STATUS
+EFIAPI
+FitParseFirmwarePropertyData (
+ IN VOID *Fdt,
+ IN CHAR8 *Firmware,
+ OUT FIT_IMAGE_CONTEXT *Context
+ )
+{
+ CONST FDT_PROPERTY *PropertyPtr;
+ INT32 ImageNode;
+ INT32 TianoNode;
+ INT32 TempLen;
+ UINT32 *Data32;
+ UINT64 *Data64;
+ UINT32 *ContextOffset32;
+ UINT64 *ContextOffset64;
+ INT32 Index;
+
+ ImageNode = FdtSubnodeOffsetNameLen (Fdt, 0, "images", (INT32)AsciiStrLen ("images"));
+ if (ImageNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ TianoNode = FdtSubnodeOffsetNameLen (Fdt, ImageNode, Firmware, (INT32)AsciiStrLen (Firmware));
+ if (TianoNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ for (Index = 0; Index < sizeof (PropertyData32List) / sizeof (PROPERTY_DATA); Index++) {
+ PropertyPtr = FdtGetProperty (Fdt, TianoNode, PropertyData32List[Index].Name, &TempLen);
+ Data32 = (UINT32 *)(PropertyPtr->Data);
+ ContextOffset32 = (UINT32 *)((UINTN)Context + PropertyData32List[Index].Offset);
+ *ContextOffset32 = Fdt32ToCpu (*Data32);
+ }
+
+ for (Index = 0; Index < sizeof (PropertyData64List)/sizeof (PROPERTY_DATA); Index++) {
+ PropertyPtr = FdtGetProperty (Fdt, TianoNode, PropertyData64List[Index].Name, &TempLen);
+ Data64 = (UINT64 *)(PropertyPtr->Data);
+ ContextOffset64 = (UINT64 *)((UINTN)Context + PropertyData64List[Index].Offset);
+ *ContextOffset64 = Fdt64ToCpu (*Data64);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Parse the FIT image info.
+ @param[in] ImageBase Memory address of an image.
+ @param[out] Context The FIT image context pointer.
+ @retval EFI_UNSUPPORTED Unsupported binary type.
+ @retval EFI_SUCCESS FIT binary is loaded successfully.
+**/
+EFI_STATUS
+EFIAPI
+ParseFitImage (
+ IN VOID *ImageBase,
+ OUT FIT_IMAGE_CONTEXT *Context
+ )
+{
+ VOID *Fdt;
+ INT32 ConfigNode;
+ INT32 Config1Node;
+ CONST FDT_PROPERTY *PropertyPtr;
+ INT32 TempLen;
+ UINT32 *Data32;
+ UINT64 Value;
+ EFI_STATUS Status;
+ UINTN UplSize;
+ CHAR8 *Firmware;
+
+ Status = FdtCheckHeader (ImageBase);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Fdt = ImageBase;
+ PropertyPtr = FdtGetProperty (Fdt, 0, "size", &TempLen);
+ Data32 = (UINT32 *)(PropertyPtr->Data);
+ UplSize = Value = Fdt32ToCpu (*Data32);
+ ConfigNode = FdtSubnodeOffsetNameLen (Fdt, 0, "configurations", (INT32)AsciiStrLen ("configurations"));
+ if (ConfigNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ Config1Node = FdtSubnodeOffsetNameLen (Fdt, ConfigNode, "conf-1", (INT32)AsciiStrLen ("conf-1"));
+ if (Config1Node <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ PropertyPtr = FdtGetProperty (Fdt, Config1Node, "firmware", &TempLen);
+ Firmware = (CHAR8 *)(PropertyPtr->Data);
+
+ FitParseFirmwarePropertyData (Fdt, Firmware, Context);
+
+ Context->ImageBase = (EFI_PHYSICAL_ADDRESS)ImageBase;
+ Context->PayloadSize = UplSize;
+ Context->RelocateTableCount = (Context->PayloadEntrySize - (Context->RelocateTableOffset - Context->PayloadEntryOffset)) / sizeof (FIT_RELOCATE_ITEM);
+
+ return EFI_SUCCESS;
+}
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
new file mode 100644
index 0000000000..de33d49bd1
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
@@ -0,0 +1,150 @@
+/** @file
+ FIT Load Image Support
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiPei.h>
+#include <UniversalPayload/UniversalPayload.h>
+#include <Guid/UniversalPayloadBase.h>
+#include <UniversalPayload/ExtraData.h>
+
+#include <Ppi/LoadFile.h>
+
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+
+#include "FitLib.h"
+
+/**
+ The wrapper function of PeiLoadImageLoadImage().
+ @param This - Pointer to EFI_PEI_LOAD_FILE_PPI.
+ @param FileHandle - Pointer to the FFS file header of the image.
+ @param ImageAddressArg - Pointer to PE/TE image.
+ @param ImageSizeArg - Size of PE/TE image.
+ @param EntryPoint - Pointer to entry point of specified image file for output.
+ @param AuthenticationState - Pointer to attestation authentication state of image.
+ @return Status of PeiLoadImageLoadImage().
+**/
+EFI_STATUS
+EFIAPI
+PeiLoadFileLoadPayload (
+ IN CONST EFI_PEI_LOAD_FILE_PPI *This,
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL,
+ OUT UINT64 *ImageSizeArg OPTIONAL,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
+ OUT UINT32 *AuthenticationState
+ )
+{
+ EFI_STATUS Status;
+ FIT_IMAGE_CONTEXT Context;
+ UINTN Instance;
+ VOID *Binary;
+ FIT_RELOCATE_ITEM *RelocateTable;
+ UNIVERSAL_PAYLOAD_BASE *PayloadBase;
+ UINTN Length;
+ UINTN Delta;
+ UINTN Index;
+
+ Instance = 0;
+ do {
+ Status = PeiServicesFfsFindSectionData3 (EFI_SECTION_RAW, Instance++, FileHandle, &Binary, AuthenticationState);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ZeroMem (&Context, sizeof (Context));
+ Status = ParseFitImage (Binary, &Context);
+ } while (EFI_ERROR (Status));
+
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "Before Rebase Payload File Base: 0x%08x, File Size: 0x%08X, EntryPoint: 0x%08x\n",
+ Context.PayloadBaseAddress,
+ Context.PayloadSize,
+ Context.PayloadEntryPoint
+ ));
+ Context.PayloadBaseAddress = (EFI_PHYSICAL_ADDRESS)AllocatePages (EFI_SIZE_TO_PAGES (Context.PayloadSize));
+
+ RelocateTable = (FIT_RELOCATE_ITEM *)(UINTN)(Context.PayloadBaseAddress + Context.RelocateTableOffset);
+ CopyMem ((VOID *)Context.PayloadBaseAddress, Binary, Context.PayloadSize);
+
+ if (Context.PayloadBaseAddress > Context.PayloadLoadAddress) {
+ Delta = Context.PayloadBaseAddress - Context.PayloadLoadAddress;
+ Context.PayloadEntryPoint += Delta;
+ for (Index = 0; Index < Context.RelocateTableCount; Index++) {
+ if ((RelocateTable[Index].RelocateType == 10) || (RelocateTable[Index].RelocateType == 3)) {
+ *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) = *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) + Delta;
+ }
+ }
+ } else {
+ Delta = Context.PayloadLoadAddress - Context.PayloadBaseAddress;
+ Context.PayloadEntryPoint -= Delta;
+ for (Index = 0; Index < Context.RelocateTableCount; Index++) {
+ if ((RelocateTable[Index].RelocateType == 10) || (RelocateTable[Index].RelocateType == 3)) {
+ *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) = *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) - Delta;
+ }
+ }
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "After Rebase Payload File Base: 0x%08x, File Size: 0x%08X, EntryPoint: 0x%08x\n",
+ Context.PayloadBaseAddress,
+ Context.PayloadSize,
+ Context.PayloadEntryPoint
+ ));
+
+ Length = sizeof (UNIVERSAL_PAYLOAD_BASE);
+ PayloadBase = BuildGuidHob (
+ &gUniversalPayloadBaseGuid,
+ Length
+ );
+ PayloadBase->Entry = (EFI_PHYSICAL_ADDRESS)Context.ImageBase;
+
+ *ImageAddressArg = Context.PayloadBaseAddress;
+ *ImageSizeArg = Context.PayloadSize;
+ *EntryPoint = Context.PayloadEntryPoint;
+
+ return EFI_SUCCESS;
+}
+
+EFI_PEI_LOAD_FILE_PPI mPeiLoadFilePpi = {
+ PeiLoadFileLoadPayload
+};
+
+EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiLoadFilePpiGuid,
+ &mPeiLoadFilePpi
+};
+
+/**
+ Install Pei Load File PPI.
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+ @retval EFI_SUCESS The entry point executes successfully.
+ @retval Others Some error occurs during the execution of this function.
+**/
+EFI_STATUS
+EFIAPI
+InitializeFitPayloadLoaderPeim (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PeiServicesInstallPpi (&gPpiLoadFilePpiList);
+
+ return Status;
+}
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
new file mode 100644
index 0000000000..cd0cb186e1
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
@@ -0,0 +1,59 @@
+## @file
+# Produce LoadFile PPI for payload loading.
+#
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FitPayloadLoaderPeim
+ FILE_GUID = 55AC82C8-FC17-4C56-BCDA-990BB0A73E41
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InitializeFitPayloadLoaderPeim
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ FitPayloadLoaderPeim.c
+ FitLib.h
+ FitLib/FitLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ PcAtChipsetPkg/PcAtChipsetPkg.dec
+ UefiPayloadPkg/UefiPayloadPkg.dec
+
+[LibraryClasses]
+ PcdLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ PeiServicesLib
+ HobLib
+ BaseLib
+ PeimEntryPoint
+ DebugLib
+ FdtLib
+
+[Ppis]
+ gEfiPeiLoadFilePpiGuid ## PRODUCES
+
+[Pcd]
+ gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister
+ gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister
+
+[Guids]
+ gUniversalPayloadExtraDataGuid ## PRODUCES
+ gUniversalPayloadBaseGuid ## PRODUCES
+
+[Depex]
+ TRUE