3 Core image handling services to load and unload PeImage.
5 Copyright (c) 2006 - 2008, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 LOADED_IMAGE_PRIVATE_DATA
*mCurrentImage
= NULL
;
23 LOAD_PE32_IMAGE_PRIVATE_DATA mLoadPe32PrivateData
= {
24 LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE
,
34 // This code is needed to build the Image handle for the DXE Core
36 LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage
= {
37 LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
, // Signature
39 EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
, // Image type
40 TRUE
, // If entrypoint has been called
43 EFI_LOADED_IMAGE_INFORMATION_REVISION
, // Revision
44 NULL
, // Parent handle
45 NULL
, // System handle
47 NULL
, // Device handle
56 EfiBootServicesCode
, // ImageCodeType
57 EfiBootServicesData
// ImageDataType
59 (EFI_PHYSICAL_ADDRESS
)0, // ImageBasePage
63 EFI_SUCCESS
, // Status
71 NULL
// LoadedImageDevicePath
76 CoreInitializeImageServices (
83 Add the Image Services to EFI Boot Services Table and install the protocol
84 interfaces for this image.
88 HobStart - The HOB to initialize
97 LOADED_IMAGE_PRIVATE_DATA
*Image
;
98 EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress
;
99 UINT64 DxeCoreImageLength
;
100 VOID
*DxeCoreEntryPoint
;
101 EFI_PEI_HOB_POINTERS DxeCoreHob
;
103 // Searching for image hob
105 DxeCoreHob
.Raw
= HobStart
;
106 while ((DxeCoreHob
.Raw
= GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, DxeCoreHob
.Raw
)) != NULL
) {
107 if (CompareGuid (&DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.Name
, &gEfiHobMemoryAllocModuleGuid
)) {
113 DxeCoreHob
.Raw
= GET_NEXT_HOB (DxeCoreHob
);
115 ASSERT (DxeCoreHob
.Raw
!= NULL
);
117 DxeCoreImageBaseAddress
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryBaseAddress
;
118 DxeCoreImageLength
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryLength
;
119 DxeCoreEntryPoint
= (VOID
*) (UINTN
) DxeCoreHob
.MemoryAllocationModule
->EntryPoint
;
120 gDxeCoreFileName
= &DxeCoreHob
.MemoryAllocationModule
->ModuleName
;
122 // Initialize the fields for an internal driver
124 Image
= &mCorePrivateImage
;
126 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)DxeCoreEntryPoint
;
127 Image
->ImageBasePage
= DxeCoreImageBaseAddress
;
128 Image
->NumberOfPages
= (UINTN
)(EFI_SIZE_TO_PAGES((UINTN
)(DxeCoreImageLength
)));
129 Image
->Tpl
= gEfiCurrentTpl
;
130 Image
->Info
.SystemTable
= gDxeCoreST
;
131 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)DxeCoreImageBaseAddress
;
132 Image
->Info
.ImageSize
= DxeCoreImageLength
;
135 // Install the protocol interfaces for this image
137 Status
= CoreInstallProtocolInterface (
139 &gEfiLoadedImageProtocolGuid
,
140 EFI_NATIVE_INTERFACE
,
143 ASSERT_EFI_ERROR (Status
);
145 mCurrentImage
= Image
;
148 // Fill in DXE globals
150 gDxeCoreImageHandle
= Image
->Handle
;
151 gDxeCoreLoadedImage
= &Image
->Info
;
154 // Export DXE Core PE Loader functionality
156 return CoreInstallProtocolInterface (
157 &mLoadPe32PrivateData
.Handle
,
158 &gEfiLoadPeImageProtocolGuid
,
159 EFI_NATIVE_INTERFACE
,
160 &mLoadPe32PrivateData
.Pe32Image
166 IN BOOLEAN BootPolicy
,
168 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
169 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
170 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
177 Loads, relocates, and invokes a PE/COFF image
180 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
181 and that the boot manager is attempting to load FilePath as a boot selection.
182 Pe32Handle - The handle of PE32 image
183 Image - PE image to be loaded
184 DstBuffer - The buffer to store the image
185 EntryPoint - A pointer to the entry point
186 Attribute - The bit mask of attributes to set for the load PE image
190 EFI_SUCCESS - The file was loaded, relocated, and invoked
192 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
194 EFI_INVALID_PARAMETER - Invalid parameter
196 EFI_BUFFER_TOO_SMALL - Buffer for image is too small
201 BOOLEAN DstBufAlocated
;
204 EFI_TCG_PLATFORM_PROTOCOL
*TcgPlatformProtocol
;
205 IMAGE_FILE_HANDLE
*FHandle
;
208 ZeroMem (&Image
->ImageContext
, sizeof (Image
->ImageContext
));
210 Image
->ImageContext
.Handle
= Pe32Handle
;
211 Image
->ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)CoreReadImageFile
;
214 // Get information about the image being loaded
216 Status
= PeCoffLoaderGetImageInfo (&Image
->ImageContext
);
217 if (EFI_ERROR (Status
)) {
221 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image
->ImageContext
.Machine
)) {
222 if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image
->ImageContext
.Machine
)) {
224 // The PE/COFF loader can support loading image types that can be executed.
225 // If we loaded an image type that we can not execute return EFI_UNSUPORTED.
227 return EFI_UNSUPPORTED
;
232 // Set EFI memory type based on ImageType
234 switch (Image
->ImageContext
.ImageType
) {
235 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
:
236 Image
->ImageContext
.ImageCodeMemoryType
= EfiLoaderCode
;
237 Image
->ImageContext
.ImageDataMemoryType
= EfiLoaderData
;
239 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
:
240 Image
->ImageContext
.ImageCodeMemoryType
= EfiBootServicesCode
;
241 Image
->ImageContext
.ImageDataMemoryType
= EfiBootServicesData
;
243 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
:
244 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
:
245 Image
->ImageContext
.ImageCodeMemoryType
= EfiRuntimeServicesCode
;
246 Image
->ImageContext
.ImageDataMemoryType
= EfiRuntimeServicesData
;
249 Image
->ImageContext
.ImageError
= IMAGE_ERROR_INVALID_SUBSYSTEM
;
250 return EFI_UNSUPPORTED
;
253 // Get the image base address in the original PeImage.
255 LinkTimeBase
= (UINTN
) Image
->ImageContext
.ImageAddress
;
258 // Allocate memory of the correct memory type aligned on the required image boundry
260 DstBufAlocated
= FALSE
;
261 if (DstBuffer
== 0) {
263 // Allocate Destination Buffer as caller did not pass it in
266 if (Image
->ImageContext
.SectionAlignment
> EFI_PAGE_SIZE
) {
267 Size
= (UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
;
269 Size
= (UINTN
)Image
->ImageContext
.ImageSize
;
272 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES (Size
);
275 // If the image relocations have not been stripped, then load at any address.
276 // Otherwise load at the address at which it was linked.
278 // Memory below 1MB should be treated reserved for CSM and there should be
279 // no modules whose preferred load addresses are below 1MB.
281 Status
= EFI_OUT_OF_RESOURCES
;
282 if (Image
->ImageContext
.ImageAddress
>= 0x100000 || Image
->ImageContext
.RelocationsStripped
) {
283 Status
= CoreAllocatePages (
285 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
286 Image
->NumberOfPages
,
287 &Image
->ImageContext
.ImageAddress
290 if (EFI_ERROR (Status
) && !Image
->ImageContext
.RelocationsStripped
) {
291 Status
= CoreAllocatePages (
293 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
294 Image
->NumberOfPages
,
295 &Image
->ImageContext
.ImageAddress
298 if (EFI_ERROR (Status
)) {
301 DstBufAlocated
= TRUE
;
304 // Caller provided the destination buffer
307 if (Image
->ImageContext
.RelocationsStripped
&& (Image
->ImageContext
.ImageAddress
!= DstBuffer
)) {
309 // If the image relocations were stripped, and the caller provided a
310 // destination buffer address that does not match the address that the
311 // image is linked at, then the image cannot be loaded.
313 return EFI_INVALID_PARAMETER
;
316 if (Image
->NumberOfPages
!= 0 &&
317 Image
->NumberOfPages
<
318 (EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
))) {
319 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
320 return EFI_BUFFER_TOO_SMALL
;
323 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
324 Image
->ImageContext
.ImageAddress
= DstBuffer
;
327 Image
->ImageBasePage
= Image
->ImageContext
.ImageAddress
;
328 Image
->ImageContext
.ImageAddress
=
329 (Image
->ImageContext
.ImageAddress
+ Image
->ImageContext
.SectionAlignment
- 1) &
330 ~((UINTN
)Image
->ImageContext
.SectionAlignment
- 1);
333 // Load the image from the file into the allocated memory
335 Status
= PeCoffLoaderLoadImage (&Image
->ImageContext
);
336 if (EFI_ERROR (Status
)) {
341 // If this is a Runtime Driver, then allocate memory for the FixupData that
342 // is used to relocate the image when SetVirtualAddressMap() is called. The
343 // relocation is done by the Runtime AP.
345 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) {
346 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
347 Image
->ImageContext
.FixupData
= CoreAllocateRuntimePool ((UINTN
)(Image
->ImageContext
.FixupDataSize
));
348 if (Image
->ImageContext
.FixupData
== NULL
) {
349 Status
= EFI_OUT_OF_RESOURCES
;
356 // Measure the image before applying fixup
358 Status
= CoreLocateProtocol (
359 &gEfiTcgPlatformProtocolGuid
,
361 (VOID
**) &TcgPlatformProtocol
363 if (!EFI_ERROR (Status
)) {
364 FHandle
= (IMAGE_FILE_HANDLE
*) Image
->ImageContext
.Handle
;
365 Status
= TcgPlatformProtocol
->MeasurePeImage (
367 (EFI_PHYSICAL_ADDRESS
) (UINTN
) FHandle
->Source
,
370 Image
->ImageContext
.ImageType
,
371 Image
->Info
.DeviceHandle
,
375 ASSERT_EFI_ERROR (Status
);
379 // Relocate the image in memory
381 Status
= PeCoffLoaderRelocateImage (&Image
->ImageContext
);
382 if (EFI_ERROR (Status
)) {
387 // Flush the Instruction Cache
389 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
, (UINTN
)Image
->ImageContext
.ImageSize
);
392 // Copy the machine type from the context to the image private data. This
393 // is needed during image unload to know if we should call an EBC protocol
394 // to unload the image.
396 Image
->Machine
= Image
->ImageContext
.Machine
;
399 // Get the image entry point. If it's an EBC image, then call into the
400 // interpreter to create a thunk for the entry point and use the returned
401 // value for the entry point.
403 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)Image
->ImageContext
.EntryPoint
;
404 if (Image
->ImageContext
.Machine
== EFI_IMAGE_MACHINE_EBC
) {
406 // Locate the EBC interpreter protocol
408 Status
= CoreLocateProtocol (&gEfiEbcProtocolGuid
, NULL
, (VOID
**)&Image
->Ebc
);
409 if (EFI_ERROR(Status
)) {
414 // Register a callback for flushing the instruction cache so that created
415 // thunks can be flushed.
417 Status
= Image
->Ebc
->RegisterICacheFlush (Image
->Ebc
, (EBC_ICACHE_FLUSH
)InvalidateInstructionCacheRange
);
418 if (EFI_ERROR(Status
)) {
423 // Create a thunk for the image's entry point. This will be the new
424 // entry point for the image.
426 Status
= Image
->Ebc
->CreateThunk (
429 (VOID
*)(UINTN
)Image
->ImageContext
.EntryPoint
,
430 (VOID
**)&Image
->EntryPoint
432 if (EFI_ERROR(Status
)) {
438 // Fill in the image information for the Loaded Image Protocol
440 Image
->Type
= Image
->ImageContext
.ImageType
;
441 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
;
442 Image
->Info
.ImageSize
= Image
->ImageContext
.ImageSize
;
443 Image
->Info
.ImageCodeType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
);
444 Image
->Info
.ImageDataType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageDataMemoryType
);
445 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) {
446 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
448 // Make a list off all the RT images so we can let the RT AP know about them.
450 Image
->RuntimeData
= CoreAllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY
));
451 if (Image
->RuntimeData
== NULL
) {
454 Image
->RuntimeData
->ImageBase
= Image
->Info
.ImageBase
;
455 Image
->RuntimeData
->ImageSize
= (UINT64
) (Image
->Info
.ImageSize
);
456 Image
->RuntimeData
->RelocationData
= Image
->ImageContext
.FixupData
;
457 Image
->RuntimeData
->Handle
= Image
->Handle
;
458 InsertTailList (&gRuntime
->ImageHead
, &Image
->RuntimeData
->Link
);
463 // Fill in the entry point of the image if it is available
465 if (EntryPoint
!= NULL
) {
466 *EntryPoint
= Image
->ImageContext
.EntryPoint
;
470 // Print the load address and the PDB file name if it is available
477 CHAR8 EfiFileName
[256];
479 if (Image
->ImageContext
.Machine
!= IMAGE_FILE_MACHINE_IA64
) {
480 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
,
481 "Loading driver at 0x%10p EntryPoint=0x%10p ",
482 (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
,
483 (VOID
*)(UINTN
)Image
->ImageContext
.EntryPoint
));
486 // For IPF Image, the real entry point should be print.
488 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
,
489 "Loading driver at 0x%10p EntryPoint=0x%10p ",
490 (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
,
491 (VOID
*)(UINTN
)(*(UINT64
*)(UINTN
)Image
->ImageContext
.EntryPoint
)));
495 // Print Module Name by Pdb file path
497 if (Image
->ImageContext
.PdbPointer
!= NULL
) {
499 for (Index
= 0; Image
->ImageContext
.PdbPointer
[Index
] != 0; Index
++) {
500 if (Image
->ImageContext
.PdbPointer
[Index
] == '\\') {
501 StartIndex
= Index
+ 1;
505 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
507 for (Index
= 0; Index
< sizeof (EfiFileName
); Index
++) {
508 EfiFileName
[Index
] = Image
->ImageContext
.PdbPointer
[Index
+ StartIndex
];
509 if (EfiFileName
[Index
] == 0) {
510 EfiFileName
[Index
] = '.';
512 if (EfiFileName
[Index
] == '.') {
513 EfiFileName
[Index
+ 1] = 'e';
514 EfiFileName
[Index
+ 2] = 'f';
515 EfiFileName
[Index
+ 3] = 'i';
516 EfiFileName
[Index
+ 4] = 0;
520 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "%a", EfiFileName
)); // &Image->ImageContext.PdbPointer[StartIndex]));
522 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "\n"));
534 if (DstBufAlocated
) {
535 CoreFreePages (Image
->ImageContext
.ImageAddress
, Image
->NumberOfPages
);
538 if (Image
->ImageContext
.FixupData
!= NULL
) {
539 CoreFreePool (Image
->ImageContext
.FixupData
);
546 LOADED_IMAGE_PRIVATE_DATA
*
547 CoreLoadedImageInfo (
548 IN EFI_HANDLE ImageHandle
554 Get the image's private data from its handle.
558 ImageHandle - The image handle
562 Return the image private data associated with ImageHandle.
567 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
568 LOADED_IMAGE_PRIVATE_DATA
*Image
;
570 Status
= CoreHandleProtocol (
572 &gEfiLoadedImageProtocolGuid
,
573 (VOID
**)&LoadedImage
575 if (!EFI_ERROR (Status
)) {
576 Image
= LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage
);
578 DEBUG ((EFI_D_LOAD
, "CoreLoadedImageInfo: Not an ImageHandle %x\n", ImageHandle
));
587 CoreLoadImageCommon (
588 IN BOOLEAN BootPolicy
,
589 IN EFI_HANDLE ParentImageHandle
,
590 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
591 IN VOID
*SourceBuffer OPTIONAL
,
593 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
594 IN OUT UINTN
*NumberOfPages OPTIONAL
,
595 OUT EFI_HANDLE
*ImageHandle
,
596 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
603 Loads an EFI image into memory and returns a handle to the image.
607 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
608 and that the boot manager is attempting to load FilePath as a boot selection.
609 ParentImageHandle - The caller's image handle.
610 FilePath - The specific file path from which the image is loaded.
611 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
612 the image to be loaded.
613 SourceSize - The size in bytes of SourceBuffer.
614 DstBuffer - The buffer to store the image
615 NumberOfPages - If not NULL, it inputs a pointer to the page number of DstBuffer and outputs
616 a pointer to the page number of the image. If this number is not enough,
617 return EFI_BUFFER_TOO_SMALL and this parameter contains the required number.
618 ImageHandle - Pointer to the returned image handle that is created when the image
619 is successfully loaded.
620 EntryPoint - A pointer to the entry point
621 Attribute - The bit mask of attributes to set for the load PE image
625 EFI_SUCCESS - The image was loaded into memory.
626 EFI_NOT_FOUND - The FilePath was not found.
627 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
628 EFI_BUFFER_TOO_SMALL - The buffer is too small
629 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
630 parsed to locate the proper protocol for loading the file.
631 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
634 LOADED_IMAGE_PRIVATE_DATA
*Image
;
635 LOADED_IMAGE_PRIVATE_DATA
*ParentImage
;
636 IMAGE_FILE_HANDLE FHand
;
638 EFI_STATUS SecurityStatus
;
639 EFI_HANDLE DeviceHandle
;
640 UINT32 AuthenticationStatus
;
641 EFI_DEVICE_PATH_PROTOCOL
*OriginalFilePath
;
642 EFI_DEVICE_PATH_PROTOCOL
*HandleFilePath
;
645 SecurityStatus
= EFI_SUCCESS
;
647 ASSERT (gEfiCurrentTpl
< TPL_NOTIFY
);
651 // The caller must pass in a valid ParentImageHandle
653 if (ImageHandle
== NULL
|| ParentImageHandle
== NULL
) {
654 return EFI_INVALID_PARAMETER
;
657 ParentImage
= CoreLoadedImageInfo (ParentImageHandle
);
658 if (ParentImage
== NULL
) {
659 DEBUG((EFI_D_LOAD
|EFI_D_ERROR
, "LoadImageEx: Parent handle not an image handle\n"));
660 return EFI_INVALID_PARAMETER
;
664 // Get simple read access to the source file
666 OriginalFilePath
= FilePath
;
667 Status
= CoreOpenImageFile (
674 &AuthenticationStatus
676 if (Status
== EFI_ALREADY_STARTED
) {
679 } else if (EFI_ERROR (Status
)) {
684 // Verify the Authentication Status through the Security Architectural Protocol
686 if ((gSecurity
!= NULL
) && (OriginalFilePath
!= NULL
)) {
687 SecurityStatus
= gSecurity
->FileAuthenticationState (
689 AuthenticationStatus
,
692 if (EFI_ERROR (SecurityStatus
) && SecurityStatus
!= EFI_SECURITY_VIOLATION
) {
693 Status
= SecurityStatus
;
701 // Allocate a new image structure
703 Image
= CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA
));
705 return EFI_OUT_OF_RESOURCES
;
709 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
711 FilePath
= OriginalFilePath
;
712 Status
= CoreHandleProtocol (DeviceHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&HandleFilePath
);
713 if (!EFI_ERROR (Status
)) {
714 FilePathSize
= CoreDevicePathSize (HandleFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
715 FilePath
= (EFI_DEVICE_PATH_PROTOCOL
*) ( ((UINT8
*)FilePath
) + FilePathSize
);
719 // Initialize the fields for an internal driver
721 Image
->Signature
= LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
;
722 Image
->Info
.SystemTable
= gDxeCoreST
;
723 Image
->Info
.DeviceHandle
= DeviceHandle
;
724 Image
->Info
.Revision
= EFI_LOADED_IMAGE_INFORMATION_REVISION
;
725 Image
->Info
.FilePath
= CoreDuplicateDevicePath (FilePath
);
726 Image
->Info
.ParentHandle
= ParentImageHandle
;
729 if (NumberOfPages
!= NULL
) {
730 Image
->NumberOfPages
= *NumberOfPages
;
732 Image
->NumberOfPages
= 0 ;
736 // Install the protocol interfaces for this image
737 // don't fire notifications yet
739 Status
= CoreInstallProtocolInterfaceNotify (
741 &gEfiLoadedImageProtocolGuid
,
742 EFI_NATIVE_INTERFACE
,
746 if (EFI_ERROR (Status
)) {
751 // Load the image. If EntryPoint is Null, it will not be set.
753 Status
= CoreLoadPeImage (BootPolicy
, &FHand
, Image
, DstBuffer
, EntryPoint
, Attribute
);
754 if (EFI_ERROR (Status
)) {
755 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_OUT_OF_RESOURCES
)) {
756 if (NumberOfPages
!= NULL
) {
757 *NumberOfPages
= Image
->NumberOfPages
;
763 if (NumberOfPages
!= NULL
) {
764 *NumberOfPages
= Image
->NumberOfPages
;
768 // Register the image in the Debug Image Info Table if the attribute is set
770 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
) {
771 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL
, &Image
->Info
, Image
->Handle
);
775 //Reinstall loaded image protocol to fire any notifications
777 Status
= CoreReinstallProtocolInterface (
779 &gEfiLoadedImageProtocolGuid
,
783 if (EFI_ERROR (Status
)) {
788 // If DevicePath parameter to the LoadImage() is not NULL, then make a copy of DevicePath,
789 // otherwise Loaded Image Device Path Protocol is installed with a NULL interface pointer.
791 if (OriginalFilePath
!= NULL
) {
792 Image
->LoadedImageDevicePath
= CoreDuplicateDevicePath (OriginalFilePath
);
796 // Install Loaded Image Device Path Protocol onto the image handle of a PE/COFE image
798 Status
= CoreInstallProtocolInterface (
800 &gEfiLoadedImageDevicePathProtocolGuid
,
801 EFI_NATIVE_INTERFACE
,
802 Image
->LoadedImageDevicePath
804 if (EFI_ERROR (Status
)) {
809 // Success. Return the image handle
811 *ImageHandle
= Image
->Handle
;
815 // All done accessing the source file
816 // If we allocated the Source buffer, free it
818 if (FHand
.FreeBuffer
) {
819 CoreFreePool (FHand
.Source
);
823 // There was an error. If there's an Image structure, free it
825 if (EFI_ERROR (Status
)) {
827 CoreUnloadAndCloseImage (Image
, (BOOLEAN
)(DstBuffer
== 0));
830 } else if (EFI_ERROR (SecurityStatus
)) {
831 Status
= SecurityStatus
;
842 IN BOOLEAN BootPolicy
,
843 IN EFI_HANDLE ParentImageHandle
,
844 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
845 IN VOID
*SourceBuffer OPTIONAL
,
847 OUT EFI_HANDLE
*ImageHandle
853 Loads an EFI image into memory and returns a handle to the image.
857 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
858 and that the boot manager is attempting to load FilePath as a boot selection.
859 ParentImageHandle - The caller's image handle.
860 FilePath - The specific file path from which the image is loaded.
861 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
862 the image to be loaded.
863 SourceSize - The size in bytes of SourceBuffer.
864 ImageHandle - Pointer to the returned image handle that is created when the image
865 is successfully loaded.
869 EFI_SUCCESS - The image was loaded into memory.
870 EFI_NOT_FOUND - The FilePath was not found.
871 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
872 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
873 parsed to locate the proper protocol for loading the file.
874 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
879 PERF_START (NULL
, "LoadImage", NULL
, 0);
881 Status
= CoreLoadImageCommon (
887 (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
,
891 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
| EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
894 PERF_END (NULL
, "LoadImage", NULL
, 0);
903 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
904 IN EFI_HANDLE ParentImageHandle
,
905 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
906 IN VOID
*SourceBuffer OPTIONAL
,
908 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
909 OUT UINTN
*NumberOfPages OPTIONAL
,
910 OUT EFI_HANDLE
*ImageHandle
,
911 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
918 Loads an EFI image into memory and returns a handle to the image with extended parameters.
922 This - Calling context
923 ParentImageHandle - The caller's image handle.
924 FilePath - The specific file path from which the image is loaded.
925 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
926 the image to be loaded.
927 SourceSize - The size in bytes of SourceBuffer.
928 DstBuffer - The buffer to store the image.
929 NumberOfPages - For input, specifies the space size of the image by caller if not NULL.
930 For output, specifies the actual space size needed.
931 ImageHandle - Image handle for output.
932 EntryPoint - Image entry point for output.
933 Attribute - The bit mask of attributes to set for the load PE image.
937 EFI_SUCCESS - The image was loaded into memory.
938 EFI_NOT_FOUND - The FilePath was not found.
939 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
940 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
941 parsed to locate the proper protocol for loading the file.
942 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
945 return CoreLoadImageCommon (
962 IN EFI_HANDLE ImageHandle
,
963 OUT UINTN
*ExitDataSize
,
964 OUT CHAR16
**ExitData OPTIONAL
970 Transfer control to a loaded image's entry point.
974 ImageHandle - Handle of image to be started.
976 ExitDataSize - Pointer of the size to ExitData
978 ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated
979 Unicode string, optionally followed by additional binary data. The string
980 is a description that the caller may use to further indicate the reason for
985 EFI_INVALID_PARAMETER - Invalid parameter
987 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
989 EFI_SUCCESS - Successfully transfer control to the image's entry point.
994 LOADED_IMAGE_PRIVATE_DATA
*Image
;
995 LOADED_IMAGE_PRIVATE_DATA
*LastImage
;
996 UINT64 HandleDatabaseKey
;
999 Image
= CoreLoadedImageInfo (ImageHandle
);
1000 if (Image
== NULL_HANDLE
|| Image
->Started
) {
1001 return EFI_INVALID_PARAMETER
;
1005 // Don't profile Objects or invalid start requests
1007 PERF_START (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
1011 // Push the current start image context, and
1012 // link the current image to the head. This is the
1013 // only image that can call Exit()
1015 HandleDatabaseKey
= CoreGetHandleDatabaseKey ();
1016 LastImage
= mCurrentImage
;
1017 mCurrentImage
= Image
;
1018 Image
->Tpl
= gEfiCurrentTpl
;
1021 // Set long jump for Exit() support
1022 // JumpContext must be aligned on a CPU specific boundary.
1023 // Overallocate the buffer and force the required alignment
1025 Image
->JumpBuffer
= CoreAllocateBootServicesPool (sizeof (BASE_LIBRARY_JUMP_BUFFER
) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
1026 if (Image
->JumpBuffer
== NULL
) {
1027 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
1028 return EFI_OUT_OF_RESOURCES
;
1030 Image
->JumpContext
= ALIGN_POINTER (Image
->JumpBuffer
, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
1032 SetJumpFlag
= SetJump (Image
->JumpContext
);
1034 // The initial call to SetJump() must always return 0.
1035 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
1039 // Call the image's entry point
1041 Image
->Started
= TRUE
;
1042 Image
->Status
= Image
->EntryPoint (ImageHandle
, Image
->Info
.SystemTable
);
1045 // Add some debug information if the image returned with error.
1046 // This make the user aware and check if the driver image have already released
1047 // all the resource in this situation.
1049 DEBUG_CODE_BEGIN ();
1050 if (EFI_ERROR (Image
->Status
)) {
1051 DEBUG ((EFI_D_ERROR
, "Error: Image at %10p start failed: %r\n", Image
->Info
.ImageBase
, Image
->Status
));
1056 // If the image returns, exit it through Exit()
1058 CoreExit (ImageHandle
, Image
->Status
, 0, NULL
);
1062 // Image has completed. Verify the tpl is the same
1064 ASSERT (Image
->Tpl
== gEfiCurrentTpl
);
1065 CoreRestoreTpl (Image
->Tpl
);
1067 CoreFreePool (Image
->JumpBuffer
);
1070 // Pop the current start image context
1072 mCurrentImage
= LastImage
;
1075 // Go connect any handles that were created or modified while the image executed.
1077 CoreConnectHandlesByKey (HandleDatabaseKey
);
1080 // Handle the image's returned ExitData
1082 DEBUG_CODE_BEGIN ();
1083 if (Image
->ExitDataSize
!= 0 || Image
->ExitData
!= NULL
) {
1087 "StartImage: ExitDataSize %d, ExitData %x",
1088 Image
->ExitDataSize
,
1091 if (Image
->ExitData
!= NULL
) {
1092 DEBUG ((EFI_D_LOAD
, " (%hs)", Image
->ExitData
));
1094 DEBUG ((EFI_D_LOAD
, "\n"));
1099 // Return the exit data to the caller
1101 if (ExitData
!= NULL
&& ExitDataSize
!= NULL
) {
1102 *ExitDataSize
= Image
->ExitDataSize
;
1103 *ExitData
= Image
->ExitData
;
1106 // Caller doesn't want the exit data, free it
1108 CoreFreePool (Image
->ExitData
);
1109 Image
->ExitData
= NULL
;
1113 // Save the Status because Image will get destroyed if it is unloaded.
1115 Status
= Image
->Status
;
1118 // If the image returned an error, or if the image is an application
1121 if (EFI_ERROR (Image
->Status
) || Image
->Type
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1122 CoreUnloadAndCloseImage (Image
, TRUE
);
1128 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
1134 CoreUnloadAndCloseImage (
1135 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
1140 Routine Description:
1142 Unloads EFI image from memory.
1147 FreePage - Free allocated pages
1157 EFI_HANDLE
*HandleBuffer
;
1159 EFI_GUID
**ProtocolGuidArray
;
1161 UINTN ProtocolIndex
;
1162 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfo
;
1163 UINTN OpenInfoCount
;
1164 UINTN OpenInfoIndex
;
1166 if (Image
->Ebc
!= NULL
) {
1168 // If EBC protocol exists we must perform cleanups for this image.
1170 Image
->Ebc
->UnloadImage (Image
->Ebc
, Image
->Handle
);
1174 // Unload image, free Image->ImageContext->ModHandle
1176 PeCoffLoaderUnloadImage (&Image
->ImageContext
);
1179 // Free our references to the image handle
1181 if (Image
->Handle
!= NULL_HANDLE
) {
1183 Status
= CoreLocateHandleBuffer (
1190 if (!EFI_ERROR (Status
)) {
1191 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
1192 Status
= CoreProtocolsPerHandle (
1193 HandleBuffer
[HandleIndex
],
1197 if (!EFI_ERROR (Status
)) {
1198 for (ProtocolIndex
= 0; ProtocolIndex
< ArrayCount
; ProtocolIndex
++) {
1199 Status
= CoreOpenProtocolInformation (
1200 HandleBuffer
[HandleIndex
],
1201 ProtocolGuidArray
[ProtocolIndex
],
1205 if (!EFI_ERROR (Status
)) {
1206 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
1207 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== Image
->Handle
) {
1208 Status
= CoreCloseProtocol (
1209 HandleBuffer
[HandleIndex
],
1210 ProtocolGuidArray
[ProtocolIndex
],
1212 OpenInfo
[OpenInfoIndex
].ControllerHandle
1216 if (OpenInfo
!= NULL
) {
1217 CoreFreePool(OpenInfo
);
1221 if (ProtocolGuidArray
!= NULL
) {
1222 CoreFreePool(ProtocolGuidArray
);
1226 if (HandleBuffer
!= NULL
) {
1227 CoreFreePool (HandleBuffer
);
1231 CoreRemoveDebugImageInfoEntry (Image
->Handle
);
1233 Status
= CoreUninstallProtocolInterface (
1235 &gEfiLoadedImageDevicePathProtocolGuid
,
1236 Image
->LoadedImageDevicePath
1239 Status
= CoreUninstallProtocolInterface (
1241 &gEfiLoadedImageProtocolGuid
,
1247 if (Image
->RuntimeData
!= NULL
) {
1248 if (Image
->RuntimeData
->Link
.ForwardLink
!= NULL
) {
1250 // Remove the Image from the Runtime Image list as we are about to Free it!
1252 RemoveEntryList (&Image
->RuntimeData
->Link
);
1254 CoreFreePool (Image
->RuntimeData
);
1258 // Free the Image from memory
1260 if ((Image
->ImageBasePage
!= 0) && FreePage
) {
1261 CoreFreePages (Image
->ImageBasePage
, Image
->NumberOfPages
);
1265 // Done with the Image structure
1267 if (Image
->Info
.FilePath
!= NULL
) {
1268 CoreFreePool (Image
->Info
.FilePath
);
1271 if (Image
->LoadedImageDevicePath
!= NULL
) {
1272 CoreFreePool (Image
->LoadedImageDevicePath
);
1275 if (Image
->FixupData
!= NULL
) {
1276 CoreFreePool (Image
->FixupData
);
1279 CoreFreePool (Image
);
1287 IN EFI_HANDLE ImageHandle
,
1288 IN EFI_STATUS Status
,
1289 IN UINTN ExitDataSize
,
1290 IN CHAR16
*ExitData OPTIONAL
1294 Routine Description:
1296 Terminates the currently loaded EFI image and returns control to boot services.
1300 ImageHandle - Handle that identifies the image. This parameter is passed to the image
1302 Status - The image's exit code.
1303 ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is
1305 ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string,
1306 optionally followed by additional binary data. The string is a
1307 description that the caller may use to further indicate the reason for
1312 EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image.
1314 EFI_SUCCESS - Successfully terminates the currently loaded EFI image.
1316 EFI_ACCESS_DENIED - Should never reach there.
1318 EFI_OUT_OF_RESOURCES - Could not allocate pool
1322 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1326 // Prevent possible reentrance to this function
1327 // for the same ImageHandle
1329 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1331 Image
= CoreLoadedImageInfo (ImageHandle
);
1332 if (Image
== NULL_HANDLE
) {
1333 Status
= EFI_INVALID_PARAMETER
;
1337 if (!Image
->Started
) {
1339 // The image has not been started so just free its resources
1341 CoreUnloadAndCloseImage (Image
, TRUE
);
1342 Status
= EFI_SUCCESS
;
1347 // Image has been started, verify this image can exit
1349 if (Image
!= mCurrentImage
) {
1350 DEBUG ((EFI_D_LOAD
|EFI_D_ERROR
, "Exit: Image is not exitable image\n"));
1351 Status
= EFI_INVALID_PARAMETER
;
1358 Image
->Status
= Status
;
1361 // If there's ExitData info, move it
1363 if (ExitData
!= NULL
) {
1364 Image
->ExitDataSize
= ExitDataSize
;
1365 Image
->ExitData
= CoreAllocateBootServicesPool (Image
->ExitDataSize
);
1366 if (Image
->ExitData
== NULL
) {
1367 Status
= EFI_OUT_OF_RESOURCES
;
1370 CopyMem (Image
->ExitData
, ExitData
, Image
->ExitDataSize
);
1373 CoreRestoreTpl (OldTpl
);
1375 // return to StartImage
1377 LongJump (Image
->JumpContext
, (UINTN
)-1);
1380 // If we return from LongJump, then it is an error
1383 Status
= EFI_ACCESS_DENIED
;
1385 CoreRestoreTpl (OldTpl
);
1394 IN EFI_HANDLE ImageHandle
1398 Routine Description:
1404 ImageHandle - Handle that identifies the image to be unloaded.
1408 EFI_SUCCESS - The image has been unloaded.
1409 EFI_UNSUPPORTED - The image has been sarted, and does not support unload.
1410 EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle.
1415 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1419 // Prevent possible reentrance to this function
1420 // for the same ImageHandle
1422 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1424 Image
= CoreLoadedImageInfo (ImageHandle
);
1425 if (Image
== NULL
) {
1427 // The image handle is not valid
1429 Status
= EFI_INVALID_PARAMETER
;
1433 if (Image
->Started
) {
1435 // The image has been started, request it to unload.
1437 Status
= EFI_UNSUPPORTED
;
1438 if (Image
->Info
.Unload
!= NULL
) {
1439 Status
= Image
->Info
.Unload (ImageHandle
);
1444 // This Image hasn't been started, thus it can be unloaded
1446 Status
= EFI_SUCCESS
;
1450 if (!EFI_ERROR (Status
)) {
1452 // if the Image was not started or Unloaded O.K. then clean up
1454 CoreUnloadAndCloseImage (Image
, TRUE
);
1458 CoreRestoreTpl (OldTpl
);
1466 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
1467 IN EFI_HANDLE ImageHandle
1471 Routine Description:
1473 Unload the specified image.
1477 This - Indicates the calling context.
1479 ImageHandle - The specified image handle.
1483 EFI_INVALID_PARAMETER - Image handle is NULL.
1485 EFI_UNSUPPORTED - Attempt to unload an unsupported image.
1487 EFI_SUCCESS - Image successfully unloaded.
1491 return CoreUnloadImage (ImageHandle
);