/** @file FIT Load Image Support Copyright (c) 2023, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #include #include #include #include #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; }