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 *
GetMachineTypeName(UINT16 MachineType)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
CoreInitializeImageServices(IN VOID * HobStart)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
CoreReadImageFile(IN VOID * UserHandle,IN UINTN Offset,IN OUT UINTN * ReadSize,OUT VOID * Buffer)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
CheckAndMarkFixLoadingMemoryUsageBitMap(IN EFI_PHYSICAL_ADDRESS ImageBase,IN UINTN ImageSize)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
GetPeCoffImageFixLoadingAssignedAddress(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT * ImageContext)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
CoreLoadPeImage(IN BOOLEAN BootPolicy,IN VOID * Pe32Handle,IN LOADED_IMAGE_PRIVATE_DATA * Image,IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,OUT EFI_PHYSICAL_ADDRESS * EntryPoint OPTIONAL,IN UINT32 Attribute)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 *
CoreLoadedImageInfo(IN EFI_HANDLE ImageHandle)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
CoreUnloadAndCloseImage(IN LOADED_IMAGE_PRIVATE_DATA * Image,IN BOOLEAN FreePage)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
CoreLoadImageCommon(IN BOOLEAN BootPolicy,IN EFI_HANDLE ParentImageHandle,IN EFI_DEVICE_PATH_PROTOCOL * FilePath,IN VOID * SourceBuffer OPTIONAL,IN UINTN SourceSize,IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,IN OUT UINTN * NumberOfPages OPTIONAL,OUT EFI_HANDLE * ImageHandle,OUT EFI_PHYSICAL_ADDRESS * EntryPoint OPTIONAL,IN UINT32 Attribute)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
CoreLoadImage(IN BOOLEAN BootPolicy,IN EFI_HANDLE ParentImageHandle,IN EFI_DEVICE_PATH_PROTOCOL * FilePath,IN VOID * SourceBuffer OPTIONAL,IN UINTN SourceSize,OUT EFI_HANDLE * ImageHandle)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
CoreLoadImageEx(IN EFI_PE32_IMAGE_PROTOCOL * This,IN EFI_HANDLE ParentImageHandle,IN EFI_DEVICE_PATH_PROTOCOL * FilePath,IN VOID * SourceBuffer OPTIONAL,IN UINTN SourceSize,IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,OUT UINTN * NumberOfPages OPTIONAL,OUT EFI_HANDLE * ImageHandle,OUT EFI_PHYSICAL_ADDRESS * EntryPoint OPTIONAL,IN UINT32 Attribute)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
CoreStartImage(IN EFI_HANDLE ImageHandle,OUT UINTN * ExitDataSize,OUT CHAR16 ** ExitData OPTIONAL)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
CoreExit(IN EFI_HANDLE ImageHandle,IN EFI_STATUS Status,IN UINTN ExitDataSize,IN CHAR16 * ExitData OPTIONAL)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
CoreUnloadImage(IN EFI_HANDLE ImageHandle)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
CoreUnloadImageEx(IN EFI_PE32_IMAGE_PROTOCOL * This,IN EFI_HANDLE ImageHandle)1926 CoreUnloadImageEx (
1927   IN EFI_PE32_IMAGE_PROTOCOL  *This,
1928   IN EFI_HANDLE                         ImageHandle
1929   )
1930 {
1931   return CoreUnloadImage (ImageHandle);
1932 }
1933