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

📄 load.c

📁 Next BIOS Source code : Extensible Firmware Interface
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.


Module Name: load.c


Abstract:  PE32+ loader.


--*/

#include "loader.h"

#include EFI_PROTOCOL_DEFINITION(Ebc)

//
//
//

typedef struct _START_IMAGE {
    LOADED_IMAGE            *Image;
    EFI_TPL                 Tpl;
    EFI_STATUS              Status;
    UINTN                   ExitDataSize;
    VOID                    *ExitData;
    EFI_JUMP_BUFFER         Exit;
} START_IMAGE;

STATIC START_IMAGE          *CurrentStartImage;
STATIC EFI_HANDLE           EfiCoreImageHandle;


//
// Internal data
//

EFI_GUID InternalImageStructure = 
    { 0x280a011, 0x9ab0, 0x11d2, 0x8e, 0x40, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b };


//
// Prototypes 
//

STATIC
EFI_STATUS
LoadedImageProtocolHandler (
    IN VOID             *HandlerContext,
    IN EFI_GUID         *Protocol,
    OUT VOID            **ProtocolInterface
    );

VOID
UnloadImage (
    IN LOADED_IMAGE     *Image
    );


//
//
//

VOID
InitializeLoader (
    VOID
    )
{
	EfiCoreImageHandle = NULL;
    InitializeListHead (&BootImageList);
    InitializeListHead (&RuntimeImageList);
    InitializeLock (&ImageListLock, TPL_NOTIFY);
}


STATIC
LOADED_IMAGE *
LoadedImageInfo (
    IN EFI_HANDLE       ImageHandle
    )
{
    LOADED_IMAGE        *Image;
    EFI_STATUS          Status;

    Status = BS->HandleProtocol (
                    ImageHandle,
                    &InternalImageStructure,
                    &Image
                    );

    if (EFI_ERROR(Status)) {
        DEBUG ((D_LOAD, "LoadedImageInfo: Not an ImageHandle %x\n", ImageHandle));
        Image = NULL;
    }

    return Image;
}

INTERNAL
EFI_STATUS
SetImageType (
    IN OUT LOADED_IMAGE             *Image,
    IN UINTN                        ImageType
    )
{
    EFI_MEMORY_TYPE                 CodeType, DataType;

    switch (ImageType) {
    case IMAGE_SUBSYSTEM_EFI_APPLICATION:
        CodeType = EfiLoaderCode;
        DataType = EfiLoaderData;
        break;

    case IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
        CodeType = EfiBootServicesCode;
        DataType = EfiBootServicesData;
        break;

    case IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
        CodeType = EfiRuntimeServicesCode;
        DataType = EfiRuntimeServicesData;
        break;
    default:
        return EFI_INVALID_PARAMETER;
    }

    Image->Type = ImageType;
    Image->Info.ImageCodeType = CodeType;    
    Image->Info.ImageDataType = DataType;
    return EFI_SUCCESS;
}

INTERNAL
EFI_STATUS
CheckImageMachineType (
    IN UINTN            MachineType
    )
// Determine if machine type is supported by the local machine
{
    EFI_STATUS          Status;

    Status = EFI_UNSUPPORTED;

#if EFI32
    if (MachineType == EFI_IMAGE_MACHINE_IA32) {
        Status = EFI_SUCCESS;
    }
#endif
    
#if EFI64
    if (MachineType == EFI_IMAGE_MACHINE_IA64) {
        Status = EFI_SUCCESS;
    }
#endif

    if (MachineType == EFI_IMAGE_MACHINE_EBC) {
        Status = EFI_SUCCESS;
    }

    return Status;
}


//
//
//

EFI_STATUS
FwLoadInternal (
    IN UINTN                        ImageType,    
    IN CHAR16                       *InternalName,
    IN EFI_IMAGE_ENTRY_POINT        ImageEntryPoint OPTIONAL
    )
{
    LOADED_IMAGE                    *Image;
    EFI_STATUS                      Status;

    //
    // Allocate a new image structure
    //

    Image = AllocateZeroPool(sizeof(LOADED_IMAGE));
    if (!Image) {
        return EFI_OUT_OF_RESOURCES;
    }

    //
    // Initialize image info fields
    //

    Image->Signature = LOADED_IMAGE_SIGNATURE;
    Image->Info.Revision = EFI_LOADED_IMAGE_INFORMATION_REVISION;
    Image->Info.SystemTable = ST;
    Image->Info.FilePath = FileDevicePath (NULL, InternalName);
	Image->Info.ParentHandle = EfiCoreImageHandle;
    Image->Name = DevicePathToStr(Image->Info.FilePath);    // for debugging
    Image->EntryPoint = ImageEntryPoint;
    SetImageType (Image, ImageType);

    //
    // If there's an entry point then this image is directly
    // linked in; otherwise, it's being emulated as a linked
    // together driver.   This is only done on builds that
    // have EmulateLoad
    //

    if (!ImageEntryPoint) {

        //
        // Call the emulator to load the internal image
        //

        ASSERT (PL->EmulateLoad);
        Status = PL->EmulateLoad (
                        InternalName, 
                        &Image->Info,
                        &Image->EntryPoint
                        );

        //
        // If ther was an error, clean up and exit
        //

        if (EFI_ERROR(Status)) {
            UnloadImage (Image);
            goto Done;
        }
    }

    //
    // Install the protocol interfaces for the image
    //

    Status = LibInstallProtocolInterfaces (
                &Image->Handle, 
                &LoadedImageProtocol,       &Image->Info,    
                &InternalImageStructure,    Image,
                NULL
                );

    ASSERT (!EFI_ERROR(Status));

    //
    // Start the image
    //
    
    Status = StartImage (Image->Handle, 0, NULL);

Done:
    return Status;
}

EFI_STATUS
BuildEfiCoreImageHandle (
  IN  VOID                 *EntryPoint,
  IN  VOID                 *BaseAddress,
  IN  UINT64               Size,
  OUT EFI_HANDLE           *CoreImageHandle
  )

{
  EFI_STATUS                  Status;
  LOADED_IMAGE                *Image;

  *CoreImageHandle = NULL;

  Image = AllocateZeroPool(sizeof(LOADED_IMAGE));
  if (Image == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  //
  // Initialize the fields for an internal driver
  //
  Image->Signature     = LOADED_IMAGE_SIGNATURE;
  Image->Info.Revision = EFI_LOADED_IMAGE_INFORMATION_REVISION;
  Image->Type          = IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;
  Image->Started       = TRUE;
  Image->EntryPoint    = (EFI_IMAGE_ENTRY_POINT)(UINTN)EntryPoint;
  Image->ImageBasePage = (EFI_PHYSICAL_ADDRESS)BaseAddress;
  Image->NumberOfPages = EFI_SIZE_TO_PAGES((UINT32)Size);

  Image->Info.SystemTable = ST;
  Image->Info.DeviceHandle = NULL;

  Image->Info.FilePath        = FileDevicePath(NULL, L"EFI Core");

  Image->Info.ParentHandle    = NULL;
  Image->Info.SystemTable     = ST;

  Image->Info.ImageBase       = BaseAddress;
  Image->Info.ImageSize       = Size;
  Image->Info.ImageCodeType   = EfiBootServicesCode;
  Image->Info.ImageDataType   = EfiBootServicesData;

  //
  // Install the protocol interfaces for this image
  //
  Status = LibInstallProtocolInterfaces (
              &Image->Handle, 
              &LoadedImageProtocol,       &Image->Info,    
              &InternalImageStructure,    Image,
              NULL
              );

  if (EFI_ERROR (Status)) {
    return Status;
  }

  *CoreImageHandle   = Image->Handle;
  EfiCoreImageHandle = Image->Handle;

  //
  // Add new image handle to debug image info table
  // This step is optional and not required by architecture.  It is
  // used by debuggers to determine image information
  //
  
  NewDebugImageInfoEntry (
    EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, 
    (EFI_LOADED_IMAGE_PROTOCOL *) &Image->Info, 
    Image->Handle
    );

  return EFI_SUCCESS;
}

EFI_STATUS
LoadImage (
    IN BOOLEAN                  BootPolicy,
    IN EFI_HANDLE               ParentImageHandle,
    IN EFI_DEVICE_PATH          *FilePath,
    IN VOID                     *SourceBuffer   OPTIONAL,
    IN UINTN                    SourceSize,
    OUT EFI_HANDLE              *ImageHandle
    )
{
    LOADED_IMAGE                *Image, *ParentImage;
    LOADED_IMAGE                *RuntimeImage;
    SIMPLE_READ_FILE            FHand;
    EFI_STATUS                  Status;
    EFI_HANDLE                  DeviceHandle;

    ASSERT (CurrentTPL() < TPL_NOTIFY);
    ParentImage = NULL;

    //
    // The caller must always pass in a valid ImageHandle and ParentImageHandle
    //
    if (ImageHandle == NULL || ParentImageHandle == NULL) {
        return EFI_INVALID_PARAMETER;
    }

    //
    // If there's a parent image handle, look it up
    //
    ParentImage = LoadedImageInfo(ParentImageHandle);
    if (!ParentImage) {
        DEBUG((D_LOAD|D_ERROR, "LoadImage: Parent handle not an image handle\n"));
        return EFI_INVALID_PARAMETER;
    }

    //
    // If SourceBuffer is NULL, then FilePath must be valid
    //
    if (SourceBuffer == NULL && FilePath == NULL) {
      return EFI_INVALID_PARAMETER;
    }

    //
    // Get simple read access to the source file
    //
    Status = OpenSimpleReadFile (
                BootPolicy,
                SourceBuffer, 
                SourceSize,
                &FilePath,
                &DeviceHandle,
                &FHand
                );

    if (Status == EFI_ALREADY_STARTED) {
        Image = NULL;
        goto Done;
    } else if (EFI_ERROR(Status)) {
        return Status;
    }

    //
    // Allocate a new image structure
    //
    Image = AllocateZeroPool(sizeof(LOADED_IMAGE));
    if (!Image) {
        return EFI_OUT_OF_RESOURCES;
    }

    //
    // Initialize the fields for an internal driver
    //
    Image->Signature = LOADED_IMAGE_SIGNATURE;
    Image->Info.Revision = EFI_LOADED_IMAGE_INFORMATION_REVISION;
    Image->Info.SystemTable = ST;
    Image->Info.DeviceHandle = DeviceHandle;

    Image->Info.FilePath = DuplicateDevicePath (FilePath);
    Image->Name = DevicePathToStr(Image->Info.FilePath);

    if (ParentImage) {
        Image->Info.ParentHandle = ParentImageHandle;
        Image->Info.SystemTable = ParentImage->Info.SystemTable;
    }

    //
    // Load Pe image types
    //
    Status = LoadPeImage (FHand, Image);

    if (EFI_ERROR(Status)) {
        goto Done;
    }

    //
    // If the image was sucessfully loaded, and it's a runtime image 
    // move its loaded_image structure to runtime memory
    //
    AcquireLock (&ImageListLock);

    if (Image->Type == IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {

        // Allocate a new buffer
        Status = BSAllocatePool (EfiRuntimeServicesData, sizeof(LOADED_IMAGE), &RuntimeImage);
        if (EFI_ERROR(Status)) {
            goto Done;
        }

        // Move the buffer to the runtime copy, and free the non-runtime buffer        
        CopyMem (RuntimeImage, Image, sizeof(LOADED_IMAGE));
        FreePool (Image);
        Image = RuntimeImage;

        // Keep track of all the runtime driver images
        InsertTailList (&RuntimeImageList, &Image->ImageLink);

    } else {

        //
        // Image is not a runtime driver.. If there's a fixup table free it
        //

        if (Image->FixupData) {
           FreePool (Image->FixupData);
           Image->FixupData = NULL;
        }
    }

    //
    // If the image is a boot service driver keep it in a list
    //

    if (Image->Type == IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) {
        InsertTailList (&BootImageList, &Image->ImageLink);
    }

    ReleaseLock (&ImageListLock);

    //
    // Install the protocol interfaces for this image
    //
    Status = LibInstallProtocolInterfaces (
                &Image->Handle, 
                &LoadedImageProtocol,       &Image->Info,    
                &InternalImageStructure,    Image,
                NULL
                );

    if (EFI_ERROR(Status)) {
        goto Done;
    }

    //
    // Success.  Return the image handle
    // 

    *ImageHandle = Image->Handle;

    //
    // Add new image handle to debug image info table
    // This step is optional and not required by architecture.  It is
    // used by debuggers to determine image information
    //
    
    NewDebugImageInfoEntry (
      EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, 
      (EFI_LOADED_IMAGE_PROTOCOL *) &Image->Info, 
      Image->Handle
      );

Done:
    //
    // All done accessing the source file

⌨️ 快捷键说明

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