4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Copyright (C) 2009-2011 Oracle Corporation
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 * 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 * 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 This code is based on:
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 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 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# error "please define EFI_FAT_CPU_TYPE for your arch"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Retrieves the magic value from the PE/COFF header.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Hdr The buffer in which to return the PE32, PE32+, or TE header.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+
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 if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Return the magic value from the PC/COFF Optional Header
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Retrieves the PE or TE Header from a PE/COFF or TE image.
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 @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#ifndef VBOX /* VBox: 64-bit VS2010 say wrong type / loss of data. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!RETURN_ERROR(Status) && Fat.Signature == EFI_FAT_IMAGE_HEADER_SIGNATURE)
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 Size = sizeof(EFI_FAT_IMAGE_HEADER_NLIST) * Fat.NFatArch;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Read the DOS image header to check for its existence
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DOS image header is present, so read the PE header after the DOS image
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->PeCoffHeaderOffset = DosHdr.e_lfanew;
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 // Use Signature to figure out if we understand the image format
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageType = (UINT16)(Hdr.Te->Subsystem);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // For TeImage, SectionAlignment is undefined to be set to Zero
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ImageSize can be calculated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN)Hdr.Te->BaseOfCode - (UINTN)Hdr.Te->StrippedSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->Machine = Hdr.Pe32->FileHeader.Machine;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32 offset
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 } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32+ offset
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 ImageContext->ImageError = IMAGE_ERROR_INVALID_MACHINE_TYPE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG((DEBUG_LOAD, "%a:%d - %r\n", __FILE__, __LINE__, RETURN_UNSUPPORTED));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_INVALID_MACHINE_TYPE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!PeCoffLoaderImageFormatSupported (ImageContext->Machine)) {
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 DEBUG((DEBUG_LOAD, "%a:%d - %r\n", __FILE__, __LINE__, RETURN_UNSUPPORTED));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Retrieves information about a PE/COFF image.
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 @param ImageContext Pointer to the image context structure that describes the PE/COFF
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync image that needs to be examined by this function.
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 // Assume success
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = PeCoffLoaderGetPeHeader (ImageContext, Hdr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Retrieve the base address of the image
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32 offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageAddress = Hdr.Pe32->OptionalHeader.ImageBase;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32+ offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageAddress = Hdr.Pe32Plus->OptionalHeader.ImageBase;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageAddress = (PHYSICAL_ADDRESS)(Hdr.Te->ImageBase + Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Initialize the alternate destination address to 0 indicating that it
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // should not be used.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Initialize the debug codeview pointer.
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 // 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 if ((!(ImageContext->IsTeImage)) && ((Hdr.Pe32->FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if ((ImageContext->IsTeImage) && (Hdr.Te->DataDirectory[0].Size == 0) && (Hdr.Te->DataDirectory[0].VirtualAddress == 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32 offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32+ offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress;
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 for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Read section header from file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG((DEBUG_LOAD, "%a:%d - %r\n", __FILE__, __LINE__, Status));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < DebugDirectoryEntry->Size; Index += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Read next debug directory entry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG((DEBUG_LOAD, "%a:%d - %r\n", __FILE__, __LINE__, Status));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DebugEntry.RVA == 0 && DebugEntry.FileOffset != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SectionHeaderOffset = (UINTN)(sizeof (EFI_TE_IMAGE_HEADER)) + FatOffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < Hdr.Te->NumberOfSections;) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Read section header from file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva -
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 if (Index < (UINTN) Hdr.Te->NumberOfSections - 1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SectionHeaderOffset += (Hdr.Te->NumberOfSections - 1 - Index) * sizeof (EFI_IMAGE_SECTION_HEADER);
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 if ((++Index) == (UINTN)Hdr.Te->NumberOfSections) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageSize = (SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < DebugDirectoryEntry->Size; Index += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Read next debug directory entry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG((DEBUG_LOAD, "%a:%d - %r\n", __FILE__, __LINE__, Status));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Converts an image address to the loaded address.
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 @return The converted address or NULL if the address can not be converted.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Make sure that Address and ImageSize is correct for the loaded image.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return (CHAR8 *)((UINTN) ImageContext->ImageAddress + Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Applies relocation fixups to a PE/COFF image that was loaded with PeCoffLoaderLoadImage().
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 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 If ImageContext is NULL, then ASSERT().
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 @param ImageContext Pointer to the image context structure that describes the PE/COFF
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync image that is being relocated.
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 // Assume success
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If there are no relocation entries, then we are done
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Applies additional environment specific actions to relocate fixups
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // to a PE/COFF image if needed
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PeCoffLoaderRelocateImageExtraAction (ImageContext);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the destination address is not 0, use that rather than the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // image address as the relocation target.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32 offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Adjust = (UINT64)BaseAddress - Hdr.Pe32->OptionalHeader.ImageBase;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Pe32->OptionalHeader.ImageBase = (UINT32)BaseAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocDir = &Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32+ offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Adjust = (UINT64) BaseAddress - Hdr.Pe32Plus->OptionalHeader.ImageBase;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Pe32Plus->OptionalHeader.ImageBase = (UINT64)BaseAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocDir = &Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
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 if ((NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) && (RelocDir->Size > 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set base and end to bypass processing below.
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 // Find the relocation block
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) ((UINTN) RelocBase + (UINTN) RelocDir->Size - 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set base and end to bypass processing below.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If Adjust is not zero, then apply fix ups to the image
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Run the relocation information and apply the fixups
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Reloc = (UINT16 *) ((CHAR8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocEnd = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Make sure RelocEnd is in the Image range.
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 FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixupBase = (CHAR8 *)(UINTN)(ImageContext->ImageAddress +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Run this relocation record
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) ((UINT32) Adjust >> 16)));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixupData = ALIGN_POINTER (FixupData, sizeof(UINT64));
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 Status = PeCoffLoaderRelocateImageEx (Reloc, Fixup, &FixupData, Adjust);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Next relocation record
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Next reloc block
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Adjust the EntryPoint to match the linked-to address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->EntryPoint -= (UINT64) ImageContext->ImageAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->EntryPoint += (UINT64) ImageContext->DestinationAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Applies additional environment specific actions to relocate fixups
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // to a PE/COFF image if needed
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PeCoffLoaderRelocateImageExtraAction (ImageContext);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Loads a PE/COFF image into memory.
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 If ImageContext is NULL, then ASSERT().
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 @param ImageContext Pointer to the image context structure that describes the PE/COFF
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync image that is being loaded.
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 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *ResourceDirectoryEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirectoryString;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Assume success
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 CopyMem (&CheckContext, ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Make sure there is enough allocated space for the image being loaded
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ImageContext->ImageSize < CheckContext.ImageSize) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_SIZE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Image cannot be loaded into 0 address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;
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 // If the image does not contain relocations and it is a runtime driver
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // then return an error.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (CheckContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the image does not contain relocations, and the requested load address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // is not the linked address, then return an error.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (CheckContext.ImageAddress != ImageContext->ImageAddress) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Make sure the allocated space has the proper section alignment
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((ImageContext->ImageAddress & (CheckContext.SectionAlignment - 1)) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_INVALID_SECTION_ALIGNMENT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Read the entire PE/COFF or TE header into memory
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfSections = (UINTN) (Hdr.Pe32->FileHeader.NumberOfSections);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Te = (EFI_TE_IMAGE_HEADER *)(UINTN)(ImageContext->ImageAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfSections = (UINTN) (Hdr.Te->NumberOfSections);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Load each section of the image
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0, MaxEnd = NULL; Index < NumberOfSections; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Read the section
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Size == 0) || (Size > Section->SizeOfRawData)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Compute sections address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Base = PeCoffLoaderImageAddress (ImageContext, Section->VirtualAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Section->VirtualAddress + Section->Misc.VirtualSize - 1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the size of the section is non-zero and the base address or end address resolved to 0, then fail.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Size > 0) && ((Base == NULL) || (End == NULL))) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->ImageError = IMAGE_ERROR_SECTION_NOT_LOADED;
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 Section->PointerToRawData + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN)Hdr.Te->StrippedSize + Offset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If raw size is less then virtual size, zero fill the remaining
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (Base + Size, Section->Misc.VirtualSize - Size);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Next Section
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get image's entry point
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Sizes of AddressOfEntryPoint are different so we need to do this safely
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32 offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->EntryPoint = (PHYSICAL_ADDRESS)(UINTN)PeCoffLoaderImageAddress (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINTN)Hdr.Pe32->OptionalHeader.AddressOfEntryPoint
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32+ offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->EntryPoint = (PHYSICAL_ADDRESS)(UINTN)PeCoffLoaderImageAddress (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINTN)Hdr.Pe32Plus->OptionalHeader.AddressOfEntryPoint
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Determine the size of the fixup data
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 // Use PE32 offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32+ offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Consumer must allocate a buffer for the relocation fixup log.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Only used for runtime drivers.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Load the Codeview info if present
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(UINTN)(
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DebugEntry->RVA == 0 && DebugEntry->FileOffset != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((UINTN)Section->SizeOfRawData < Section->Misc.VirtualSize) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TempDebugEntryRva = Section->VirtualAddress + Section->Misc.VirtualSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TempDebugEntryRva = Section->VirtualAddress + Section->SizeOfRawData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->CodeView = PeCoffLoaderImageAddress (ImageContext, TempDebugEntryRva);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugEntry->FileOffset + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize + Offset,
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 ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get Image's HII resource section
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32 offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32+ offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Base = PeCoffLoaderImageAddress (ImageContext, DirectoryEntry->VirtualAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) Base;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < ResourceDirectory->NumberOfNamedEntries; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (Base + ResourceDirectoryEntry->u1.s.NameOffset);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Resource Type "HII" found
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ResourceDirectoryEntry->u2.s.DataIsDirectory) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Move to next level - resource Name
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (Base + ResourceDirectoryEntry->u2.s.OffsetToDirectory);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ResourceDirectoryEntry->u2.s.DataIsDirectory) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Move to next level - resource Language
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (Base + ResourceDirectoryEntry->u2.s.OffsetToDirectory);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Now it ought to be resource Data
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 Reapply fixups on a fixed up PE32/PE32+ image to allow virtual calling at EFI
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 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 @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 if(Fat->Signature == EFI_FAT_IMAGE_HEADER_SIGNATURE)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FAT_IMAGE_HEADER_NLIST *nlist = (EFI_FAT_IMAGE_HEADER_NLIST *)&Fat[1];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Find the image's relocate dir info
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Valid DOS header so get address of PE header
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(((CHAR8 *)DosHdr) + DosHdr->e_lfanew);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // No Dos header so assume image starts with PE header.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Not a valid PE image so Exit
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32 offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataDirectory = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[0]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32+ offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataDirectory = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[0]);
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 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 // Cannot find relocations, cannot continue to relocate the image, ASSERT for this invalid image.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ASSERT for the invalid image when RelocBase and RelocBaseEnd are both NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (RelocBase != NULL && RelocBaseEnd != NULL);
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 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 // Run this relocation record
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) ((UINT32) Adjust >> 16)));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) Adjust & 0xffff));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixupData = ALIGN_POINTER (FixupData, sizeof (UINT64));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Not valid Relocation type for UEFI image, ASSERT
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Only Itanium requires ConvertPeImage_Ex
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = PeHotRelocateImageEx (Reloc, Fixup, &FixupData, Adjust);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Next relocation record
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // next reloc block
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Reads contents of a PE/COFF image from a buffer in system memory.
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 If FileHandle is NULL, then ASSERT().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If ReadSize is NULL, then ASSERT().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If Buffer is NULL, then ASSERT().
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 @retval RETURN_SUCCESS Data is read from FileOffset from the Handle into
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the buffer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (Buffer, ((UINT8 *)FileHandle) + FileOffset, *ReadSize);
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 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 If ImageContext is NULL, then ASSERT().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ImageContext Pointer to the image context structure that describes the PE/COFF
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync image to be unloaded.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval RETURN_SUCCESS The PE/COFF image was unloaded successfully.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Applies additional environment specific actions to unload a
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // PE/COFF image if needed