audk/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c

151 lines
5.1 KiB
C

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