summaryrefslogtreecommitdiffstats
path: root/UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.c
diff options
context:
space:
mode:
Diffstat (limited to 'UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.c')
-rw-r--r--UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.c187
1 files changed, 187 insertions, 0 deletions
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.c b/UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.c
new file mode 100644
index 0000000000..c619470dbb
--- /dev/null
+++ b/UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.c
@@ -0,0 +1,187 @@
+/** @file
+ ELF Load Image Support
+
+Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <UniversalPayload/UniversalPayload.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 "ElfLib.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;
+ VOID *Elf;
+ UNIVERSAL_PAYLOAD_EXTRA_DATA *ExtraData;
+ ELF_IMAGE_CONTEXT Context;
+ UNIVERSAL_PAYLOAD_INFO_HEADER *PldInfo;
+ UINT32 Index;
+ UINT16 ExtraDataIndex;
+ CHAR8 *SectionName;
+ UINTN Offset;
+ UINTN Size;
+ UINT32 ExtraDataCount;
+ UINTN Instance;
+
+ //
+ // ELF is added to file as RAW section for EDKII bootloader.
+ // But RAW section might be added by build tool before the ELF RAW section when alignment is specified for ELF RAW section.
+ // Below loop skips the RAW section that doesn't contain valid ELF image.
+ //
+ Instance = 0;
+ do {
+ Status = PeiServicesFfsFindSectionData3 (EFI_SECTION_RAW, Instance++, FileHandle, &Elf, AuthenticationState);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ZeroMem (&Context, sizeof (Context));
+ Status = ParseElfImage (Elf, &Context);
+ } while (EFI_ERROR (Status));
+
+ DEBUG ((
+ DEBUG_INFO, "Payload File Size: 0x%08X, Mem Size: 0x%08x, Reload: %d\n",
+ Context.FileSize, Context.ImageSize, Context.ReloadRequired
+ ));
+
+ //
+ // Get UNIVERSAL_PAYLOAD_INFO_HEADER and number of additional PLD sections.
+ //
+ PldInfo = NULL;
+ ExtraDataCount = 0;
+ for (Index = 0; Index < Context.ShNum; Index++) {
+ Status = GetElfSectionName (&Context, Index, &SectionName);
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+ DEBUG ((DEBUG_INFO, "Payload Section[%d]: %a\n", Index, SectionName));
+ if (AsciiStrCmp(SectionName, UNIVERSAL_PAYLOAD_INFO_SEC_NAME) == 0) {
+ Status = GetElfSectionPos (&Context, Index, &Offset, &Size);
+ if (!EFI_ERROR(Status)) {
+ PldInfo = (UNIVERSAL_PAYLOAD_INFO_HEADER *)(Context.FileBase + Offset);
+ }
+ } else if (AsciiStrnCmp(SectionName, UNIVERSAL_PAYLOAD_EXTRA_SEC_NAME_PREFIX, UNIVERSAL_PAYLOAD_EXTRA_SEC_NAME_PREFIX_LENGTH) == 0) {
+ Status = GetElfSectionPos (&Context, Index, &Offset, &Size);
+ if (!EFI_ERROR (Status)) {
+ ExtraDataCount++;
+ }
+ }
+ }
+
+ //
+ // Report the additional PLD sections through HOB.
+ //
+ ExtraData = BuildGuidHob (
+ &gUniversalPayloadExtraDataGuid,
+ sizeof (UNIVERSAL_PAYLOAD_EXTRA_DATA) + ExtraDataCount * sizeof (UNIVERSAL_PAYLOAD_EXTRA_DATA_ENTRY)
+ );
+ ExtraData->Count = ExtraDataCount;
+ if (ExtraDataCount != 0) {
+ for (ExtraDataIndex = 0, Index = 0; Index < Context.ShNum; Index++) {
+ Status = GetElfSectionName (&Context, Index, &SectionName);
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+ if (AsciiStrnCmp(SectionName, UNIVERSAL_PAYLOAD_EXTRA_SEC_NAME_PREFIX, UNIVERSAL_PAYLOAD_EXTRA_SEC_NAME_PREFIX_LENGTH) == 0) {
+ Status = GetElfSectionPos (&Context, Index, &Offset, &Size);
+ if (!EFI_ERROR (Status)) {
+ ASSERT (ExtraDataIndex < ExtraDataCount);
+ AsciiStrCpyS (
+ ExtraData->Entry[ExtraDataIndex].Identifier,
+ sizeof(ExtraData->Entry[ExtraDataIndex].Identifier),
+ SectionName + UNIVERSAL_PAYLOAD_EXTRA_SEC_NAME_PREFIX_LENGTH
+ );
+ ExtraData->Entry[ExtraDataIndex].Base = (UINTN)(Context.FileBase + Offset);
+ ExtraData->Entry[ExtraDataIndex].Size = Size;
+ ExtraDataIndex++;
+ }
+ }
+ }
+ }
+
+ if (Context.ReloadRequired || Context.PreferredImageAddress != Context.FileBase) {
+ Context.ImageAddress = AllocatePages (EFI_SIZE_TO_PAGES (Context.ImageSize));
+ } else {
+ Context.ImageAddress = Context.FileBase;
+ }
+
+ //
+ // Load ELF into the required base
+ //
+ Status = LoadElfImage (&Context);
+ if (!EFI_ERROR(Status)) {
+ *ImageAddressArg = (UINTN) Context.ImageAddress;
+ *EntryPoint = Context.EntryPoint;
+ *ImageSizeArg = Context.ImageSize;
+ }
+ return Status;
+}
+
+
+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
+InitializePayloadLoaderPeim (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ Status = PeiServicesInstallPpi (&gPpiLoadFilePpiList);
+
+ return Status;
+}