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>
This commit is contained in:
Brucex.Wang
2023-09-06 09:08:12 +08:00
committed by mergify[bot]
parent d6b05375b4
commit 39f3c26e8c
14 changed files with 1904 additions and 108 deletions

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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