Home | History | Annotate | Download | only in Image
      1 /** @file
      2   Core image handling services to load and unload PeImage.
      3 
      4 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "DxeMain.h"
     16 #include "Image.h"
     17 
     18 //
     19 // Module Globals
     20 //
     21 LOADED_IMAGE_PRIVATE_DATA  *mCurrentImage = NULL;
     22 
     23 LOAD_PE32_IMAGE_PRIVATE_DATA  mLoadPe32PrivateData = {
     24   LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE,
     25   NULL,
     26   {
     27     CoreLoadImageEx,
     28     CoreUnloadImageEx
     29   }
     30 };
     31 
     32 
     33 //
     34 // This code is needed to build the Image handle for the DXE Core
     35 //
     36 LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage  = {
     37   LOADED_IMAGE_PRIVATE_DATA_SIGNATURE,            // Signature
     38   NULL,                                           // Image handle
     39   EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,    // Image type
     40   TRUE,                                           // If entrypoint has been called
     41   NULL, // EntryPoint
     42   {
     43     EFI_LOADED_IMAGE_INFORMATION_REVISION,        // Revision
     44     NULL,                                         // Parent handle
     45     NULL,                                         // System handle
     46 
     47     NULL,                                         // Device handle
     48     NULL,                                         // File path
     49     NULL,                                         // Reserved
     50 
     51     0,                                            // LoadOptionsSize
     52     NULL,                                         // LoadOptions
     53 
     54     NULL,                                         // ImageBase
     55     0,                                            // ImageSize
     56     EfiBootServicesCode,                          // ImageCodeType
     57     EfiBootServicesData                           // ImageDataType
     58   },
     59   (EFI_PHYSICAL_ADDRESS)0,    // ImageBasePage
     60   0,                          // NumberOfPages
     61   NULL,                       // FixupData
     62   0,                          // Tpl
     63   EFI_SUCCESS,                // Status
     64   0,                          // ExitDataSize
     65   NULL,                       // ExitData
     66   NULL,                       // JumpBuffer
     67   NULL,                       // JumpContext
     68   0,                          // Machine
     69   NULL,                       // Ebc
     70   NULL,                       // RuntimeData
     71   NULL                        // LoadedImageDevicePath
     72 };
     73 //
     74 // The field is define for Loading modules at fixed address feature to tracker the PEI code
     75 // memory range usage. It is a bit mapped array in which every bit indicates the correspoding memory page
     76 // available or not.
     77 //
     78 GLOBAL_REMOVE_IF_UNREFERENCED    UINT64                *mDxeCodeMemoryRangeUsageBitMap=NULL;
     79 
     80 typedef struct {
     81   UINT16  MachineType;
     82   CHAR16  *MachineTypeName;
     83 } MACHINE_TYPE_INFO;
     84 
     85 //
     86 // EBC machine is not listed in this table, because EBC is in the default supported scopes of other machine type.
     87 //
     88 GLOBAL_REMOVE_IF_UNREFERENCED MACHINE_TYPE_INFO  mMachineTypeInfo[] = {
     89   {EFI_IMAGE_MACHINE_IA32,           L"IA32"},
     90   {EFI_IMAGE_MACHINE_IA64,           L"IA64"},
     91   {EFI_IMAGE_MACHINE_X64,            L"X64"},
     92   {EFI_IMAGE_MACHINE_ARMTHUMB_MIXED, L"ARM"}
     93 };
     94 
     95 UINT16 mDxeCoreImageMachineType = 0;
     96 
     97 /**
     98  Return machine type name.
     99 
    100  @param MachineType The machine type
    101 
    102  @return machine type name
    103 **/
    104 CHAR16 *
    105 GetMachineTypeName (
    106   UINT16 MachineType
    107   )
    108 {
    109   UINTN  Index;
    110 
    111   for (Index = 0; Index < sizeof(mMachineTypeInfo)/sizeof(mMachineTypeInfo[0]); Index++) {
    112     if (mMachineTypeInfo[Index].MachineType == MachineType) {
    113       return mMachineTypeInfo[Index].MachineTypeName;
    114     }
    115   }
    116 
    117   return L"<Unknown>";
    118 }
    119 
    120 /**
    121   Add the Image Services to EFI Boot Services Table and install the protocol
    122   interfaces for this image.
    123 
    124   @param  HobStart                The HOB to initialize
    125 
    126   @return Status code.
    127 
    128 **/
    129 EFI_STATUS
    130 CoreInitializeImageServices (
    131   IN  VOID *HobStart
    132   )
    133 {
    134   EFI_STATUS                        Status;
    135   LOADED_IMAGE_PRIVATE_DATA         *Image;
    136   EFI_PHYSICAL_ADDRESS              DxeCoreImageBaseAddress;
    137   UINT64                            DxeCoreImageLength;
    138   VOID                              *DxeCoreEntryPoint;
    139   EFI_PEI_HOB_POINTERS              DxeCoreHob;
    140 
    141   //
    142   // Searching for image hob
    143   //
    144   DxeCoreHob.Raw          = HobStart;
    145   while ((DxeCoreHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, DxeCoreHob.Raw)) != NULL) {
    146     if (CompareGuid (&DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) {
    147       //
    148       // Find Dxe Core HOB
    149       //
    150       break;
    151     }
    152     DxeCoreHob.Raw = GET_NEXT_HOB (DxeCoreHob);
    153   }
    154   ASSERT (DxeCoreHob.Raw != NULL);
    155 
    156   DxeCoreImageBaseAddress = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress;
    157   DxeCoreImageLength      = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength;
    158   DxeCoreEntryPoint       = (VOID *) (UINTN) DxeCoreHob.MemoryAllocationModule->EntryPoint;
    159   gDxeCoreFileName        = &DxeCoreHob.MemoryAllocationModule->ModuleName;
    160 
    161   //
    162   // Initialize the fields for an internal driver
    163   //
    164   Image = &mCorePrivateImage;
    165 
    166   Image->EntryPoint         = (EFI_IMAGE_ENTRY_POINT)(UINTN)DxeCoreEntryPoint;
    167   Image->ImageBasePage      = DxeCoreImageBaseAddress;
    168   Image->NumberOfPages      = (UINTN)(EFI_SIZE_TO_PAGES((UINTN)(DxeCoreImageLength)));
    169   Image->Tpl                = gEfiCurrentTpl;
    170   Image->Info.SystemTable   = gDxeCoreST;
    171   Image->Info.ImageBase     = (VOID *)(UINTN)DxeCoreImageBaseAddress;
    172   Image->Info.ImageSize     = DxeCoreImageLength;
    173 
    174   //
    175   // Install the protocol interfaces for this image
    176   //
    177   Status = CoreInstallProtocolInterface (
    178              &Image->Handle,
    179              &gEfiLoadedImageProtocolGuid,
    180              EFI_NATIVE_INTERFACE,
    181              &Image->Info
    182              );
    183   ASSERT_EFI_ERROR (Status);
    184 
    185   mCurrentImage = Image;
    186 
    187   //
    188   // Fill in DXE globals
    189   //
    190   mDxeCoreImageMachineType = PeCoffLoaderGetMachineType (Image->Info.ImageBase);
    191   gDxeCoreImageHandle = Image->Handle;
    192   gDxeCoreLoadedImage = &Image->Info;
    193 
    194   if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
    195     //
    196     // Export DXE Core PE Loader functionality for backward compatibility.
    197     //
    198     Status = CoreInstallProtocolInterface (
    199                &mLoadPe32PrivateData.Handle,
    200                &gEfiLoadPeImageProtocolGuid,
    201                EFI_NATIVE_INTERFACE,
    202                &mLoadPe32PrivateData.Pe32Image
    203                );
    204   }
    205 
    206   return Status;
    207 }
    208 
    209 /**
    210   Read image file (specified by UserHandle) into user specified buffer with specified offset
    211   and length.
    212 
    213   @param  UserHandle             Image file handle
    214   @param  Offset                 Offset to the source file
    215   @param  ReadSize               For input, pointer of size to read; For output,
    216                                  pointer of size actually read.
    217   @param  Buffer                 Buffer to write into
    218 
    219   @retval EFI_SUCCESS            Successfully read the specified part of file
    220                                  into buffer.
    221 
    222 **/
    223 EFI_STATUS
    224 EFIAPI
    225 CoreReadImageFile (
    226   IN     VOID    *UserHandle,
    227   IN     UINTN   Offset,
    228   IN OUT UINTN   *ReadSize,
    229   OUT    VOID    *Buffer
    230   )
    231 {
    232   UINTN               EndPosition;
    233   IMAGE_FILE_HANDLE  *FHand;
    234 
    235   if (UserHandle == NULL || ReadSize == NULL || Buffer == NULL) {
    236     return EFI_INVALID_PARAMETER;
    237   }
    238 
    239   if (MAX_ADDRESS - Offset < *ReadSize) {
    240     return EFI_INVALID_PARAMETER;
    241   }
    242 
    243   FHand = (IMAGE_FILE_HANDLE  *)UserHandle;
    244   ASSERT (FHand->Signature == IMAGE_FILE_HANDLE_SIGNATURE);
    245 
    246   //
    247   // Move data from our local copy of the file
    248   //
    249   EndPosition = Offset + *ReadSize;
    250   if (EndPosition > FHand->SourceSize) {
    251     *ReadSize = (UINT32)(FHand->SourceSize - Offset);
    252   }
    253   if (Offset >= FHand->SourceSize) {
    254       *ReadSize = 0;
    255   }
    256 
    257   CopyMem (Buffer, (CHAR8 *)FHand->Source + Offset, *ReadSize);
    258   return EFI_SUCCESS;
    259 }
    260 /**
    261   To check memory usage bit map arry to figure out if the memory range the image will be loaded in is available or not. If
    262   memory range is avaliable, the function will mark the correponding bits to 1 which indicates the memory range is used.
    263   The function is only invoked when load modules at fixed address feature is enabled.
    264 
    265   @param  ImageBase                The base addres the image will be loaded at.
    266   @param  ImageSize                The size of the image
    267 
    268   @retval EFI_SUCCESS              The memory range the image will be loaded in is available
    269   @retval EFI_NOT_FOUND            The memory range the image will be loaded in is not available
    270 **/
    271 EFI_STATUS
    272 CheckAndMarkFixLoadingMemoryUsageBitMap (
    273   IN  EFI_PHYSICAL_ADDRESS          ImageBase,
    274   IN  UINTN                         ImageSize
    275   )
    276 {
    277    UINT32                             DxeCodePageNumber;
    278    UINT64                             DxeCodeSize;
    279    EFI_PHYSICAL_ADDRESS               DxeCodeBase;
    280    UINTN                              BaseOffsetPageNumber;
    281    UINTN                              TopOffsetPageNumber;
    282    UINTN                              Index;
    283    //
    284    // The DXE code range includes RuntimeCodePage range and Boot time code range.
    285    //
    286    DxeCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);
    287    DxeCodePageNumber += PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);
    288    DxeCodeSize       = EFI_PAGES_TO_SIZE(DxeCodePageNumber);
    289    DxeCodeBase       =  gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress - DxeCodeSize;
    290 
    291    //
    292    // If the memory usage bit map is not initialized,  do it. Every bit in the array
    293    // indicate the status of the corresponding memory page, available or not
    294    //
    295    if (mDxeCodeMemoryRangeUsageBitMap == NULL) {
    296      mDxeCodeMemoryRangeUsageBitMap = AllocateZeroPool(((DxeCodePageNumber/64) + 1)*sizeof(UINT64));
    297    }
    298    //
    299    // If the Dxe code memory range is not allocated or the bit map array allocation failed, return EFI_NOT_FOUND
    300    //
    301    if (!gLoadFixedAddressCodeMemoryReady || mDxeCodeMemoryRangeUsageBitMap == NULL) {
    302      return EFI_NOT_FOUND;
    303    }
    304    //
    305    // Test the memory range for loading the image in the DXE code range.
    306    //
    307    if (gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress <  ImageBase + ImageSize ||
    308        DxeCodeBase >  ImageBase) {
    309      return EFI_NOT_FOUND;
    310    }
    311    //
    312    // Test if the memory is avalaible or not.
    313    //
    314    BaseOffsetPageNumber = (UINTN)EFI_SIZE_TO_PAGES((UINT32)(ImageBase - DxeCodeBase));
    315    TopOffsetPageNumber  = (UINTN)EFI_SIZE_TO_PAGES((UINT32)(ImageBase + ImageSize - DxeCodeBase));
    316    for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {
    317      if ((mDxeCodeMemoryRangeUsageBitMap[Index / 64] & LShiftU64(1, (Index % 64))) != 0) {
    318        //
    319        // This page is already used.
    320        //
    321        return EFI_NOT_FOUND;
    322      }
    323    }
    324 
    325    //
    326    // Being here means the memory range is available.  So mark the bits for the memory range
    327    //
    328    for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {
    329      mDxeCodeMemoryRangeUsageBitMap[Index / 64] |= LShiftU64(1, (Index % 64));
    330    }
    331    return  EFI_SUCCESS;
    332 }
    333 /**
    334 
    335   Get the fixed loadding address from image header assigned by build tool. This function only be called
    336   when Loading module at Fixed address feature enabled.
    337 
    338   @param  ImageContext              Pointer to the image context structure that describes the PE/COFF
    339                                     image that needs to be examined by this function.
    340   @retval EFI_SUCCESS               An fixed loading address is assigned to this image by build tools .
    341   @retval EFI_NOT_FOUND             The image has no assigned fixed loadding address.
    342 
    343 **/
    344 EFI_STATUS
    345 GetPeCoffImageFixLoadingAssignedAddress(
    346   IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
    347   )
    348 {
    349    UINTN                              SectionHeaderOffset;
    350    EFI_STATUS                         Status;
    351    EFI_IMAGE_SECTION_HEADER           SectionHeader;
    352    EFI_IMAGE_OPTIONAL_HEADER_UNION    *ImgHdr;
    353    UINT16                             Index;
    354    UINTN                              Size;
    355    UINT16                             NumberOfSections;
    356    IMAGE_FILE_HANDLE                  *Handle;
    357    UINT64                             ValueInSectionHeader;
    358 
    359 
    360    Status = EFI_NOT_FOUND;
    361 
    362    //
    363    // Get PeHeader pointer
    364    //
    365    Handle = (IMAGE_FILE_HANDLE*)ImageContext->Handle;
    366    ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )Handle->Source + ImageContext->PeCoffHeaderOffset);
    367    SectionHeaderOffset = (UINTN)(
    368                                  ImageContext->PeCoffHeaderOffset +
    369                                  sizeof (UINT32) +
    370                                  sizeof (EFI_IMAGE_FILE_HEADER) +
    371                                  ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
    372                                  );
    373    NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;
    374 
    375    //
    376    // Get base address from the first section header that doesn't point to code section.
    377    //
    378    for (Index = 0; Index < NumberOfSections; Index++) {
    379      //
    380      // Read section header from file
    381      //
    382      Size = sizeof (EFI_IMAGE_SECTION_HEADER);
    383      Status = ImageContext->ImageRead (
    384                               ImageContext->Handle,
    385                               SectionHeaderOffset,
    386                               &Size,
    387                               &SectionHeader
    388                               );
    389      if (EFI_ERROR (Status)) {
    390        return Status;
    391      }
    392      if (Size != sizeof (EFI_IMAGE_SECTION_HEADER)) {
    393        return EFI_NOT_FOUND;
    394      }
    395 
    396      Status = EFI_NOT_FOUND;
    397 
    398      if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {
    399        //
    400        // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header
    401        // that doesn't point to code section in image header, as well as ImageBase field of image header. And there is an
    402        // assumption that when the feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations
    403        // & PointerToLineNumbers fields should NOT be Zero, or else, these 2 fileds should be set to Zero
    404        //
    405        ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations);
    406        if (ValueInSectionHeader != 0) {
    407          //
    408          // When the feature is configured as load module at fixed absolute address, the ImageAddress field of ImageContext
    409          // hold the spcified address. If the feature is configured as load module at fixed offset, ImageAddress hold an offset
    410          // relative to top address
    411          //
    412          if ((INT64)PcdGet64(PcdLoadModuleAtFixAddressEnable) < 0) {
    413          	 ImageContext->ImageAddress = gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress + (INT64)(INTN)ImageContext->ImageAddress;
    414          }
    415          //
    416          // Check if the memory range is avaliable.
    417          //
    418          Status = CheckAndMarkFixLoadingMemoryUsageBitMap (ImageContext->ImageAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment));
    419        }
    420        break;
    421      }
    422      SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
    423    }
    424    DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address 0x%11p. Status = %r \n", (VOID *)(UINTN)(ImageContext->ImageAddress), Status));
    425    return Status;
    426 }
    427 /**
    428   Loads, relocates, and invokes a PE/COFF image
    429 
    430   @param  BootPolicy              If TRUE, indicates that the request originates
    431                                   from the boot manager, and that the boot
    432                                   manager is attempting to load FilePath as a
    433                                   boot selection.
    434   @param  Pe32Handle              The handle of PE32 image
    435   @param  Image                   PE image to be loaded
    436   @param  DstBuffer               The buffer to store the image
    437   @param  EntryPoint              A pointer to the entry point
    438   @param  Attribute               The bit mask of attributes to set for the load
    439                                   PE image
    440 
    441   @retval EFI_SUCCESS             The file was loaded, relocated, and invoked
    442   @retval EFI_OUT_OF_RESOURCES    There was not enough memory to load and
    443                                   relocate the PE/COFF file
    444   @retval EFI_INVALID_PARAMETER   Invalid parameter
    445   @retval EFI_BUFFER_TOO_SMALL    Buffer for image is too small
    446 
    447 **/
    448 EFI_STATUS
    449 CoreLoadPeImage (
    450   IN BOOLEAN                     BootPolicy,
    451   IN VOID                        *Pe32Handle,
    452   IN LOADED_IMAGE_PRIVATE_DATA   *Image,
    453   IN EFI_PHYSICAL_ADDRESS        DstBuffer    OPTIONAL,
    454   OUT EFI_PHYSICAL_ADDRESS       *EntryPoint  OPTIONAL,
    455   IN  UINT32                     Attribute
    456   )
    457 {
    458   EFI_STATUS                Status;
    459   BOOLEAN                   DstBufAlocated;
    460   UINTN                     Size;
    461 
    462   ZeroMem (&Image->ImageContext, sizeof (Image->ImageContext));
    463 
    464   Image->ImageContext.Handle    = Pe32Handle;
    465   Image->ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)CoreReadImageFile;
    466 
    467   //
    468   // Get information about the image being loaded
    469   //
    470   Status = PeCoffLoaderGetImageInfo (&Image->ImageContext);
    471   if (EFI_ERROR (Status)) {
    472     return Status;
    473   }
    474 
    475   if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine)) {
    476     if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image->ImageContext.Machine)) {
    477       //
    478       // The PE/COFF loader can support loading image types that can be executed.
    479       // If we loaded an image type that we can not execute return EFI_UNSUPORTED.
    480       //
    481       DEBUG ((EFI_D_ERROR, "Image type %s can't be loaded ", GetMachineTypeName(Image->ImageContext.Machine)));
    482       DEBUG ((EFI_D_ERROR, "on %s UEFI system.\n", GetMachineTypeName(mDxeCoreImageMachineType)));
    483       return EFI_UNSUPPORTED;
    484     }
    485   }
    486 
    487   //
    488   // Set EFI memory type based on ImageType
    489   //
    490   switch (Image->ImageContext.ImageType) {
    491   case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:
    492     Image->ImageContext.ImageCodeMemoryType = EfiLoaderCode;
    493     Image->ImageContext.ImageDataMemoryType = EfiLoaderData;
    494     break;
    495   case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
    496     Image->ImageContext.ImageCodeMemoryType = EfiBootServicesCode;
    497     Image->ImageContext.ImageDataMemoryType = EfiBootServicesData;
    498     break;
    499   case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
    500   case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER:
    501     Image->ImageContext.ImageCodeMemoryType = EfiRuntimeServicesCode;
    502     Image->ImageContext.ImageDataMemoryType = EfiRuntimeServicesData;
    503     break;
    504   default:
    505     Image->ImageContext.ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM;
    506     return EFI_UNSUPPORTED;
    507   }
    508 
    509   //
    510   // Allocate memory of the correct memory type aligned on the required image boundry
    511   //
    512   DstBufAlocated = FALSE;
    513   if (DstBuffer == 0) {
    514     //
    515     // Allocate Destination Buffer as caller did not pass it in
    516     //
    517 
    518     if (Image->ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
    519       Size = (UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment;
    520     } else {
    521       Size = (UINTN)Image->ImageContext.ImageSize;
    522     }
    523 
    524     Image->NumberOfPages = EFI_SIZE_TO_PAGES (Size);
    525 
    526     //
    527     // If the image relocations have not been stripped, then load at any address.
    528     // Otherwise load at the address at which it was linked.
    529     //
    530     // Memory below 1MB should be treated reserved for CSM and there should be
    531     // no modules whose preferred load addresses are below 1MB.
    532     //
    533     Status = EFI_OUT_OF_RESOURCES;
    534     //
    535     // If Loading Module At Fixed Address feature is enabled, the module should be loaded to
    536     // a specified address.
    537     //
    538     if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 ) {
    539       Status = GetPeCoffImageFixLoadingAssignedAddress (&(Image->ImageContext));
    540 
    541       if (EFI_ERROR (Status))  {
    542           //
    543       	  // If the code memory is not ready, invoke CoreAllocatePage with AllocateAnyPages to load the driver.
    544       	  //
    545           DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED ERROR: Loading module at fixed address failed since specified memory is not available.\n"));
    546 
    547           Status = CoreAllocatePages (
    548                      AllocateAnyPages,
    549                      (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),
    550                      Image->NumberOfPages,
    551                      &Image->ImageContext.ImageAddress
    552                      );
    553       }
    554     } else {
    555       if (Image->ImageContext.ImageAddress >= 0x100000 || Image->ImageContext.RelocationsStripped) {
    556         Status = CoreAllocatePages (
    557                    AllocateAddress,
    558                    (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),
    559                    Image->NumberOfPages,
    560                    &Image->ImageContext.ImageAddress
    561                    );
    562       }
    563       if (EFI_ERROR (Status) && !Image->ImageContext.RelocationsStripped) {
    564         Status = CoreAllocatePages (
    565                    AllocateAnyPages,
    566                    (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),
    567                    Image->NumberOfPages,
    568                    &Image->ImageContext.ImageAddress
    569                    );
    570       }
    571     }
    572     if (EFI_ERROR (Status)) {
    573       return Status;
    574     }
    575     DstBufAlocated = TRUE;
    576   } else {
    577     //
    578     // Caller provided the destination buffer
    579     //
    580 
    581     if (Image->ImageContext.RelocationsStripped && (Image->ImageContext.ImageAddress != DstBuffer)) {
    582       //
    583       // If the image relocations were stripped, and the caller provided a
    584       // destination buffer address that does not match the address that the
    585       // image is linked at, then the image cannot be loaded.
    586       //
    587       return EFI_INVALID_PARAMETER;
    588     }
    589 
    590     if (Image->NumberOfPages != 0 &&
    591         Image->NumberOfPages <
    592         (EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment))) {
    593       Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);
    594       return EFI_BUFFER_TOO_SMALL;
    595     }
    596 
    597     Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);
    598     Image->ImageContext.ImageAddress = DstBuffer;
    599   }
    600 
    601   Image->ImageBasePage = Image->ImageContext.ImageAddress;
    602   if (!Image->ImageContext.IsTeImage) {
    603     Image->ImageContext.ImageAddress =
    604         (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &
    605         ~((UINTN)Image->ImageContext.SectionAlignment - 1);
    606   }
    607 
    608   //
    609   // Load the image from the file into the allocated memory
    610   //
    611   Status = PeCoffLoaderLoadImage (&Image->ImageContext);
    612   if (EFI_ERROR (Status)) {
    613     goto Done;
    614   }
    615 
    616   //
    617   // If this is a Runtime Driver, then allocate memory for the FixupData that
    618   // is used to relocate the image when SetVirtualAddressMap() is called. The
    619   // relocation is done by the Runtime AP.
    620   //
    621   if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) != 0) {
    622     if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
    623       Image->ImageContext.FixupData = AllocateRuntimePool ((UINTN)(Image->ImageContext.FixupDataSize));
    624       if (Image->ImageContext.FixupData == NULL) {
    625         Status = EFI_OUT_OF_RESOURCES;
    626         goto Done;
    627       }
    628     }
    629   }
    630 
    631   //
    632   // Relocate the image in memory
    633   //
    634   Status = PeCoffLoaderRelocateImage (&Image->ImageContext);
    635   if (EFI_ERROR (Status)) {
    636     goto Done;
    637   }
    638 
    639   //
    640   // Flush the Instruction Cache
    641   //
    642   InvalidateInstructionCacheRange ((VOID *)(UINTN)Image->ImageContext.ImageAddress, (UINTN)Image->ImageContext.ImageSize);
    643 
    644   //
    645   // Copy the machine type from the context to the image private data. This
    646   // is needed during image unload to know if we should call an EBC protocol
    647   // to unload the image.
    648   //
    649   Image->Machine = Image->ImageContext.Machine;
    650 
    651   //
    652   // Get the image entry point. If it's an EBC image, then call into the
    653   // interpreter to create a thunk for the entry point and use the returned
    654   // value for the entry point.
    655   //
    656   Image->EntryPoint   = (EFI_IMAGE_ENTRY_POINT)(UINTN)Image->ImageContext.EntryPoint;
    657   if (Image->ImageContext.Machine == EFI_IMAGE_MACHINE_EBC) {
    658     //
    659     // Locate the EBC interpreter protocol
    660     //
    661     Status = CoreLocateProtocol (&gEfiEbcProtocolGuid, NULL, (VOID **)&Image->Ebc);
    662     if (EFI_ERROR(Status) || Image->Ebc == NULL) {
    663       DEBUG ((DEBUG_LOAD | DEBUG_ERROR, "CoreLoadPeImage: There is no EBC interpreter for an EBC image.\n"));
    664       goto Done;
    665     }
    666 
    667     //
    668     // Register a callback for flushing the instruction cache so that created
    669     // thunks can be flushed.
    670     //
    671     Status = Image->Ebc->RegisterICacheFlush (Image->Ebc, (EBC_ICACHE_FLUSH)InvalidateInstructionCacheRange);
    672     if (EFI_ERROR(Status)) {
    673       goto Done;
    674     }
    675 
    676     //
    677     // Create a thunk for the image's entry point. This will be the new
    678     // entry point for the image.
    679     //
    680     Status = Image->Ebc->CreateThunk (
    681                            Image->Ebc,
    682                            Image->Handle,
    683                            (VOID *)(UINTN) Image->ImageContext.EntryPoint,
    684                            (VOID **) &Image->EntryPoint
    685                            );
    686     if (EFI_ERROR(Status)) {
    687       goto Done;
    688     }
    689   }
    690 
    691   //
    692   // Fill in the image information for the Loaded Image Protocol
    693   //
    694   Image->Type               = Image->ImageContext.ImageType;
    695   Image->Info.ImageBase     = (VOID *)(UINTN)Image->ImageContext.ImageAddress;
    696   Image->Info.ImageSize     = Image->ImageContext.ImageSize;
    697   Image->Info.ImageCodeType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType);
    698   Image->Info.ImageDataType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageDataMemoryType);
    699   if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) != 0) {
    700     if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
    701       //
    702       // Make a list off all the RT images so we can let the RT AP know about them.
    703       //
    704       Image->RuntimeData = AllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY));
    705       if (Image->RuntimeData == NULL) {
    706         goto Done;
    707       }
    708       Image->RuntimeData->ImageBase      = Image->Info.ImageBase;
    709       Image->RuntimeData->ImageSize      = (UINT64) (Image->Info.ImageSize);
    710       Image->RuntimeData->RelocationData = Image->ImageContext.FixupData;
    711       Image->RuntimeData->Handle         = Image->Handle;
    712       InsertTailList (&gRuntime->ImageHead, &Image->RuntimeData->Link);
    713       InsertImageRecord (Image->RuntimeData);
    714     }
    715   }
    716 
    717   //
    718   // Fill in the entry point of the image if it is available
    719   //
    720   if (EntryPoint != NULL) {
    721     *EntryPoint = Image->ImageContext.EntryPoint;
    722   }
    723 
    724   //
    725   // Print the load address and the PDB file name if it is available
    726   //
    727 
    728   DEBUG_CODE_BEGIN ();
    729 
    730     UINTN Index;
    731     UINTN StartIndex;
    732     CHAR8 EfiFileName[256];
    733 
    734 
    735     DEBUG ((DEBUG_INFO | DEBUG_LOAD,
    736            "Loading driver at 0x%11p EntryPoint=0x%11p ",
    737            (VOID *)(UINTN) Image->ImageContext.ImageAddress,
    738            FUNCTION_ENTRY_POINT (Image->ImageContext.EntryPoint)));
    739 
    740 
    741     //
    742     // Print Module Name by Pdb file path.
    743     // Windows and Unix style file path are all trimmed correctly.
    744     //
    745     if (Image->ImageContext.PdbPointer != NULL) {
    746       StartIndex = 0;
    747       for (Index = 0; Image->ImageContext.PdbPointer[Index] != 0; Index++) {
    748         if ((Image->ImageContext.PdbPointer[Index] == '\\') || (Image->ImageContext.PdbPointer[Index] == '/')) {
    749           StartIndex = Index + 1;
    750         }
    751       }
    752       //
    753       // Copy the PDB file name to our temporary string, and replace .pdb with .efi
    754       // The PDB file name is limited in the range of 0~255.
    755       // If the length is bigger than 255, trim the redudant characters to avoid overflow in array boundary.
    756       //
    757       for (Index = 0; Index < sizeof (EfiFileName) - 4; Index++) {
    758         EfiFileName[Index] = Image->ImageContext.PdbPointer[Index + StartIndex];
    759         if (EfiFileName[Index] == 0) {
    760           EfiFileName[Index] = '.';
    761         }
    762         if (EfiFileName[Index] == '.') {
    763           EfiFileName[Index + 1] = 'e';
    764           EfiFileName[Index + 2] = 'f';
    765           EfiFileName[Index + 3] = 'i';
    766           EfiFileName[Index + 4] = 0;
    767           break;
    768         }
    769       }
    770 
    771       if (Index == sizeof (EfiFileName) - 4) {
    772         EfiFileName[Index] = 0;
    773       }
    774       DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex]));
    775     }
    776     DEBUG ((DEBUG_INFO | DEBUG_LOAD, "\n"));
    777 
    778   DEBUG_CODE_END ();
    779 
    780   return EFI_SUCCESS;
    781 
    782 Done:
    783 
    784   //
    785   // Free memory.
    786   //
    787 
    788   if (DstBufAlocated) {
    789     CoreFreePages (Image->ImageContext.ImageAddress, Image->NumberOfPages);
    790   }
    791 
    792   if (Image->ImageContext.FixupData != NULL) {
    793     CoreFreePool (Image->ImageContext.FixupData);
    794   }
    795 
    796   return Status;
    797 }
    798 
    799 
    800 
    801 /**
    802   Get the image's private data from its handle.
    803 
    804   @param  ImageHandle             The image handle
    805 
    806   @return Return the image private data associated with ImageHandle.
    807 
    808 **/
    809 LOADED_IMAGE_PRIVATE_DATA *
    810 CoreLoadedImageInfo (
    811   IN EFI_HANDLE  ImageHandle
    812   )
    813 {
    814   EFI_STATUS                 Status;
    815   EFI_LOADED_IMAGE_PROTOCOL  *LoadedImage;
    816   LOADED_IMAGE_PRIVATE_DATA  *Image;
    817 
    818   Status = CoreHandleProtocol (
    819              ImageHandle,
    820              &gEfiLoadedImageProtocolGuid,
    821              (VOID **)&LoadedImage
    822              );
    823   if (!EFI_ERROR (Status)) {
    824     Image = LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage);
    825   } else {
    826     DEBUG ((DEBUG_LOAD, "CoreLoadedImageInfo: Not an ImageHandle %p\n", ImageHandle));
    827     Image = NULL;
    828   }
    829 
    830   return Image;
    831 }
    832 
    833 
    834 /**
    835   Unloads EFI image from memory.
    836 
    837   @param  Image                   EFI image
    838   @param  FreePage                Free allocated pages
    839 
    840 **/
    841 VOID
    842 CoreUnloadAndCloseImage (
    843   IN LOADED_IMAGE_PRIVATE_DATA  *Image,
    844   IN BOOLEAN                    FreePage
    845   )
    846 {
    847   EFI_STATUS                          Status;
    848   UINTN                               HandleCount;
    849   EFI_HANDLE                          *HandleBuffer;
    850   UINTN                               HandleIndex;
    851   EFI_GUID                            **ProtocolGuidArray;
    852   UINTN                               ArrayCount;
    853   UINTN                               ProtocolIndex;
    854   EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;
    855   UINTN                               OpenInfoCount;
    856   UINTN                               OpenInfoIndex;
    857 
    858   HandleBuffer = NULL;
    859   ProtocolGuidArray = NULL;
    860 
    861   if (Image->Started) {
    862     UnregisterMemoryProfileImage (Image);
    863   }
    864 
    865   if (Image->Ebc != NULL) {
    866     //
    867     // If EBC protocol exists we must perform cleanups for this image.
    868     //
    869     Image->Ebc->UnloadImage (Image->Ebc, Image->Handle);
    870   }
    871 
    872   //
    873   // Unload image, free Image->ImageContext->ModHandle
    874   //
    875   PeCoffLoaderUnloadImage (&Image->ImageContext);
    876 
    877   //
    878   // Free our references to the image handle
    879   //
    880   if (Image->Handle != NULL) {
    881 
    882     Status = CoreLocateHandleBuffer (
    883                AllHandles,
    884                NULL,
    885                NULL,
    886                &HandleCount,
    887                &HandleBuffer
    888                );
    889     if (!EFI_ERROR (Status)) {
    890       for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
    891         Status = CoreProtocolsPerHandle (
    892                    HandleBuffer[HandleIndex],
    893                    &ProtocolGuidArray,
    894                    &ArrayCount
    895                    );
    896         if (!EFI_ERROR (Status)) {
    897           for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
    898             Status = CoreOpenProtocolInformation (
    899                        HandleBuffer[HandleIndex],
    900                        ProtocolGuidArray[ProtocolIndex],
    901                        &OpenInfo,
    902                        &OpenInfoCount
    903                        );
    904             if (!EFI_ERROR (Status)) {
    905               for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
    906                 if (OpenInfo[OpenInfoIndex].AgentHandle == Image->Handle) {
    907                   Status = CoreCloseProtocol (
    908                              HandleBuffer[HandleIndex],
    909                              ProtocolGuidArray[ProtocolIndex],
    910                              Image->Handle,
    911                              OpenInfo[OpenInfoIndex].ControllerHandle
    912                              );
    913                 }
    914               }
    915               if (OpenInfo != NULL) {
    916                 CoreFreePool(OpenInfo);
    917               }
    918             }
    919           }
    920           if (ProtocolGuidArray != NULL) {
    921             CoreFreePool(ProtocolGuidArray);
    922           }
    923         }
    924       }
    925       if (HandleBuffer != NULL) {
    926         CoreFreePool (HandleBuffer);
    927       }
    928     }
    929 
    930     CoreRemoveDebugImageInfoEntry (Image->Handle);
    931 
    932     Status = CoreUninstallProtocolInterface (
    933                Image->Handle,
    934                &gEfiLoadedImageDevicePathProtocolGuid,
    935                Image->LoadedImageDevicePath
    936                );
    937 
    938     Status = CoreUninstallProtocolInterface (
    939                Image->Handle,
    940                &gEfiLoadedImageProtocolGuid,
    941                &Image->Info
    942                );
    943 
    944     if (Image->ImageContext.HiiResourceData != 0) {
    945       Status = CoreUninstallProtocolInterface (
    946                  Image->Handle,
    947                  &gEfiHiiPackageListProtocolGuid,
    948                  (VOID *) (UINTN) Image->ImageContext.HiiResourceData
    949                  );
    950     }
    951 
    952   }
    953 
    954   if (Image->RuntimeData != NULL) {
    955     if (Image->RuntimeData->Link.ForwardLink != NULL) {
    956       //
    957       // Remove the Image from the Runtime Image list as we are about to Free it!
    958       //
    959       RemoveEntryList (&Image->RuntimeData->Link);
    960       RemoveImageRecord (Image->RuntimeData);
    961     }
    962     CoreFreePool (Image->RuntimeData);
    963   }
    964 
    965   //
    966   // Free the Image from memory
    967   //
    968   if ((Image->ImageBasePage != 0) && FreePage) {
    969     CoreFreePages (Image->ImageBasePage, Image->NumberOfPages);
    970   }
    971 
    972   //
    973   // Done with the Image structure
    974   //
    975   if (Image->Info.FilePath != NULL) {
    976     CoreFreePool (Image->Info.FilePath);
    977   }
    978 
    979   if (Image->LoadedImageDevicePath != NULL) {
    980     CoreFreePool (Image->LoadedImageDevicePath);
    981   }
    982 
    983   if (Image->FixupData != NULL) {
    984     CoreFreePool (Image->FixupData);
    985   }
    986 
    987   CoreFreePool (Image);
    988 }
    989 
    990 
    991 /**
    992   Loads an EFI image into memory and returns a handle to the image.
    993 
    994   @param  BootPolicy              If TRUE, indicates that the request originates
    995                                   from the boot manager, and that the boot
    996                                   manager is attempting to load FilePath as a
    997                                   boot selection.
    998   @param  ParentImageHandle       The caller's image handle.
    999   @param  FilePath                The specific file path from which the image is
   1000                                   loaded.
   1001   @param  SourceBuffer            If not NULL, a pointer to the memory location
   1002                                   containing a copy of the image to be loaded.
   1003   @param  SourceSize              The size in bytes of SourceBuffer.
   1004   @param  DstBuffer               The buffer to store the image
   1005   @param  NumberOfPages           If not NULL, it inputs a pointer to the page
   1006                                   number of DstBuffer and outputs a pointer to
   1007                                   the page number of the image. If this number is
   1008                                   not enough,  return EFI_BUFFER_TOO_SMALL and
   1009                                   this parameter contains the required number.
   1010   @param  ImageHandle             Pointer to the returned image handle that is
   1011                                   created when the image is successfully loaded.
   1012   @param  EntryPoint              A pointer to the entry point
   1013   @param  Attribute               The bit mask of attributes to set for the load
   1014                                   PE image
   1015 
   1016   @retval EFI_SUCCESS             The image was loaded into memory.
   1017   @retval EFI_NOT_FOUND           The FilePath was not found.
   1018   @retval EFI_INVALID_PARAMETER   One of the parameters has an invalid value.
   1019   @retval EFI_BUFFER_TOO_SMALL    The buffer is too small
   1020   @retval EFI_UNSUPPORTED         The image type is not supported, or the device
   1021                                   path cannot be parsed to locate the proper
   1022                                   protocol for loading the file.
   1023   @retval EFI_OUT_OF_RESOURCES    Image was not loaded due to insufficient
   1024                                   resources.
   1025   @retval EFI_LOAD_ERROR          Image was not loaded because the image format was corrupt or not
   1026                                   understood.
   1027   @retval EFI_DEVICE_ERROR        Image was not loaded because the device returned a read error.
   1028   @retval EFI_ACCESS_DENIED       Image was not loaded because the platform policy prohibits the
   1029                                   image from being loaded. NULL is returned in *ImageHandle.
   1030   @retval EFI_SECURITY_VIOLATION  Image was loaded and an ImageHandle was created with a
   1031                                   valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
   1032                                   platform policy specifies that the image should not be started.
   1033 
   1034 **/
   1035 EFI_STATUS
   1036 CoreLoadImageCommon (
   1037   IN  BOOLEAN                          BootPolicy,
   1038   IN  EFI_HANDLE                       ParentImageHandle,
   1039   IN  EFI_DEVICE_PATH_PROTOCOL         *FilePath,
   1040   IN  VOID                             *SourceBuffer       OPTIONAL,
   1041   IN  UINTN                            SourceSize,
   1042   IN  EFI_PHYSICAL_ADDRESS             DstBuffer           OPTIONAL,
   1043   IN OUT UINTN                         *NumberOfPages      OPTIONAL,
   1044   OUT EFI_HANDLE                       *ImageHandle,
   1045   OUT EFI_PHYSICAL_ADDRESS             *EntryPoint         OPTIONAL,
   1046   IN  UINT32                           Attribute
   1047   )
   1048 {
   1049   LOADED_IMAGE_PRIVATE_DATA  *Image;
   1050   LOADED_IMAGE_PRIVATE_DATA  *ParentImage;
   1051   IMAGE_FILE_HANDLE          FHand;
   1052   EFI_STATUS                 Status;
   1053   EFI_STATUS                 SecurityStatus;
   1054   EFI_HANDLE                 DeviceHandle;
   1055   UINT32                     AuthenticationStatus;
   1056   EFI_DEVICE_PATH_PROTOCOL   *OriginalFilePath;
   1057   EFI_DEVICE_PATH_PROTOCOL   *HandleFilePath;
   1058   EFI_DEVICE_PATH_PROTOCOL   *InputFilePath;
   1059   EFI_DEVICE_PATH_PROTOCOL   *Node;
   1060   UINTN                      FilePathSize;
   1061   BOOLEAN                    ImageIsFromFv;
   1062   BOOLEAN                    ImageIsFromLoadFile;
   1063 
   1064   SecurityStatus = EFI_SUCCESS;
   1065 
   1066   ASSERT (gEfiCurrentTpl < TPL_NOTIFY);
   1067   ParentImage = NULL;
   1068 
   1069   //
   1070   // The caller must pass in a valid ParentImageHandle
   1071   //
   1072   if (ImageHandle == NULL || ParentImageHandle == NULL) {
   1073     return EFI_INVALID_PARAMETER;
   1074   }
   1075 
   1076   ParentImage = CoreLoadedImageInfo (ParentImageHandle);
   1077   if (ParentImage == NULL) {
   1078     DEBUG((DEBUG_LOAD|DEBUG_ERROR, "LoadImageEx: Parent handle not an image handle\n"));
   1079     return EFI_INVALID_PARAMETER;
   1080   }
   1081 
   1082   ZeroMem (&FHand, sizeof (IMAGE_FILE_HANDLE));
   1083   FHand.Signature  = IMAGE_FILE_HANDLE_SIGNATURE;
   1084   OriginalFilePath = FilePath;
   1085   InputFilePath    = FilePath;
   1086   HandleFilePath   = FilePath;
   1087   DeviceHandle     = NULL;
   1088   Status           = EFI_SUCCESS;
   1089   AuthenticationStatus = 0;
   1090   ImageIsFromFv        = FALSE;
   1091   ImageIsFromLoadFile  = FALSE;
   1092 
   1093   //
   1094   // If the caller passed a copy of the file, then just use it
   1095   //
   1096   if (SourceBuffer != NULL) {
   1097     FHand.Source     = SourceBuffer;
   1098     FHand.SourceSize = SourceSize;
   1099     Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &HandleFilePath, &DeviceHandle);
   1100     if (EFI_ERROR (Status)) {
   1101       DeviceHandle = NULL;
   1102     }
   1103     if (SourceSize > 0) {
   1104       Status = EFI_SUCCESS;
   1105     } else {
   1106       Status = EFI_LOAD_ERROR;
   1107     }
   1108   } else {
   1109     if (FilePath == NULL) {
   1110       return EFI_INVALID_PARAMETER;
   1111     }
   1112 
   1113     //
   1114     // Try to get the image device handle by checking the match protocol.
   1115     //
   1116     Node   = NULL;
   1117     Status = CoreLocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &HandleFilePath, &DeviceHandle);
   1118     if (!EFI_ERROR (Status)) {
   1119       ImageIsFromFv = TRUE;
   1120     } else {
   1121       HandleFilePath = FilePath;
   1122       Status = CoreLocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &HandleFilePath, &DeviceHandle);
   1123       if (EFI_ERROR (Status)) {
   1124         if (!BootPolicy) {
   1125           HandleFilePath = FilePath;
   1126           Status = CoreLocateDevicePath (&gEfiLoadFile2ProtocolGuid, &HandleFilePath, &DeviceHandle);
   1127         }
   1128         if (EFI_ERROR (Status)) {
   1129           HandleFilePath = FilePath;
   1130           Status = CoreLocateDevicePath (&gEfiLoadFileProtocolGuid, &HandleFilePath, &DeviceHandle);
   1131           if (!EFI_ERROR (Status)) {
   1132             ImageIsFromLoadFile = TRUE;
   1133             Node = HandleFilePath;
   1134           }
   1135         }
   1136       }
   1137     }
   1138 
   1139     //
   1140     // Get the source file buffer by its device path.
   1141     //
   1142     FHand.Source = GetFileBufferByFilePath (
   1143                       BootPolicy,
   1144                       FilePath,
   1145                       &FHand.SourceSize,
   1146                       &AuthenticationStatus
   1147                       );
   1148     if (FHand.Source == NULL) {
   1149       Status = EFI_NOT_FOUND;
   1150     } else {
   1151       FHand.FreeBuffer = TRUE;
   1152       if (ImageIsFromLoadFile) {
   1153         //
   1154         // LoadFile () may cause the device path of the Handle be updated.
   1155         //
   1156         OriginalFilePath = AppendDevicePath (DevicePathFromHandle (DeviceHandle), Node);
   1157       }
   1158     }
   1159   }
   1160 
   1161   if (EFI_ERROR (Status)) {
   1162     Image = NULL;
   1163     goto Done;
   1164   }
   1165 
   1166   if (gSecurity2 != NULL) {
   1167     //
   1168     // Verify File Authentication through the Security2 Architectural Protocol
   1169     //
   1170     SecurityStatus = gSecurity2->FileAuthentication (
   1171                                   gSecurity2,
   1172                                   OriginalFilePath,
   1173                                   FHand.Source,
   1174                                   FHand.SourceSize,
   1175                                   BootPolicy
   1176                                   );
   1177     if (!EFI_ERROR (SecurityStatus) && ImageIsFromFv) {
   1178       //
   1179       // When Security2 is installed, Security Architectural Protocol must be published.
   1180       //
   1181       ASSERT (gSecurity != NULL);
   1182 
   1183       //
   1184       // Verify the Authentication Status through the Security Architectural Protocol
   1185       // Only on images that have been read using Firmware Volume protocol.
   1186       //
   1187       SecurityStatus = gSecurity->FileAuthenticationState (
   1188                                     gSecurity,
   1189                                     AuthenticationStatus,
   1190                                     OriginalFilePath
   1191                                     );
   1192     }
   1193   } else if ((gSecurity != NULL) && (OriginalFilePath != NULL)) {
   1194     //
   1195     // Verify the Authentication Status through the Security Architectural Protocol
   1196     //
   1197     SecurityStatus = gSecurity->FileAuthenticationState (
   1198                                   gSecurity,
   1199                                   AuthenticationStatus,
   1200                                   OriginalFilePath
   1201                                   );
   1202   }
   1203 
   1204   //
   1205   // Check Security Status.
   1206   //
   1207   if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {
   1208     if (SecurityStatus == EFI_ACCESS_DENIED) {
   1209       //
   1210       // Image was not loaded because the platform policy prohibits the image from being loaded.
   1211       // It's the only place we could meet EFI_ACCESS_DENIED.
   1212       //
   1213       *ImageHandle = NULL;
   1214     }
   1215     Status = SecurityStatus;
   1216     Image = NULL;
   1217     goto Done;
   1218   }
   1219 
   1220   //
   1221   // Allocate a new image structure
   1222   //
   1223   Image = AllocateZeroPool (sizeof(LOADED_IMAGE_PRIVATE_DATA));
   1224   if (Image == NULL) {
   1225     Status = EFI_OUT_OF_RESOURCES;
   1226     goto Done;
   1227   }
   1228 
   1229   //
   1230   // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
   1231   //
   1232   FilePath = OriginalFilePath;
   1233   if (DeviceHandle != NULL) {
   1234     Status = CoreHandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath);
   1235     if (!EFI_ERROR (Status)) {
   1236       FilePathSize = GetDevicePathSize (HandleFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
   1237       FilePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *)FilePath) + FilePathSize );
   1238     }
   1239   }
   1240   //
   1241   // Initialize the fields for an internal driver
   1242   //
   1243   Image->Signature         = LOADED_IMAGE_PRIVATE_DATA_SIGNATURE;
   1244   Image->Info.SystemTable  = gDxeCoreST;
   1245   Image->Info.DeviceHandle = DeviceHandle;
   1246   Image->Info.Revision     = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
   1247   Image->Info.FilePath     = DuplicateDevicePath (FilePath);
   1248   Image->Info.ParentHandle = ParentImageHandle;
   1249 
   1250 
   1251   if (NumberOfPages != NULL) {
   1252     Image->NumberOfPages = *NumberOfPages ;
   1253   } else {
   1254     Image->NumberOfPages = 0 ;
   1255   }
   1256 
   1257   //
   1258   // Install the protocol interfaces for this image
   1259   // don't fire notifications yet
   1260   //
   1261   Status = CoreInstallProtocolInterfaceNotify (
   1262              &Image->Handle,
   1263              &gEfiLoadedImageProtocolGuid,
   1264              EFI_NATIVE_INTERFACE,
   1265              &Image->Info,
   1266              FALSE
   1267              );
   1268   if (EFI_ERROR (Status)) {
   1269     goto Done;
   1270   }
   1271 
   1272   //
   1273   // Load the image.  If EntryPoint is Null, it will not be set.
   1274   //
   1275   Status = CoreLoadPeImage (BootPolicy, &FHand, Image, DstBuffer, EntryPoint, Attribute);
   1276   if (EFI_ERROR (Status)) {
   1277     if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_OUT_OF_RESOURCES)) {
   1278       if (NumberOfPages != NULL) {
   1279         *NumberOfPages = Image->NumberOfPages;
   1280       }
   1281     }
   1282     goto Done;
   1283   }
   1284 
   1285   if (NumberOfPages != NULL) {
   1286     *NumberOfPages = Image->NumberOfPages;
   1287   }
   1288 
   1289   //
   1290   // Register the image in the Debug Image Info Table if the attribute is set
   1291   //
   1292   if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION) != 0) {
   1293     CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, &Image->Info, Image->Handle);
   1294   }
   1295 
   1296   //
   1297   //Reinstall loaded image protocol to fire any notifications
   1298   //
   1299   Status = CoreReinstallProtocolInterface (
   1300              Image->Handle,
   1301              &gEfiLoadedImageProtocolGuid,
   1302              &Image->Info,
   1303              &Image->Info
   1304              );
   1305   if (EFI_ERROR (Status)) {
   1306     goto Done;
   1307   }
   1308 
   1309   //
   1310   // If DevicePath parameter to the LoadImage() is not NULL, then make a copy of DevicePath,
   1311   // otherwise Loaded Image Device Path Protocol is installed with a NULL interface pointer.
   1312   //
   1313   if (OriginalFilePath != NULL) {
   1314     Image->LoadedImageDevicePath = DuplicateDevicePath (OriginalFilePath);
   1315   }
   1316 
   1317   //
   1318   // Install Loaded Image Device Path Protocol onto the image handle of a PE/COFE image
   1319   //
   1320   Status = CoreInstallProtocolInterface (
   1321             &Image->Handle,
   1322             &gEfiLoadedImageDevicePathProtocolGuid,
   1323             EFI_NATIVE_INTERFACE,
   1324             Image->LoadedImageDevicePath
   1325             );
   1326   if (EFI_ERROR (Status)) {
   1327     goto Done;
   1328   }
   1329 
   1330   //
   1331   // Install HII Package List Protocol onto the image handle
   1332   //
   1333   if (Image->ImageContext.HiiResourceData != 0) {
   1334     Status = CoreInstallProtocolInterface (
   1335                &Image->Handle,
   1336                &gEfiHiiPackageListProtocolGuid,
   1337                EFI_NATIVE_INTERFACE,
   1338                (VOID *) (UINTN) Image->ImageContext.HiiResourceData
   1339                );
   1340     if (EFI_ERROR (Status)) {
   1341       goto Done;
   1342     }
   1343   }
   1344 
   1345   //
   1346   // Success.  Return the image handle
   1347   //
   1348   *ImageHandle = Image->Handle;
   1349 
   1350 Done:
   1351   //
   1352   // All done accessing the source file
   1353   // If we allocated the Source buffer, free it
   1354   //
   1355   if (FHand.FreeBuffer) {
   1356     CoreFreePool (FHand.Source);
   1357   }
   1358   if (OriginalFilePath != InputFilePath) {
   1359     CoreFreePool (OriginalFilePath);
   1360   }
   1361 
   1362   //
   1363   // There was an error.  If there's an Image structure, free it
   1364   //
   1365   if (EFI_ERROR (Status)) {
   1366     if (Image != NULL) {
   1367       CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer == 0));
   1368       Image = NULL;
   1369     }
   1370   } else if (EFI_ERROR (SecurityStatus)) {
   1371     Status = SecurityStatus;
   1372   }
   1373 
   1374   //
   1375   // Track the return status from LoadImage.
   1376   //
   1377   if (Image != NULL) {
   1378     Image->LoadImageStatus = Status;
   1379   }
   1380 
   1381   return Status;
   1382 }
   1383 
   1384 
   1385 
   1386 
   1387 /**
   1388   Loads an EFI image into memory and returns a handle to the image.
   1389 
   1390   @param  BootPolicy              If TRUE, indicates that the request originates
   1391                                   from the boot manager, and that the boot
   1392                                   manager is attempting to load FilePath as a
   1393                                   boot selection.
   1394   @param  ParentImageHandle       The caller's image handle.
   1395   @param  FilePath                The specific file path from which the image is
   1396                                   loaded.
   1397   @param  SourceBuffer            If not NULL, a pointer to the memory location
   1398                                   containing a copy of the image to be loaded.
   1399   @param  SourceSize              The size in bytes of SourceBuffer.
   1400   @param  ImageHandle             Pointer to the returned image handle that is
   1401                                   created when the image is successfully loaded.
   1402 
   1403   @retval EFI_SUCCESS             The image was loaded into memory.
   1404   @retval EFI_NOT_FOUND           The FilePath was not found.
   1405   @retval EFI_INVALID_PARAMETER   One of the parameters has an invalid value.
   1406   @retval EFI_UNSUPPORTED         The image type is not supported, or the device
   1407                                   path cannot be parsed to locate the proper
   1408                                   protocol for loading the file.
   1409   @retval EFI_OUT_OF_RESOURCES    Image was not loaded due to insufficient
   1410                                   resources.
   1411   @retval EFI_LOAD_ERROR          Image was not loaded because the image format was corrupt or not
   1412                                   understood.
   1413   @retval EFI_DEVICE_ERROR        Image was not loaded because the device returned a read error.
   1414   @retval EFI_ACCESS_DENIED       Image was not loaded because the platform policy prohibits the
   1415                                   image from being loaded. NULL is returned in *ImageHandle.
   1416   @retval EFI_SECURITY_VIOLATION  Image was loaded and an ImageHandle was created with a
   1417                                   valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
   1418                                   platform policy specifies that the image should not be started.
   1419 
   1420 **/
   1421 EFI_STATUS
   1422 EFIAPI
   1423 CoreLoadImage (
   1424   IN BOOLEAN                    BootPolicy,
   1425   IN EFI_HANDLE                 ParentImageHandle,
   1426   IN EFI_DEVICE_PATH_PROTOCOL   *FilePath,
   1427   IN VOID                       *SourceBuffer   OPTIONAL,
   1428   IN UINTN                      SourceSize,
   1429   OUT EFI_HANDLE                *ImageHandle
   1430   )
   1431 {
   1432   EFI_STATUS    Status;
   1433   UINT64        Tick;
   1434   EFI_HANDLE    Handle;
   1435 
   1436   Tick = 0;
   1437   PERF_CODE (
   1438     Tick = GetPerformanceCounter ();
   1439   );
   1440 
   1441   Status = CoreLoadImageCommon (
   1442              BootPolicy,
   1443              ParentImageHandle,
   1444              FilePath,
   1445              SourceBuffer,
   1446              SourceSize,
   1447              (EFI_PHYSICAL_ADDRESS) (UINTN) NULL,
   1448              NULL,
   1449              ImageHandle,
   1450              NULL,
   1451              EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION | EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
   1452              );
   1453 
   1454   Handle = NULL;
   1455   if (!EFI_ERROR (Status)) {
   1456     //
   1457     // ImageHandle will be valid only Status is success.
   1458     //
   1459     Handle = *ImageHandle;
   1460   }
   1461 
   1462   PERF_START (Handle, "LoadImage:", NULL, Tick);
   1463   PERF_END (Handle, "LoadImage:", NULL, 0);
   1464 
   1465   return Status;
   1466 }
   1467 
   1468 
   1469 
   1470 /**
   1471   Loads an EFI image into memory and returns a handle to the image with extended parameters.
   1472 
   1473   @param  This                    Calling context
   1474   @param  ParentImageHandle       The caller's image handle.
   1475   @param  FilePath                The specific file path from which the image is
   1476                                   loaded.
   1477   @param  SourceBuffer            If not NULL, a pointer to the memory location
   1478                                   containing a copy of the image to be loaded.
   1479   @param  SourceSize              The size in bytes of SourceBuffer.
   1480   @param  DstBuffer               The buffer to store the image.
   1481   @param  NumberOfPages           For input, specifies the space size of the
   1482                                   image by caller if not NULL. For output,
   1483                                   specifies the actual space size needed.
   1484   @param  ImageHandle             Image handle for output.
   1485   @param  EntryPoint              Image entry point for output.
   1486   @param  Attribute               The bit mask of attributes to set for the load
   1487                                   PE image.
   1488 
   1489   @retval EFI_SUCCESS             The image was loaded into memory.
   1490   @retval EFI_NOT_FOUND           The FilePath was not found.
   1491   @retval EFI_INVALID_PARAMETER   One of the parameters has an invalid value.
   1492   @retval EFI_UNSUPPORTED         The image type is not supported, or the device
   1493                                   path cannot be parsed to locate the proper
   1494                                   protocol for loading the file.
   1495   @retval EFI_OUT_OF_RESOURCES    Image was not loaded due to insufficient
   1496                                   resources.
   1497   @retval EFI_LOAD_ERROR          Image was not loaded because the image format was corrupt or not
   1498                                   understood.
   1499   @retval EFI_DEVICE_ERROR        Image was not loaded because the device returned a read error.
   1500   @retval EFI_ACCESS_DENIED       Image was not loaded because the platform policy prohibits the
   1501                                   image from being loaded. NULL is returned in *ImageHandle.
   1502   @retval EFI_SECURITY_VIOLATION  Image was loaded and an ImageHandle was created with a
   1503                                   valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
   1504                                   platform policy specifies that the image should not be started.
   1505 
   1506 **/
   1507 EFI_STATUS
   1508 EFIAPI
   1509 CoreLoadImageEx (
   1510   IN  EFI_PE32_IMAGE_PROTOCOL          *This,
   1511   IN  EFI_HANDLE                       ParentImageHandle,
   1512   IN  EFI_DEVICE_PATH_PROTOCOL         *FilePath,
   1513   IN  VOID                             *SourceBuffer       OPTIONAL,
   1514   IN  UINTN                            SourceSize,
   1515   IN  EFI_PHYSICAL_ADDRESS             DstBuffer           OPTIONAL,
   1516   OUT UINTN                            *NumberOfPages      OPTIONAL,
   1517   OUT EFI_HANDLE                       *ImageHandle,
   1518   OUT EFI_PHYSICAL_ADDRESS             *EntryPoint         OPTIONAL,
   1519   IN  UINT32                           Attribute
   1520   )
   1521 {
   1522   EFI_STATUS    Status;
   1523   UINT64        Tick;
   1524   EFI_HANDLE    Handle;
   1525 
   1526   Tick = 0;
   1527   PERF_CODE (
   1528     Tick = GetPerformanceCounter ();
   1529   );
   1530 
   1531   Status = CoreLoadImageCommon (
   1532            TRUE,
   1533            ParentImageHandle,
   1534            FilePath,
   1535            SourceBuffer,
   1536            SourceSize,
   1537            DstBuffer,
   1538            NumberOfPages,
   1539            ImageHandle,
   1540            EntryPoint,
   1541            Attribute
   1542            );
   1543 
   1544   Handle = NULL;
   1545   if (!EFI_ERROR (Status)) {
   1546     //
   1547     // ImageHandle will be valid only Status is success.
   1548     //
   1549     Handle = *ImageHandle;
   1550   }
   1551 
   1552   PERF_START (Handle, "LoadImage:", NULL, Tick);
   1553   PERF_END (Handle, "LoadImage:", NULL, 0);
   1554 
   1555   return Status;
   1556 }
   1557 
   1558 
   1559 /**
   1560   Transfer control to a loaded image's entry point.
   1561 
   1562   @param  ImageHandle             Handle of image to be started.
   1563   @param  ExitDataSize            Pointer of the size to ExitData
   1564   @param  ExitData                Pointer to a pointer to a data buffer that
   1565                                   includes a Null-terminated string,
   1566                                   optionally followed by additional binary data.
   1567                                   The string is a description that the caller may
   1568                                   use to further indicate the reason for the
   1569                                   image's exit.
   1570 
   1571   @retval EFI_INVALID_PARAMETER   Invalid parameter
   1572   @retval EFI_OUT_OF_RESOURCES    No enough buffer to allocate
   1573   @retval EFI_SECURITY_VIOLATION  The current platform policy specifies that the image should not be started.
   1574   @retval EFI_SUCCESS             Successfully transfer control to the image's
   1575                                   entry point.
   1576 
   1577 **/
   1578 EFI_STATUS
   1579 EFIAPI
   1580 CoreStartImage (
   1581   IN EFI_HANDLE  ImageHandle,
   1582   OUT UINTN      *ExitDataSize,
   1583   OUT CHAR16     **ExitData  OPTIONAL
   1584   )
   1585 {
   1586   EFI_STATUS                    Status;
   1587   LOADED_IMAGE_PRIVATE_DATA     *Image;
   1588   LOADED_IMAGE_PRIVATE_DATA     *LastImage;
   1589   UINT64                        HandleDatabaseKey;
   1590   UINTN                         SetJumpFlag;
   1591   UINT64                        Tick;
   1592   EFI_HANDLE                    Handle;
   1593 
   1594   Tick = 0;
   1595   Handle = ImageHandle;
   1596 
   1597   Image = CoreLoadedImageInfo (ImageHandle);
   1598   if (Image == NULL  ||  Image->Started) {
   1599     return EFI_INVALID_PARAMETER;
   1600   }
   1601   if (EFI_ERROR (Image->LoadImageStatus)) {
   1602     return Image->LoadImageStatus;
   1603   }
   1604 
   1605   //
   1606   // The image to be started must have the machine type supported by DxeCore.
   1607   //
   1608   if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->Machine)) {
   1609     //
   1610     // Do not ASSERT here, because image might be loaded via EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED
   1611     // But it can not be started.
   1612     //
   1613     DEBUG ((EFI_D_ERROR, "Image type %s can't be started ", GetMachineTypeName(Image->Machine)));
   1614     DEBUG ((EFI_D_ERROR, "on %s UEFI system.\n", GetMachineTypeName(mDxeCoreImageMachineType)));
   1615     return EFI_UNSUPPORTED;
   1616   }
   1617 
   1618   PERF_CODE (
   1619     Tick = GetPerformanceCounter ();
   1620   );
   1621 
   1622 
   1623   //
   1624   // Push the current start image context, and
   1625   // link the current image to the head.   This is the
   1626   // only image that can call Exit()
   1627   //
   1628   HandleDatabaseKey = CoreGetHandleDatabaseKey ();
   1629   LastImage         = mCurrentImage;
   1630   mCurrentImage     = Image;
   1631   Image->Tpl        = gEfiCurrentTpl;
   1632 
   1633   //
   1634   // Set long jump for Exit() support
   1635   // JumpContext must be aligned on a CPU specific boundary.
   1636   // Overallocate the buffer and force the required alignment
   1637   //
   1638   Image->JumpBuffer = AllocatePool (sizeof (BASE_LIBRARY_JUMP_BUFFER) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);
   1639   if (Image->JumpBuffer == NULL) {
   1640     //
   1641     // Image may be unloaded after return with failure,
   1642     // then ImageHandle may be invalid, so use NULL handle to record perf log.
   1643     //
   1644     PERF_START (NULL, "StartImage:", NULL, Tick);
   1645     PERF_END (NULL, "StartImage:", NULL, 0);
   1646     return EFI_OUT_OF_RESOURCES;
   1647   }
   1648   Image->JumpContext = ALIGN_POINTER (Image->JumpBuffer, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);
   1649 
   1650   SetJumpFlag = SetJump (Image->JumpContext);
   1651   //
   1652   // The initial call to SetJump() must always return 0.
   1653   // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
   1654   //
   1655   if (SetJumpFlag == 0) {
   1656     RegisterMemoryProfileImage (Image, (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION ? EFI_FV_FILETYPE_APPLICATION : EFI_FV_FILETYPE_DRIVER));
   1657     //
   1658     // Call the image's entry point
   1659     //
   1660     Image->Started = TRUE;
   1661     Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable);
   1662 
   1663     //
   1664     // Add some debug information if the image returned with error.
   1665     // This make the user aware and check if the driver image have already released
   1666     // all the resource in this situation.
   1667     //
   1668     DEBUG_CODE_BEGIN ();
   1669       if (EFI_ERROR (Image->Status)) {
   1670         DEBUG ((DEBUG_ERROR, "Error: Image at %11p start failed: %r\n", Image->Info.ImageBase, Image->Status));
   1671       }
   1672     DEBUG_CODE_END ();
   1673 
   1674     //
   1675     // If the image returns, exit it through Exit()
   1676     //
   1677     CoreExit (ImageHandle, Image->Status, 0, NULL);
   1678   }
   1679 
   1680   //
   1681   // Image has completed.  Verify the tpl is the same
   1682   //
   1683   ASSERT (Image->Tpl == gEfiCurrentTpl);
   1684   CoreRestoreTpl (Image->Tpl);
   1685 
   1686   CoreFreePool (Image->JumpBuffer);
   1687 
   1688   //
   1689   // Pop the current start image context
   1690   //
   1691   mCurrentImage = LastImage;
   1692 
   1693   //
   1694   // Go connect any handles that were created or modified while the image executed.
   1695   //
   1696   CoreConnectHandlesByKey (HandleDatabaseKey);
   1697 
   1698   //
   1699   // Handle the image's returned ExitData
   1700   //
   1701   DEBUG_CODE_BEGIN ();
   1702     if (Image->ExitDataSize != 0 || Image->ExitData != NULL) {
   1703 
   1704       DEBUG ((DEBUG_LOAD, "StartImage: ExitDataSize %d, ExitData %p", (UINT32)Image->ExitDataSize, Image->ExitData));
   1705       if (Image->ExitData != NULL) {
   1706         DEBUG ((DEBUG_LOAD, " (%hs)", Image->ExitData));
   1707       }
   1708       DEBUG ((DEBUG_LOAD, "\n"));
   1709     }
   1710   DEBUG_CODE_END ();
   1711 
   1712   //
   1713   //  Return the exit data to the caller
   1714   //
   1715   if (ExitData != NULL && ExitDataSize != NULL) {
   1716     *ExitDataSize = Image->ExitDataSize;
   1717     *ExitData     = Image->ExitData;
   1718   } else {
   1719     //
   1720     // Caller doesn't want the exit data, free it
   1721     //
   1722     CoreFreePool (Image->ExitData);
   1723     Image->ExitData = NULL;
   1724   }
   1725 
   1726   //
   1727   // Save the Status because Image will get destroyed if it is unloaded.
   1728   //
   1729   Status = Image->Status;
   1730 
   1731   //
   1732   // If the image returned an error, or if the image is an application
   1733   // unload it
   1734   //
   1735   if (EFI_ERROR (Image->Status) || Image->Type == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
   1736     CoreUnloadAndCloseImage (Image, TRUE);
   1737     //
   1738     // ImageHandle may be invalid after the image is unloaded, so use NULL handle to record perf log.
   1739     //
   1740     Handle = NULL;
   1741   }
   1742 
   1743   //
   1744   // Done
   1745   //
   1746   PERF_START (Handle, "StartImage:", NULL, Tick);
   1747   PERF_END (Handle, "StartImage:", NULL, 0);
   1748   return Status;
   1749 }
   1750 
   1751 /**
   1752   Terminates the currently loaded EFI image and returns control to boot services.
   1753 
   1754   @param  ImageHandle             Handle that identifies the image. This
   1755                                   parameter is passed to the image on entry.
   1756   @param  Status                  The image's exit code.
   1757   @param  ExitDataSize            The size, in bytes, of ExitData. Ignored if
   1758                                   ExitStatus is EFI_SUCCESS.
   1759   @param  ExitData                Pointer to a data buffer that includes a
   1760                                   Null-terminated Unicode string, optionally
   1761                                   followed by additional binary data. The string
   1762                                   is a description that the caller may use to
   1763                                   further indicate the reason for the image's
   1764                                   exit.
   1765 
   1766   @retval EFI_INVALID_PARAMETER   Image handle is NULL or it is not current
   1767                                   image.
   1768   @retval EFI_SUCCESS             Successfully terminates the currently loaded
   1769                                   EFI image.
   1770   @retval EFI_ACCESS_DENIED       Should never reach there.
   1771   @retval EFI_OUT_OF_RESOURCES    Could not allocate pool
   1772 
   1773 **/
   1774 EFI_STATUS
   1775 EFIAPI
   1776 CoreExit (
   1777   IN EFI_HANDLE  ImageHandle,
   1778   IN EFI_STATUS  Status,
   1779   IN UINTN       ExitDataSize,
   1780   IN CHAR16      *ExitData  OPTIONAL
   1781   )
   1782 {
   1783   LOADED_IMAGE_PRIVATE_DATA  *Image;
   1784   EFI_TPL                    OldTpl;
   1785 
   1786   //
   1787   // Prevent possible reentrance to this function
   1788   // for the same ImageHandle
   1789   //
   1790   OldTpl = CoreRaiseTpl (TPL_NOTIFY);
   1791 
   1792   Image = CoreLoadedImageInfo (ImageHandle);
   1793   if (Image == NULL) {
   1794     Status = EFI_INVALID_PARAMETER;
   1795     goto Done;
   1796   }
   1797 
   1798   if (!Image->Started) {
   1799     //
   1800     // The image has not been started so just free its resources
   1801     //
   1802     CoreUnloadAndCloseImage (Image, TRUE);
   1803     Status = EFI_SUCCESS;
   1804     goto Done;
   1805   }
   1806 
   1807   //
   1808   // Image has been started, verify this image can exit
   1809   //
   1810   if (Image != mCurrentImage) {
   1811     DEBUG ((DEBUG_LOAD|DEBUG_ERROR, "Exit: Image is not exitable image\n"));
   1812     Status = EFI_INVALID_PARAMETER;
   1813     goto Done;
   1814   }
   1815 
   1816   //
   1817   // Set status
   1818   //
   1819   Image->Status = Status;
   1820 
   1821   //
   1822   // If there's ExitData info, move it
   1823   //
   1824   if (ExitData != NULL) {
   1825     Image->ExitDataSize = ExitDataSize;
   1826     Image->ExitData = AllocatePool (Image->ExitDataSize);
   1827     if (Image->ExitData == NULL) {
   1828       Status = EFI_OUT_OF_RESOURCES;
   1829       goto Done;
   1830     }
   1831     CopyMem (Image->ExitData, ExitData, Image->ExitDataSize);
   1832   }
   1833 
   1834   CoreRestoreTpl (OldTpl);
   1835   //
   1836   // return to StartImage
   1837   //
   1838   LongJump (Image->JumpContext, (UINTN)-1);
   1839 
   1840   //
   1841   // If we return from LongJump, then it is an error
   1842   //
   1843   ASSERT (FALSE);
   1844   Status = EFI_ACCESS_DENIED;
   1845 Done:
   1846   CoreRestoreTpl (OldTpl);
   1847   return Status;
   1848 }
   1849 
   1850 
   1851 
   1852 
   1853 /**
   1854   Unloads an image.
   1855 
   1856   @param  ImageHandle             Handle that identifies the image to be
   1857                                   unloaded.
   1858 
   1859   @retval EFI_SUCCESS             The image has been unloaded.
   1860   @retval EFI_UNSUPPORTED         The image has been sarted, and does not support
   1861                                   unload.
   1862   @retval EFI_INVALID_PARAMPETER  ImageHandle is not a valid image handle.
   1863 
   1864 **/
   1865 EFI_STATUS
   1866 EFIAPI
   1867 CoreUnloadImage (
   1868   IN EFI_HANDLE  ImageHandle
   1869   )
   1870 {
   1871   EFI_STATUS                 Status;
   1872   LOADED_IMAGE_PRIVATE_DATA  *Image;
   1873 
   1874   Image = CoreLoadedImageInfo (ImageHandle);
   1875   if (Image == NULL ) {
   1876     //
   1877     // The image handle is not valid
   1878     //
   1879     Status = EFI_INVALID_PARAMETER;
   1880     goto Done;
   1881   }
   1882 
   1883   if (Image->Started) {
   1884     //
   1885     // The image has been started, request it to unload.
   1886     //
   1887     Status = EFI_UNSUPPORTED;
   1888     if (Image->Info.Unload != NULL) {
   1889       Status = Image->Info.Unload (ImageHandle);
   1890     }
   1891 
   1892   } else {
   1893     //
   1894     // This Image hasn't been started, thus it can be unloaded
   1895     //
   1896     Status = EFI_SUCCESS;
   1897   }
   1898 
   1899 
   1900   if (!EFI_ERROR (Status)) {
   1901     //
   1902     // if the Image was not started or Unloaded O.K. then clean up
   1903     //
   1904     CoreUnloadAndCloseImage (Image, TRUE);
   1905   }
   1906 
   1907 Done:
   1908   return Status;
   1909 }
   1910 
   1911 
   1912 
   1913 /**
   1914   Unload the specified image.
   1915 
   1916   @param  This                    Indicates the calling context.
   1917   @param  ImageHandle             The specified image handle.
   1918 
   1919   @retval EFI_INVALID_PARAMETER   Image handle is NULL.
   1920   @retval EFI_UNSUPPORTED         Attempt to unload an unsupported image.
   1921   @retval EFI_SUCCESS             Image successfully unloaded.
   1922 
   1923 **/
   1924 EFI_STATUS
   1925 EFIAPI
   1926 CoreUnloadImageEx (
   1927   IN EFI_PE32_IMAGE_PROTOCOL  *This,
   1928   IN EFI_HANDLE                         ImageHandle
   1929   )
   1930 {
   1931   return CoreUnloadImage (ImageHandle);
   1932 }
   1933