4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* $Id$ */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * BasePeCoff.c
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Copyright (C) 2009-2011 Oracle Corporation
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * available from http://www.virtualbox.org. This file is free software;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * you can redistribute it and/or modify it under the terms of the GNU
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * General Public License (GPL) as published by the Free Software
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * The contents of this file may alternatively be used under the terms
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * of the Common Development and Distribution License Version 1.0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * VirtualBox OSE distribution, in which case the provisions of the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * CDDL are applicable instead of those of the GPL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * You may elect to license modified versions of this file under the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * terms and conditions of either the GPL or the CDDL or both.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This code is based on:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Base PE/COFF loader supports loading any PE32/PE32+ or TE image, but
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync only supports relocating IA32, x64, IPF, and EBC images.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Copyright (c) 2006 - 2008, Intel Corporation<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Portions copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync All rights reserved. This program and the accompanying materials
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync are licensed and made available under the terms and conditions of the BSD License
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync which accompanies this distribution. The full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync http://opensource.org/licenses/bsd-license.php
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "BasePeCoffLibInternals.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#if defined(MDE_CPU_IA32)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync# define EFI_FAT_CPU_TYPE EFI_FAT_CPU_TYPE_I386
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#elif defined(MDE_CPU_X64)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync# define EFI_FAT_CPU_TYPE EFI_FAT_CPU_TYPE_X64
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync# error "please define EFI_FAT_CPU_TYPE for your arch"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Retrieves the magic value from the PE/COFF header.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Hdr The buffer in which to return the PE32, PE32+, or TE header.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUINT16
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncPeCoffLoaderGetPeHeaderMagicValue (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // then override the returned value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Return the magic value from the PC/COFF Optional Header
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Hdr.Pe32->OptionalHeader.Magic;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Retrieves the PE or TE Header from a PE/COFF or TE image.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ImageContext The context of the image being loaded.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Hdr The buffer in which to return the PE32, PE32+, or TE header.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval RETURN_SUCCESS The PE or TE Header is read.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Other The error status from reading the PE/COFF or TE image using the ImageRead function.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncRETURN_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncPeCoffLoaderGetPeHeader (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RETURN_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_DOS_HEADER DosHdr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FAT_IMAGE_HEADER Fat;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Size;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifndef VBOX /* VBox: 64-bit VS2010 say wrong type / loss of data. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Offset = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Offset = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 Magic;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FAT_IMAGE_HEADER_NLIST nlist[5];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Size = sizeof (EFI_FAT_IMAGE_HEADER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = ImageContext->ImageRead (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->Handle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Size,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Fat
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!RETURN_ERROR(Status) && Fat.Signature == EFI_FAT_IMAGE_HEADER_SIGNATURE)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 i;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG((DEBUG_LOAD, "%a:%d - %x narches:%d\n", __FILE__, __LINE__, Fat.Signature, Fat.NFatArch));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Can't find the way to allocate here because library used in all phases */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT((Fat.NFatArch < 5));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Size = sizeof(EFI_FAT_IMAGE_HEADER_NLIST) * Fat.NFatArch;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = ImageContext->ImageRead (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->Handle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (EFI_FAT_IMAGE_HEADER),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Size,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync nlist
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i = 0; i < Fat.NFatArch ; ++i)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (nlist[i].CpuType == EFI_FAT_CPU_TYPE)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->IsFat = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->FatOffset = Offset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset = nlist[i].Offset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Read the DOS image header to check for its existence
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->FatOffset = Offset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Size = sizeof (EFI_IMAGE_DOS_HEADER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = ImageContext->ImageRead (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->Handle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Size,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &DosHdr
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RETURN_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->PeCoffHeaderOffset = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DosHdr.e_magic == EFI_IMAGE_DOS_SIGNATURE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DOS image header is present, so read the PE header after the DOS image
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // header
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->PeCoffHeaderOffset = DosHdr.e_lfanew;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Read the PE/COFF Header. For PE32 (32-bit) this will read in too much
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // data, but that should not hurt anything. Hdr.Pe32->OptionalHeader.Magic
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // determines if this is a PE32 or PE32+ image. The magic is in the same
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // location in both images.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Size = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = ImageContext->ImageRead (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->Handle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->PeCoffHeaderOffset + Offset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Size,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Pe32
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RETURN_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use Signature to figure out if we understand the image format
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->IsTeImage = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->Machine = Hdr.Te->Machine;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageType = (UINT16)(Hdr.Te->Subsystem);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // For TeImage, SectionAlignment is undefined to be set to Zero
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ImageSize can be calculated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageSize = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->SectionAlignment = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN)Hdr.Te->BaseOfCode - (UINTN)Hdr.Te->StrippedSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->IsTeImage = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->Machine = Hdr.Pe32->FileHeader.Machine;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Magic = PeCoffLoaderGetPeHeaderMagicValue (Hdr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32 offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageType = Hdr.Pe32->OptionalHeader.Subsystem;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageSize = (UINT64)Hdr.Pe32->OptionalHeader.SizeOfImage;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->SizeOfHeaders = Hdr.Pe32->OptionalHeader.SizeOfHeaders;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32+ offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageType = Hdr.Pe32Plus->OptionalHeader.Subsystem;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageSize = (UINT64) Hdr.Pe32Plus->OptionalHeader.SizeOfImage;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->SectionAlignment = Hdr.Pe32Plus->OptionalHeader.SectionAlignment;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->SizeOfHeaders = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_INVALID_MACHINE_TYPE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG((DEBUG_LOAD, "%a:%d - %r\n", __FILE__, __LINE__, RETURN_UNSUPPORTED));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_UNSUPPORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_INVALID_MACHINE_TYPE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_UNSUPPORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!PeCoffLoaderImageFormatSupported (ImageContext->Machine)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the PE/COFF loader does not support the image type return
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // unsupported. This library can support lots of types of images
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // this does not mean the user of this library can call the entry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // point of the image.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG((DEBUG_LOAD, "%a:%d - %r\n", __FILE__, __LINE__, RETURN_UNSUPPORTED));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_UNSUPPORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Retrieves information about a PE/COFF image.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Computes the PeCoffHeaderOffset, IsTeImage, ImageType, ImageAddress, ImageSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DestinationAddress, RelocationsStripped, SectionAlignment, SizeOfHeaders, and
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntryRva fields of the ImageContext structure.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If ImageContext is NULL, then return RETURN_INVALID_PARAMETER.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If the PE/COFF image accessed through the ImageRead service in the ImageContext
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync structure is not a supported PE/COFF image type, then return RETURN_UNSUPPORTED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If any errors occur while computing the fields of ImageContext,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync then the error status is returned in the ImageError field of ImageContext.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If the image is a TE image, then SectionAlignment is set to 0.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The ImageRead and Handle fields of ImageContext structure must be valid prior
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync to invoking this service.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ImageContext Pointer to the image context structure that describes the PE/COFF
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync image that needs to be examined by this function.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval RETURN_SUCCESS The information on the PE/COFF image was collected.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval RETURN_INVALID_PARAMETER ImageContext is NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval RETURN_UNSUPPORTED The PE/COFF image is not supported.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncRETURN_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncPeCoffLoaderGetImageInfo (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RETURN_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_DATA_DIRECTORY *DebugDirectoryEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Size;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Index;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN DebugDirectoryEntryRva;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN DebugDirectoryEntryFileOffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN SectionHeaderOffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_SECTION_HEADER SectionHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_DEBUG_DIRECTORY_ENTRY DebugEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 Magic;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 FatOffset = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ImageContext == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Assume success
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Union = &HdrData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = PeCoffLoaderGetPeHeader (ImageContext, Hdr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RETURN_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ImageContext->IsFat)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FatOffset = ImageContext->FatOffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Magic = PeCoffLoaderGetPeHeaderMagicValue (Hdr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Retrieve the base address of the image
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!(ImageContext->IsTeImage)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32 offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageAddress = Hdr.Pe32->OptionalHeader.ImageBase;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32+ offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageAddress = Hdr.Pe32Plus->OptionalHeader.ImageBase;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageAddress = (PHYSICAL_ADDRESS)(Hdr.Te->ImageBase + Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageAddress += FatOffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Initialize the alternate destination address to 0 indicating that it
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // should not be used.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->DestinationAddress = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Initialize the debug codeview pointer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->DebugDirectoryEntryRva = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->CodeView = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->PdbPointer = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Three cases with regards to relocations:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // has no base relocs to apply
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Look at the file header to determine if relocations have been stripped, and
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // save this info in the image context for later use.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((!(ImageContext->IsTeImage)) && ((Hdr.Pe32->FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->RelocationsStripped = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if ((ImageContext->IsTeImage) && (Hdr.Te->DataDirectory[0].Size == 0) && (Hdr.Te->DataDirectory[0].VirtualAddress == 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->RelocationsStripped = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->RelocationsStripped = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!(ImageContext->IsTeImage)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32 offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32+ offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Determine the file offset of the debug directory... This means we walk
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the sections to find which section contains the RVA of the debug
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // directory
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntryFileOffset = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SectionHeaderOffset = (UINTN)(
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->PeCoffHeaderOffset +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (UINT32) +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (EFI_IMAGE_FILE_HEADER) +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Pe32->FileHeader.SizeOfOptionalHeader
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Read section header from file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Size = sizeof (EFI_IMAGE_SECTION_HEADER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = ImageContext->ImageRead (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->Handle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SectionHeaderOffset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Size,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &SectionHeader
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RETURN_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG((DEBUG_LOAD, "%a:%d - %r\n", __FILE__, __LINE__, Status));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DebugDirectoryEntryFileOffset != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < DebugDirectoryEntry->Size; Index += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Read next debug directory entry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = ImageContext->ImageRead (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->Handle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntryFileOffset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Size,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &DebugEntry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG((DEBUG_LOAD, "%a:%d - %r\n", __FILE__, __LINE__, Status));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RETURN_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DebugEntry.RVA == 0 && DebugEntry.FileOffset != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageSize += DebugEntry.SizeOfData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntry = &Hdr.Te->DataDirectory[1];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SectionHeaderOffset = (UINTN)(sizeof (EFI_TE_IMAGE_HEADER)) + FatOffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntryFileOffset = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < Hdr.Te->NumberOfSections;) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Read section header from file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Size = sizeof (EFI_IMAGE_SECTION_HEADER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = ImageContext->ImageRead (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->Handle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SectionHeaderOffset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Size,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &SectionHeader
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RETURN_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva -
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SectionHeader.VirtualAddress +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SectionHeader.PointerToRawData +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (EFI_TE_IMAGE_HEADER) -
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Te->StrippedSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // File offset of the debug directory was found, if this is not the last
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // section, then skip to the last section for calculating the image size.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Index < (UINTN) Hdr.Te->NumberOfSections - 1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SectionHeaderOffset += (Hdr.Te->NumberOfSections - 1 - Index) * sizeof (EFI_IMAGE_SECTION_HEADER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Index = Hdr.Te->NumberOfSections - 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync continue;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // In Te image header there is not a field to describe the ImageSize.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Actually, the ImageSize equals the RVA plus the VirtualSize of
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the last section mapped into memory (Must be rounded up to
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // a multiple of Section Alignment). Per the PE/COFF specification, the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // section headers in the Section Table must appear in order of the RVA
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // values for the corresponding sections. So the ImageSize can be determined
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // by the RVA and the VirtualSize of the last section header in the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Section Table.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((++Index) == (UINTN)Hdr.Te->NumberOfSections) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageSize = (SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DebugDirectoryEntryFileOffset != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < DebugDirectoryEntry->Size; Index += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Read next debug directory entry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = ImageContext->ImageRead (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->Handle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntryFileOffset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Size,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &DebugEntry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG((DEBUG_LOAD, "%a:%d - %r\n", __FILE__, __LINE__, Status));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RETURN_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Converts an image address to the loaded address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ImageContext The context of the image being loaded.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Address The relative virtual address to be converted to the loaded address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The converted address or NULL if the address can not be converted.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncPeCoffLoaderImageAddress (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN Address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Make sure that Address and ImageSize is correct for the loaded image.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Address >= ImageContext->ImageSize) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return (CHAR8 *)((UINTN) ImageContext->ImageAddress + Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Applies relocation fixups to a PE/COFF image that was loaded with PeCoffLoaderLoadImage().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If the DestinationAddress field of ImageContext is 0, then use the ImageAddress field of
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext as the relocation base address. Otherwise, use the DestinationAddress field
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync of ImageContext as the relocation base address. The caller must allocate the relocation
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fixup log buffer and fill in the FixupData field of ImageContext prior to calling this function.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The ImageRead, Handle, PeCoffHeaderOffset, IsTeImage, Machine, ImageType, ImageAddress,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageSize, DestinationAddress, RelocationsStripped, SectionAlignment, SizeOfHeaders,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntryRva, EntryPoint, FixupDataSize, CodeView, PdbPointer, and FixupData of
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the ImageContext structure must be valid prior to invoking this service.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If ImageContext is NULL, then ASSERT().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Note that if the platform does not maintain coherency between the instruction cache(s) and the data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync cache(s) in hardware, then the caller is responsible for performing cache maintenance operations
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync prior to transferring control to a PE/COFF image that is loaded using this library.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ImageContext Pointer to the image context structure that describes the PE/COFF
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync image that is being relocated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval RETURN_SUCCESS The PE/COFF image was relocated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Extended status information is in the ImageError field of ImageContext.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval RETURN_LOAD_ERROR The image in not a valid PE/COFF image.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Extended status information is in the ImageError field of ImageContext.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval RETURN_UNSUPPORTED A relocation record type is not supported.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Extended status information is in the ImageError field of ImageContext.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncRETURN_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncPeCoffLoaderRelocateImage (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RETURN_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_DATA_DIRECTORY *RelocDir;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT64 Adjust;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_BASE_RELOCATION *RelocBase;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 *Reloc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 *RelocEnd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHAR8 *Fixup;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHAR8 *FixupBase;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 *Fixup16;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 *Fixup32;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT64 *Fixup64;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHAR8 *FixupData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PHYSICAL_ADDRESS BaseAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 Magic;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (ImageContext != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Assume success
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If there are no relocation entries, then we are done
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ImageContext->RelocationsStripped) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Applies additional environment specific actions to relocate fixups
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // to a PE/COFF image if needed
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PeCoffLoaderRelocateImageExtraAction (ImageContext);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the destination address is not 0, use that rather than the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // image address as the relocation target.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ImageContext->DestinationAddress != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaseAddress = ImageContext->DestinationAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaseAddress = ImageContext->ImageAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!(ImageContext->IsTeImage)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Magic = PeCoffLoaderGetPeHeaderMagicValue (Hdr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32 offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Adjust = (UINT64)BaseAddress - Hdr.Pe32->OptionalHeader.ImageBase;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Pe32->OptionalHeader.ImageBase = (UINT32)BaseAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocDir = &Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32+ offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Adjust = (UINT64) BaseAddress - Hdr.Pe32Plus->OptionalHeader.ImageBase;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Pe32Plus->OptionalHeader.ImageBase = (UINT64)BaseAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocDir = &Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Find the relocation block
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Per the PE/COFF spec, you can't assume that a given data directory
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // is present in the image. You have to check the NumberOfRvaAndSizes in
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the optional header to verify a desired directory entry is there.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) && (RelocDir->Size > 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocBaseEnd = PeCoffLoaderImageAddress (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocDir->VirtualAddress + RelocDir->Size - 1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RelocBase == NULL || RelocBaseEnd == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_LOAD_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set base and end to bypass processing below.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocBase = RelocBaseEnd = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Te = (EFI_TE_IMAGE_HEADER *)(UINTN)(ImageContext->ImageAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Adjust = (UINT64) (BaseAddress - Hdr.Te->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->ImageBase);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Te->ImageBase = (UINT64) (BaseAddress - Hdr.Te->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Find the relocation block
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocDir = &Hdr.Te->DataDirectory[0];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RelocDir->Size > 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocBase = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)(
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageAddress +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocDir->VirtualAddress +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof(EFI_TE_IMAGE_HEADER) -
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Te->StrippedSize
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) ((UINTN) RelocBase + (UINTN) RelocDir->Size - 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set base and end to bypass processing below.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocBase = RelocBaseEnd = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If Adjust is not zero, then apply fix ups to the image
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Adjust != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Run the relocation information and apply the fixups
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixupData = ImageContext->FixupData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (RelocBase < RelocBaseEnd) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Reloc = (UINT16 *) ((CHAR8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocEnd = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock);
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Make sure RelocEnd is in the Image range.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((CHAR8 *) RelocEnd < (CHAR8 *)((UINTN) ImageContext->ImageAddress) ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (CHAR8 *) RelocEnd > (CHAR8 *)((UINTN)ImageContext->ImageAddress + (UINTN)ImageContext->ImageSize)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_LOAD_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!(ImageContext->IsTeImage)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (FixupBase == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_LOAD_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixupBase = (CHAR8 *)(UINTN)(ImageContext->ImageAddress +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocBase->VirtualAddress +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof(EFI_TE_IMAGE_HEADER) -
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Te->StrippedSize
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Run this relocation record
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (Reloc < RelocEnd) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fixup = FixupBase + (*Reloc & 0xFFF);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch ((*Reloc) >> 12) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EFI_IMAGE_REL_BASED_ABSOLUTE:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EFI_IMAGE_REL_BASED_HIGH:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fixup16 = (UINT16 *) Fixup;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) ((UINT32) Adjust >> 16)));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (FixupData != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *(UINT16 *) FixupData = *Fixup16;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixupData = FixupData + sizeof (UINT16);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EFI_IMAGE_REL_BASED_LOW:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fixup16 = (UINT16 *) Fixup;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Fixup16 = (UINT16) (*Fixup16 + (UINT16) Adjust);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (FixupData != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *(UINT16 *) FixupData = *Fixup16;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixupData = FixupData + sizeof (UINT16);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EFI_IMAGE_REL_BASED_HIGHLOW:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fixup32 = (UINT32 *) Fixup;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Fixup32 = *Fixup32 + (UINT32) Adjust;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (FixupData != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *(UINT32 *)FixupData = *Fixup32;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixupData = FixupData + sizeof (UINT32);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EFI_IMAGE_REL_BASED_DIR64:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fixup64 = (UINT64 *) Fixup;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Fixup64 = *Fixup64 + (UINT64) Adjust;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (FixupData != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixupData = ALIGN_POINTER (FixupData, sizeof(UINT64));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *(UINT64 *)(FixupData) = *Fixup64;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixupData = FixupData + sizeof(UINT64);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The common code does not handle some of the stranger IPF relocations
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // PeCoffLoaderRelocateImageEx () adds support for these complex fixups
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // on IPF and is a No-Op on other architectures.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = PeCoffLoaderRelocateImageEx (Reloc, Fixup, &FixupData, Adjust);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RETURN_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Next relocation record
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Reloc += 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Next reloc block
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Adjust the EntryPoint to match the linked-to address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ImageContext->DestinationAddress != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->EntryPoint -= (UINT64) ImageContext->ImageAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->EntryPoint += (UINT64) ImageContext->DestinationAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Applies additional environment specific actions to relocate fixups
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // to a PE/COFF image if needed
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PeCoffLoaderRelocateImageExtraAction (ImageContext);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Loads a PE/COFF image into memory.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Loads the PE/COFF image accessed through the ImageRead service of ImageContext into the buffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync specified by the ImageAddress and ImageSize fields of ImageContext. The caller must allocate
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the load buffer and fill in the ImageAddress and ImageSize fields prior to calling this function.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The EntryPoint, FixupDataSize, CodeView, PdbPointer and HiiResourceData fields of ImageContext are computed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The ImageRead, Handle, PeCoffHeaderOffset, IsTeImage, Machine, ImageType, ImageAddress, ImageSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DestinationAddress, RelocationsStripped, SectionAlignment, SizeOfHeaders, and DebugDirectoryEntryRva
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fields of the ImageContext structure must be valid prior to invoking this service.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If ImageContext is NULL, then ASSERT().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Note that if the platform does not maintain coherency between the instruction cache(s) and the data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync cache(s) in hardware, then the caller is responsible for performing cache maintenance operations
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync prior to transferring control to a PE/COFF image that is loaded using this library.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ImageContext Pointer to the image context structure that describes the PE/COFF
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync image that is being loaded.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval RETURN_SUCCESS The PE/COFF image was loaded into the buffer specified by
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the ImageAddress and ImageSize fields of ImageContext.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Extended status information is in the ImageError field of ImageContext.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval RETURN_BUFFER_TOO_SMALL The caller did not provide a large enough buffer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Extended status information is in the ImageError field of ImageContext.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval RETURN_LOAD_ERROR The PE/COFF image is an EFI Runtime image with no relocations.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Extended status information is in the ImageError field of ImageContext.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval RETURN_INVALID_PARAMETER The image address is invalid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Extended status information is in the ImageError field of ImageContext.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncRETURN_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncPeCoffLoaderLoadImage (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RETURN_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PE_COFF_LOADER_IMAGE_CONTEXT CheckContext;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_SECTION_HEADER *FirstSection;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_SECTION_HEADER *Section;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN NumberOfSections;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Index;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHAR8 *Base;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHAR8 *End;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHAR8 *MaxEnd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Size;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 TempDebugEntryRva;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 Magic;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_RESOURCE_DIRECTORY *ResourceDirectory;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *ResourceDirectoryEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirectoryString;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Offset = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (ImageContext != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Assume success
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Copy the provided context info into our local version, get what we
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // can from the original image, and then use that to make sure everything
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // is legit.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (&CheckContext, ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = PeCoffLoaderGetImageInfo (&CheckContext);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RETURN_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ImageContext->IsFat)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset = ImageContext->FatOffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Make sure there is enough allocated space for the image being loaded
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ImageContext->ImageSize < CheckContext.ImageSize) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_SIZE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_BUFFER_TOO_SMALL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ImageContext->ImageAddress == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Image cannot be loaded into 0 address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If there's no relocations, then make sure it's not a runtime driver,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // and that it's being loaded at the linked address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (CheckContext.RelocationsStripped) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the image does not contain relocations and it is a runtime driver
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // then return an error.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (CheckContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_LOAD_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the image does not contain relocations, and the requested load address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // is not the linked address, then return an error.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (CheckContext.ImageAddress != ImageContext->ImageAddress) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Make sure the allocated space has the proper section alignment
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!(ImageContext->IsTeImage)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((ImageContext->ImageAddress & (CheckContext.SectionAlignment - 1)) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_INVALID_SECTION_ALIGNMENT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Read the entire PE/COFF or TE header into memory
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!(ImageContext->IsTeImage)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = ImageContext->ImageRead (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->Handle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &ImageContext->SizeOfHeaders,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (VOID *) (UINTN) ImageContext->ImageAddress
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FirstSection = (EFI_IMAGE_SECTION_HEADER *) (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINTN)ImageContext->ImageAddress +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->PeCoffHeaderOffset +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof(UINT32) +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof(EFI_IMAGE_FILE_HEADER) +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Pe32->FileHeader.SizeOfOptionalHeader
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfSections = (UINTN) (Hdr.Pe32->FileHeader.NumberOfSections);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = ImageContext->ImageRead (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->Handle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &ImageContext->SizeOfHeaders,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (void *)(UINTN)ImageContext->ImageAddress
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Te = (EFI_TE_IMAGE_HEADER *)(UINTN)(ImageContext->ImageAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FirstSection = (EFI_IMAGE_SECTION_HEADER *) (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINTN)ImageContext->ImageAddress +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof(EFI_TE_IMAGE_HEADER)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfSections = (UINTN) (Hdr.Te->NumberOfSections);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RETURN_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_LOAD_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Load each section of the image
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Section = FirstSection;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0, MaxEnd = NULL; Index < NumberOfSections; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Read the section
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Size = (UINTN) Section->Misc.VirtualSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Size == 0) || (Size > Section->SizeOfRawData)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Size = (UINTN) Section->SizeOfRawData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Compute sections address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Base = PeCoffLoaderImageAddress (ImageContext, Section->VirtualAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync End = PeCoffLoaderImageAddress (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Section->VirtualAddress + Section->Misc.VirtualSize - 1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the size of the section is non-zero and the base address or end address resolved to 0, then fail.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Size > 0) && ((Base == NULL) || (End == NULL))) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_SECTION_NOT_LOADED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_LOAD_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ImageContext->IsTeImage) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Base = (CHAR8 *)((UINTN) Base + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN)Hdr.Te->StrippedSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync End = (CHAR8 *)((UINTN) End + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN)Hdr.Te->StrippedSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (End > MaxEnd) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MaxEnd = End;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Section->SizeOfRawData > 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!(ImageContext->IsTeImage)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = ImageContext->ImageRead (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->Handle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Section->PointerToRawData + Offset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Size,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Base
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = ImageContext->ImageRead (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->Handle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Section->PointerToRawData + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN)Hdr.Te->StrippedSize + Offset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Size,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Base
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RETURN_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If raw size is less then virtual size, zero fill the remaining
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Size < Section->Misc.VirtualSize) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (Base + Size, Section->Misc.VirtualSize - Size);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Next Section
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Section += 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get image's entry point
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Magic = PeCoffLoaderGetPeHeaderMagicValue (Hdr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!(ImageContext->IsTeImage)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Sizes of AddressOfEntryPoint are different so we need to do this safely
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32 offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->EntryPoint = (PHYSICAL_ADDRESS)(UINTN)PeCoffLoaderImageAddress (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINTN)Hdr.Pe32->OptionalHeader.AddressOfEntryPoint
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32+ offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->EntryPoint = (PHYSICAL_ADDRESS)(UINTN)PeCoffLoaderImageAddress (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINTN)Hdr.Pe32Plus->OptionalHeader.AddressOfEntryPoint
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->EntryPoint = (PHYSICAL_ADDRESS) (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINTN)ImageContext->ImageAddress +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINTN)Hdr.Te->AddressOfEntryPoint +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINTN)Hdr.Te->StrippedSize
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Determine the size of the fixup data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Per the PE/COFF spec, you can't assume that a given data directory
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // is present in the image. You have to check the NumberOfRvaAndSizes in
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the optional header to verify a desired directory entry is there.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!(ImageContext->IsTeImage)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32 offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32+ offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->FixupDataSize = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DirectoryEntry = &Hdr.Te->DataDirectory[0];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Consumer must allocate a buffer for the relocation fixup log.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Only used for runtime drivers.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->FixupData = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Load the Codeview info if present
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ImageContext->DebugDirectoryEntryRva != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!(ImageContext->IsTeImage)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugEntry = PeCoffLoaderImageAddress (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->DebugDirectoryEntryRva
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(UINTN)(
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageAddress +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->DebugDirectoryEntryRva +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof(EFI_TE_IMAGE_HEADER) -
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Te->StrippedSize
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DebugEntry != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TempDebugEntryRva = DebugEntry->RVA;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DebugEntry->RVA == 0 && DebugEntry->FileOffset != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Section--;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((UINTN)Section->SizeOfRawData < Section->Misc.VirtualSize) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TempDebugEntryRva = Section->VirtualAddress + Section->Misc.VirtualSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TempDebugEntryRva = Section->VirtualAddress + Section->SizeOfRawData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TempDebugEntryRva != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!(ImageContext->IsTeImage)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->CodeView = PeCoffLoaderImageAddress (ImageContext, TempDebugEntryRva);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->CodeView = (VOID *)(
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINTN)ImageContext->ImageAddress +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINTN)TempDebugEntryRva +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINTN)sizeof (EFI_TE_IMAGE_HEADER) -
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINTN) Hdr.Te->StrippedSize + Offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ImageContext->CodeView == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_LOAD_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DebugEntry->RVA == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Size = DebugEntry->SizeOfData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!(ImageContext->IsTeImage)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = ImageContext->ImageRead (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->Handle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugEntry->FileOffset + Offset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Size,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->CodeView
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = ImageContext->ImageRead (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->Handle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugEntry->FileOffset + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize + Offset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Size,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->CodeView
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Should we apply fix up to this field according to the size difference between PE and TE?
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Because now we maintain TE header fields unfixed, this field will also remain as they are
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // in original PE image.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RETURN_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_LOAD_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugEntry->RVA = TempDebugEntryRva;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (*(UINT32 *) ImageContext->CodeView) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case CODEVIEW_SIGNATURE_NB10:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case CODEVIEW_SIGNATURE_RSDS:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case CODEVIEW_SIGNATURE_MTOC:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get Image's HII resource section
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->HiiResourceData = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!(ImageContext->IsTeImage)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32 offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32+ offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DirectoryEntry->Size != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Base = PeCoffLoaderImageAddress (ImageContext, DirectoryEntry->VirtualAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Base != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) Base;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < ResourceDirectory->NumberOfNamedEntries; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ResourceDirectoryEntry->u1.s.NameIsString) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (Base + ResourceDirectoryEntry->u1.s.NameOffset);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ResourceDirectoryString->Length == 3 &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ResourceDirectoryString->String[0] == L'H' &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ResourceDirectoryString->String[1] == L'I' &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ResourceDirectoryString->String[2] == L'I') {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Resource Type "HII" found
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ResourceDirectoryEntry->u2.s.DataIsDirectory) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Move to next level - resource Name
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (Base + ResourceDirectoryEntry->u2.s.OffsetToDirectory);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ResourceDirectoryEntry->u2.s.DataIsDirectory) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Move to next level - resource Language
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (Base + ResourceDirectoryEntry->u2.s.OffsetToDirectory);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Now it ought to be resource Data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!ResourceDirectoryEntry->u2.s.DataIsDirectory) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *) (Base + ResourceDirectoryEntry->u2.OffsetToData);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->HiiResourceData = (PHYSICAL_ADDRESS) (UINTN) PeCoffLoaderImageAddress (ImageContext, ResourceDataEntry->OffsetToData);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ResourceDirectoryEntry++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Reapply fixups on a fixed up PE32/PE32+ image to allow virtual calling at EFI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync runtime.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This function reapplies relocation fixups to the PE/COFF image specified by ImageBase
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync and ImageSize so the image will execute correctly when the PE/COFF image is mapped
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync to the address specified by VirtualImageBase. RelocationData must be identical
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync to the FiuxupData buffer from the PE_COFF_LOADER_IMAGE_CONTEXT structure
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync after this PE/COFF image was relocated with PeCoffLoaderRelocateImage().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Note that if the platform does not maintain coherency between the instruction cache(s) and the data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync cache(s) in hardware, then the caller is responsible for performing cache maintenance operations
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync prior to transferring control to a PE/COFF image that is loaded using this library.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ImageBase Base address of a PE/COFF image that has been loaded
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync and relocated into system memory.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param VirtImageBase The request virtual address that the PE/COFF image is to
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync be fixed up for.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ImageSize The size, in bytes, of the PE/COFF image.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param RelocationData A pointer to the relocation data that was collected when the PE/COFF
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync image was relocated using PeCoffLoaderRelocateImage().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncPeCoffLoaderRelocateImageForRuntime (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN PHYSICAL_ADDRESS ImageBase,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN PHYSICAL_ADDRESS VirtImageBase,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN ImageSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *RelocationData
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHAR8 *OldBase;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHAR8 *NewBase;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_DOS_HEADER *DosHdr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_DATA_DIRECTORY *DataDirectory;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_DATA_DIRECTORY *RelocDir;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_BASE_RELOCATION *RelocBase;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 *Reloc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 *RelocEnd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHAR8 *Fixup;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHAR8 *FixupBase;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 *Fixup16;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 *Fixup32;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT64 *Fixup64;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHAR8 *FixupData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Adjust;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RETURN_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 Magic;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 FatOffset = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FAT_IMAGE_HEADER *Fat;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OldBase = (CHAR8 *)((UINTN)ImageBase);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewBase = (CHAR8 *)((UINTN)VirtImageBase);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fat = (EFI_FAT_IMAGE_HEADER *)OldBase;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if(Fat->Signature == EFI_FAT_IMAGE_HEADER_SIGNATURE)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 i;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FAT_IMAGE_HEADER_NLIST *nlist = (EFI_FAT_IMAGE_HEADER_NLIST *)&Fat[1];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i = 0; i < Fat->NFatArch; ++i)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (nlist[i].CpuType == EFI_FAT_CPU_TYPE)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FatOffset = nlist[i].Offset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OldBase += FatOffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Adjust = (UINTN) NewBase - (UINTN) OldBase;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Find the image's relocate dir info
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DosHdr = (EFI_IMAGE_DOS_HEADER *)(OldBase);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Valid DOS header so get address of PE header
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(((CHAR8 *)DosHdr) + DosHdr->e_lfanew);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // No Dos header so assume image starts with PE header.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)OldBase;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Not a valid PE image so Exit
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Magic = PeCoffLoaderGetPeHeaderMagicValue (Hdr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32 offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataDirectory = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[0]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32+ offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataDirectory = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[0]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Find the relocation block
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Per the PE/COFF spec, you can't assume that a given data directory
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // is present in the image. You have to check the NumberOfRvaAndSizes in
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the optional header to verify a desired directory entry is there.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocDir = DataDirectory + EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocBase = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)(ImageBase + FatOffset + RelocDir->VirtualAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)(ImageBase + FatOffset + RelocDir->VirtualAddress + RelocDir->Size);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Cannot find relocations, cannot continue to relocate the image, ASSERT for this invalid image.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (FALSE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ASSERT for the invalid image when RelocBase and RelocBaseEnd are both NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (RelocBase != NULL && RelocBaseEnd != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Run the whole relocation block. And re-fixup data that has not been
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // modified. The FixupData is used to see if the image has been modified
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // since it was relocated. This is so data sections that have been updated
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // by code will not be fixed up, since that would set them back to
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // defaults.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixupData = RelocationData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (RelocBase < RelocBaseEnd) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Reloc = (UINT16 *) ((UINT8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocEnd = (UINT16 *) ((UINT8 *) RelocBase + RelocBase->SizeOfBlock);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixupBase = (CHAR8 *) ((UINTN)ImageBase) + FatOffset + RelocBase->VirtualAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Run this relocation record
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (Reloc < RelocEnd) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fixup = FixupBase + (*Reloc & 0xFFF);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch ((*Reloc) >> 12) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EFI_IMAGE_REL_BASED_ABSOLUTE:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EFI_IMAGE_REL_BASED_HIGH:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fixup16 = (UINT16 *) Fixup;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*(UINT16 *) FixupData == *Fixup16) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) ((UINT32) Adjust >> 16)));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixupData = FixupData + sizeof (UINT16);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EFI_IMAGE_REL_BASED_LOW:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fixup16 = (UINT16 *) Fixup;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*(UINT16 *) FixupData == *Fixup16) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) Adjust & 0xffff));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixupData = FixupData + sizeof (UINT16);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EFI_IMAGE_REL_BASED_HIGHLOW:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fixup32 = (UINT32 *) Fixup;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*(UINT32 *) FixupData == *Fixup32) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Fixup32 = *Fixup32 + (UINT32) Adjust;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixupData = FixupData + sizeof (UINT32);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EFI_IMAGE_REL_BASED_DIR64:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fixup64 = (UINT64 *)Fixup;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixupData = ALIGN_POINTER (FixupData, sizeof (UINT64));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*(UINT64 *) FixupData == *Fixup64) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Fixup64 = *Fixup64 + (UINT64)Adjust;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixupData = FixupData + sizeof (UINT64);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EFI_IMAGE_REL_BASED_HIGHADJ:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Not valid Relocation type for UEFI image, ASSERT
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (FALSE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Only Itanium requires ConvertPeImage_Ex
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = PeHotRelocateImageEx (Reloc, Fixup, &FixupData, Adjust);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RETURN_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Next relocation record
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Reloc += 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // next reloc block
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Reads contents of a PE/COFF image from a buffer in system memory.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This is the default implementation of a PE_COFF_LOADER_READ_FILE function
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync that assumes FileHandle pointer to the beginning of a PE/COFF image.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This function reads contents of the PE/COFF image that starts at the system memory
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync address specified by FileHandle. The read operation copies ReadSize bytes from the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PE/COFF image starting at byte offset FileOffset into the buffer specified by Buffer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The size of the buffer actually read is returned in ReadSize.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If FileHandle is NULL, then ASSERT().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If ReadSize is NULL, then ASSERT().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If Buffer is NULL, then ASSERT().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FileHandle Pointer to base of the input stream
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FileOffset Offset into the PE/COFF image to begin the read operation.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ReadSize On input, the size in bytes of the requested read operation.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync On output, the number of bytes actually read.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Buffer Output buffer that contains the data read from the PE/COFF image.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval RETURN_SUCCESS Data is read from FileOffset from the Handle into
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the buffer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncRETURN_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncPeCoffLoaderImageReadFromMemory (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *FileHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN FileOffset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT UINTN *ReadSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT VOID *Buffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (ReadSize != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (FileHandle != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Buffer != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (Buffer, ((UINT8 *)FileHandle) + FileOffset, *ReadSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Unloads a loaded PE/COFF image from memory and releases its taken resource.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Releases any environment specific resources that were allocated when the image
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync specified by ImageContext was loaded using PeCoffLoaderLoadImage().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync For NT32 emulator, the PE/COFF image loaded by system needs to release.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync For real platform, the PE/COFF image loaded by Core doesn't needs to be unloaded,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync this function can simply return RETURN_SUCCESS.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If ImageContext is NULL, then ASSERT().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ImageContext Pointer to the image context structure that describes the PE/COFF
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync image to be unloaded.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval RETURN_SUCCESS The PE/COFF image was unloaded successfully.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncRETURN_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncPeCoffLoaderUnloadImage (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Applies additional environment specific actions to unload a
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // PE/COFF image if needed
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PeCoffLoaderUnloadImageExtraAction (ImageContext);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}