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