⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 image.c

📁 EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是EFI BIOS源代码中的与平台无关部分的代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++

Copyright (c) 2004 - 2006, Intel Corporation                                                         
All rights reserved. This program and the accompanying materials                          
are licensed and made available under the terms and conditions of the BSD License         
which accompanies this distribution.  The full text of the license may be found at        
http://opensource.org/licenses/bsd-license.php                                            
                                                                                          
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

Module Name:
  
  Image.c

Abstract:

  Core image handling services

--*/

#include "Image.h"
#include "EfiHobLib.h"
#include "EfiPerf.h"

//
// Module Globals
//

LOADED_IMAGE_PRIVATE_DATA  *mCurrentImage = NULL;

LOAD_PE32_IMAGE_PRIVATE_DATA  mLoadPe32PrivateData = { 
  LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE,
  NULL,
  CoreLoadImageEx,
  CoreUnloadImageEx
};


//
// This code is needed to build the Image handle for the DXE Core
//
LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage  = {
  LOADED_IMAGE_PRIVATE_DATA_SIGNATURE,            // Signature
  NULL,                                           // Image handle
  EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,    // Image type
  TRUE,                                           // If entrypoint has been called
  NULL,                                           // EntryPoint
  {
    EFI_LOADED_IMAGE_INFORMATION_REVISION,        // Revision
    NULL,                                         // Parent handle
    NULL,                                         // System handle

    NULL,                                         // Device handle
    NULL,                                         // File path
    NULL,                                         // Reserved

    0,                                            // LoadOptionsSize
    NULL,                                         // LoadOptions

    NULL,                                         // ImageBase
    0,                                            // ImageSize
    EfiBootServicesCode,                          // ImageCodeType
    EfiBootServicesData                           // ImageDataType
  },
  (EFI_PHYSICAL_ADDRESS)0,                        // ImageBasePage
  0,                                              // NumberOfPages
  NULL,                                           // FixupData  
  0,                                              // Tpl
  EFI_SUCCESS,                                    // Status
  0,                                              // ExitDataSize
  NULL,                                           // ExitData
  NULL,                                           // JumpContext
  0,                                              // Machine
  NULL,                                           // Ebc 
  NULL,                                           // RuntimeData
};


STATIC
EFI_STATUS
EFIAPI
CoreFlushICache (
  IN EFI_PHYSICAL_ADDRESS     Start,
  IN UINT64                   Length
  );



EFI_STATUS
CoreInitializeImageServices (
  IN  VOID *HobStart
  )
/*++

Routine Description:

  Add the Image Services to EFI Boot Services Table and install the protocol
  interfaces for this image.

Arguments:

  HobStart        - The HOB to initialize

Returns:

  Status code.

--*/
{
  EFI_STATUS                      Status;
  LOADED_IMAGE_PRIVATE_DATA       *Image;
  EFI_PHYSICAL_ADDRESS            DxeCoreImageBaseAddress;
  UINT64                          DxeCoreImageLength;
  VOID                            *DxeCoreEntryPoint;


  //
  // Searching for image hob
  //
  Status = GetDxeCoreHobInfo (
             HobStart,
             &DxeCoreImageBaseAddress,
             &DxeCoreImageLength,
             &DxeCoreEntryPoint,
             &gDxeCoreFileName
             );
  ASSERT_EFI_ERROR (Status);

  //
  // Initialize the fields for an internal driver
  //
  Image = &mCorePrivateImage;

  Image->EntryPoint         = (EFI_IMAGE_ENTRY_POINT)(UINTN)DxeCoreEntryPoint;
  Image->ImageBasePage      = DxeCoreImageBaseAddress; 
  Image->NumberOfPages      = (UINTN)(EFI_SIZE_TO_PAGES((UINTN)(DxeCoreImageLength)));
  Image->Tpl                = gEfiCurrentTpl;
  Image->Info.SystemTable   = gST;
  Image->Info.ImageBase     = (VOID *)(UINTN)DxeCoreImageBaseAddress;
  Image->Info.ImageSize     = DxeCoreImageLength;
  
  //
  // Install the protocol interfaces for this image
  //
  Status = CoreInstallProtocolInterface (
             &Image->Handle,
             &gEfiLoadedImageProtocolGuid,
             EFI_NATIVE_INTERFACE,
             &Image->Info
             );
  ASSERT_EFI_ERROR (Status);

  //
  // Install Debug Mask Protocol
  //
  DEBUG_CODE (
    if (!EFI_ERROR (Status)) {
      Status = InstallCoreDebugMaskProtocol(Image->Handle); 
      ASSERT_EFI_ERROR (Status);
    } 
  )

  mCurrentImage = Image;
  
  //
  // Fill in DXE globals
  //
  gDxeCoreImageHandle = Image->Handle;
  gDxeCoreLoadedImage = &Image->Info;

  //
  // Export DXE Core PE Loader functionality 
  //
  return CoreInstallProtocolInterface (
           &mLoadPe32PrivateData.Handle,
           &gEfiLoadPeImageGuid,
           EFI_NATIVE_INTERFACE,
           &mLoadPe32PrivateData.Pe32Image
           );
}


STATIC
EFI_STATUS
CoreLoadPeImage (
  IN VOID                        *Pe32Handle,           
  IN LOADED_IMAGE_PRIVATE_DATA   *Image,                
  IN EFI_PHYSICAL_ADDRESS        DstBuffer    OPTIONAL,
  OUT EFI_PHYSICAL_ADDRESS       *EntryPoint  OPTIONAL,
  IN  UINT32                     Attribute,
  IN  BOOLEAN                    CrossLoad
  )
/*++

Routine Description:

  Loads, relocates, and invokes a PE/COFF image.

Arguments:

  Pe32Handle       - The handle of PE32 image.
  Image            - PE image to be loaded.
  DstBuffer        - The buffer to store the image.
  EntryPoint       - A pointer to the entry point.
  Attribute        - The bit mask of attributes to set for the load PE image.
  CrossLoad        - Whether expect to support cross architecture loading.

Returns:

  EFI_SUCCESS             - The file was loaded, relocated, and invoked.
  EFI_OUT_OF_RESOURCES    - There was not enough memory to load and relocate the PE/COFF file.
  EFI_INVALID_PARAMETER   - Invalid parameter.
  EFI_BUFFER_TOO_SMALL    - Buffer for image is too small.

--*/
{
  EFI_STATUS      Status;
  BOOLEAN         DstBufAlocated;
  UINTN           Size;
  
  DEBUG_CODE (
    UINTN   Index;
    UINTN   StartIndex;
    CHAR8   EfiFileName[256];
  )
 
  EfiCommonLibZeroMem (&(Image->ImageContext), sizeof (Image->ImageContext));

  Image->ImageContext.Handle    = Pe32Handle;
  Image->ImageContext.ImageRead = (EFI_PEI_PE_COFF_LOADER_READ_FILE) CoreReadImageFile;

  //
  // Get information about the image being loaded.
  //
  Status = gEfiPeiPeCoffLoader->GetImageInfo (gEfiPeiPeCoffLoader, &(Image->ImageContext));
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Check the processor architecture of the image
  //
  if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine)) {
    if (CrossLoad) {
      if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image->ImageContext.Machine)) {
        return EFI_UNSUPPORTED;
      }
    } else {
      return EFI_UNSUPPORTED;
    }
  }

  //
  // Allocate memory of the correct memory type aligned on the required image boundary.
  //
  DstBufAlocated = FALSE;
  if (DstBuffer == 0) {
    //
    // Allocate Destination Buffer as caller did not pass it in.
    //

    if (Image->ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
      Size = (UINTN) Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment;
    } else {
      Size = (UINTN) Image->ImageContext.ImageSize;
    }

    Image->NumberOfPages = EFI_SIZE_TO_PAGES (Size);

    //
    // If the image relocations have not been stripped, then load at any address. 
    // Otherwise load at the address at which it was linked.
    //
    Status = CoreAllocatePages (
               AllocateAddress,
               Image->ImageContext.ImageCodeMemoryType,
               Image->NumberOfPages,
               &Image->ImageContext.ImageAddress
               );
    if (EFI_ERROR (Status) && !Image->ImageContext.RelocationsStripped)
      Status = CoreAllocatePages (
                 AllocateAnyPages,
                 Image->ImageContext.ImageCodeMemoryType,
                 Image->NumberOfPages,
                 &Image->ImageContext.ImageAddress
                 );
    if (EFI_ERROR (Status)) {
      return Status;
    }
    DstBufAlocated = TRUE;
  } else {
    //
    // Caller provided the destination buffer.
    //
    
    if (Image->ImageContext.RelocationsStripped && (Image->ImageContext.ImageAddress != DstBuffer)) {
      //
      // If the image relocations were stripped, and the caller provided a 
      // destination buffer address that does not match the address that the 
      // image is linked at, then the image cannot be loaded.
      //
      return EFI_INVALID_PARAMETER;
    }
    
    Size = EFI_SIZE_TO_PAGES ((UINTN) Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);
    
    if ((Image->NumberOfPages != 0) && (Image->NumberOfPages < Size)) {
      Image->NumberOfPages = Size;
      return EFI_BUFFER_TOO_SMALL;
    }

    Image->NumberOfPages = Size;
    Image->ImageContext.ImageAddress = DstBuffer;
  }
  
  Image->ImageBasePage = Image->ImageContext.ImageAddress;
  Image->ImageContext.ImageAddress = 
                        (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) & 
                        ~((UINTN) Image->ImageContext.SectionAlignment - 1);

  //
  // Load the image from the file into the allocated memory
  //
  Status = gEfiPeiPeCoffLoader->LoadImage (gEfiPeiPeCoffLoader, &(Image->ImageContext));
  if (EFI_ERROR (Status)) {
    goto Done;
  }
    
  //
  // If this is a Runtime Driver, then allocate memory for the FixupData that 
  // is used to relocate the image when SetVirtualAddressMap() is called. The 
  // relocation is done by the Runtime AP.
  //
  if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) {
    if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER &&
        EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine)) {
      Image->ImageContext.FixupData = CoreAllocateRuntimePool ((UINTN)(Image->ImageContext.FixupDataSize));
      if (Image->ImageContext.FixupData == NULL) {
        Status = EFI_OUT_OF_RESOURCES;
        goto Done;
      }
    }
  }

  //
  // Relocate the image in memory
  //
  Status = gEfiPeiPeCoffLoader->RelocateImage (gEfiPeiPeCoffLoader, &(Image->ImageContext));
  if (EFI_ERROR (Status)) {
    goto Done;
  }

  //
  // Flush the Instruction Cache
  //
  Status = CoreFlushICache (Image->ImageContext.ImageAddress, Image->ImageContext.ImageSize);
  if (EFI_ERROR (Status)) {
    goto Done;
  }

  //
  // Get the image entry point. If it's an EBC image, then call into the 
  // interpreter to create a thunk for the entry point and use the returned
  // value for the entry point. 
  //
  Image->EntryPoint   = (EFI_IMAGE_ENTRY_POINT) (UINTN) Image->ImageContext.EntryPoint;
  
  //
  // Copy the machine type from the context to the image private data. This
  // is needed during image unload to know if we should call an EBC protocol
  // to unload the image.
  //
  Image->Machine = Image->ImageContext.Machine;
  if (Image->ImageContext.Machine == EFI_IMAGE_MACHINE_EBC) {
    //
    // Locate the EBC interpreter protocol
    //
    Status = CoreLocateProtocol (&gEfiEbcProtocolGuid, NULL, &Image->Ebc);
    if (EFI_ERROR (Status)) {
      goto Done;
    }
   
    //
    // Register a callback for flushing the instruction cache so that created
    // thunks can be flushed.
    //
    Status = Image->Ebc->RegisterICacheFlush (Image->Ebc, CoreFlushICache);
    if (EFI_ERROR (Status)) {
      goto Done;
    }
    
    //
    // Create a thunk for the image's entry point. This will be the new
    // entry point for the image.
    //
    Status = Image->Ebc->CreateThunk ( 
                           Image->Ebc,      
                           Image->Handle, 
                           (VOID *)(UINTN)Image->ImageContext.EntryPoint, 
                           (VOID **)&Image->EntryPoint
                           );
    if (EFI_ERROR (Status)) {
      goto Done;
    }
  }

  //
  // Fill in the image information for the Loaded Image Protocol
  //
  Image->Type               = Image->ImageContext.ImageType;
  Image->Info.ImageBase     = (VOID *) (UINTN) Image->ImageContext.ImageAddress;
  Image->Info.ImageSize     = Image->ImageContext.ImageSize;
  Image->Info.ImageCodeType = Image->ImageContext.ImageCodeMemoryType;
  Image->Info.ImageDataType = Image->ImageContext.ImageDataMemoryType;
  
  if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) {
    if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
      //
      // Make a list off all the RT images so we can let the RT AP know about them.
      //
      Image->RuntimeData = CoreAllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY));
      if (Image->RuntimeData == NULL) {
        goto Done;
      }
      Image->RuntimeData->ImageBase      = Image->Info.ImageBase;
      Image->RuntimeData->ImageSize      = (UINT64) (Image->Info.ImageSize);
      Image->RuntimeData->RelocationData = Image->ImageContext.FixupData;
      Image->RuntimeData->Handle         = Image->Handle;
      InsertTailList (&gRuntime->ImageHead, &Image->RuntimeData->Link);
    }
  }
  
  //
  // Fill in the entry point of the image if it is available
  //
  if (EntryPoint != NULL) {
    *EntryPoint = Image->ImageContext.EntryPoint;
  }

  //
  // Print the load address and the PDB file name if it is available
  //

  DEBUG_CODE (
  {
    DEBUG ((
      EFI_D_INFO | EFI_D_LOAD, 
      "Loading driver at 0x%08x EntryPoint=0x%08x ", 
      (UINTN) Image->ImageContext.ImageAddress, 
      (UINTN) Image->ImageContext.EntryPoint
      ));
    if (Image->ImageContext.PdbPointer != NULL) {
      StartIndex = 0;
      for (Index = 0; Image->ImageContext.PdbPointer[Index] != 0; Index++) {
        if (Image->ImageContext.PdbPointer[Index] == '\\') {
          StartIndex = Index + 1;
        }
      }
      //
      // Copy the PDB file name to our temporary string, and replace .pdb with .efi
      //
      for (Index = 0; Index < sizeof (EfiFileName); Index++) {
        EfiFileName[Index] = Image->ImageContext.PdbPointer[Index + StartIndex];
        if (EfiFileName[Index] == 0) {
          EfiFileName[Index] = '.';
        }
        if (EfiFileName[Index] == '.') {
          EfiFileName[Index + 1] = 'e';
          EfiFileName[Index + 2] = 'f';
          EfiFileName[Index + 3] = 'i';
          EfiFileName[Index + 4] = 0;
          break;
        }
      }
      DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a", EfiFileName));
    }
    DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));
  }
  );

  return EFI_SUCCESS;

Done:

  //
  // Free memory.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -