Skip to content

Commit

Permalink
UefiPayloadPkg: Add FIT support
Browse files Browse the repository at this point in the history
Provide Fit format for UniversalPayload, developer can use argument
"--Fit" to build UniversalPayload.fit

Cc: Guo Dong <[email protected]>
Cc: Sean Rhodes <[email protected]>
Cc: James Lu <[email protected]>
Cc: Gua Guo <[email protected]>

Reviewed-by: Gua Guo <[email protected]>

Signed-off-by: BruceX Wang <[email protected]>
  • Loading branch information
IntelBrucexWang authored and mergify[bot] committed Sep 26, 2023
1 parent d6b0537 commit 39f3c26
Show file tree
Hide file tree
Showing 14 changed files with 1,899 additions and 103 deletions.
6 changes: 3 additions & 3 deletions MdePkg/Include/Library/FdtLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -411,9 +411,9 @@ FdtSetProp (
CONST CHAR8 *
EFIAPI
FdtGetName (
IN VOID *Fdt,
IN INT32 NodeOffset,
IN UINT32 *Length
IN VOID *Fdt,
IN INT32 NodeOffset,
IN INT32 *Length
);

/**
Expand Down
8 changes: 4 additions & 4 deletions MdePkg/Library/BaseFdtLib/FdtLib.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,12 +416,12 @@ FdtSetProp (
CONST CHAR8 *
EFIAPI
FdtGetName (
IN VOID *Fdt,
IN INT32 NodeOffset,
IN UINT32 *Length
IN VOID *Fdt,
IN INT32 NodeOffset,
IN INT32 *Length
)
{
return fdt_get_name (Fdt, NodeOffset, (int *)Length);
return fdt_get_name (Fdt, NodeOffset, Length);
}

/**
Expand Down
19 changes: 19 additions & 0 deletions UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/** @file
Universal Payload general definitions.
Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#ifndef UNIVERSAL_PAYLOAD_BASE_H_
#define UNIVERSAL_PAYLOAD_BASE_H_

extern GUID gUniversalPayloadBaseGuid;

typedef struct {
UNIVERSAL_PAYLOAD_GENERIC_HEADER Header;
EFI_PHYSICAL_ADDRESS Entry;
} UNIVERSAL_PAYLOAD_BASE;

#endif // UNIVERSAL_PAYLOAD_BASE_H_
60 changes: 60 additions & 0 deletions UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
Original file line number Diff line number Diff line change
@@ -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
127 changes: 127 additions & 0 deletions UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
Original file line number Diff line number Diff line change
@@ -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;
}
150 changes: 150 additions & 0 deletions UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
Original file line number Diff line number Diff line change
@@ -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;
}
Loading

0 comments on commit 39f3c26

Please sign in to comment.