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>
		
			
				
	
	
		
			151 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			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;
 | 
						|
}
 |