3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Core image handling services
28 // LIST of runtime images that need to be relocated.
30 LIST_ENTRY mRuntimeImageList
= INITIALIZE_LIST_HEAD_VARIABLE (mRuntimeImageList
);
32 LOADED_IMAGE_PRIVATE_DATA
*mCurrentImage
= NULL
;
34 LOAD_PE32_IMAGE_PRIVATE_DATA mLoadPe32PrivateData
= {
35 LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE
,
45 // This code is needed to build the Image handle for the DXE Core
47 LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage
= {
48 LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
, // Signature
50 EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
, // Image type
51 TRUE
, // If entrypoint has been called
54 EFI_LOADED_IMAGE_INFORMATION_REVISION
, // Revision
55 NULL
, // Parent handle
56 NULL
, // System handle
58 NULL
, // Device handle
67 EfiBootServicesCode
, // ImageCodeType
68 EfiBootServicesData
// ImageDataType
70 (EFI_PHYSICAL_ADDRESS
)0, // ImageBasePage
74 EFI_SUCCESS
, // Status
81 FALSE
, // RuntimeFixupValid
83 { NULL
, NULL
}, // Link
88 CoreInitializeImageServices (
95 Add the Image Services to EFI Boot Services Table and install the protocol
96 interfaces for this image.
100 HobStart - The HOB to initialize
109 LOADED_IMAGE_PRIVATE_DATA
*Image
;
110 EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress
;
111 UINT64 DxeCoreImageLength
;
112 VOID
*DxeCoreEntryPoint
;
113 EFI_PEI_HOB_POINTERS DxeCoreHob
;
115 // Searching for image hob
117 DxeCoreHob
.Raw
= HobStart
;
118 while ((DxeCoreHob
.Raw
= GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, DxeCoreHob
.Raw
)) != NULL
) {
119 if (CompareGuid (&DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.Name
, &gEfiHobMemoryAllocModuleGuid
)) {
125 DxeCoreHob
.Raw
= GET_NEXT_HOB (DxeCoreHob
);
127 ASSERT (DxeCoreHob
.Raw
!= NULL
);
129 DxeCoreImageBaseAddress
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryBaseAddress
;
130 DxeCoreImageLength
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryLength
;
131 DxeCoreEntryPoint
= (VOID
*) (UINTN
) DxeCoreHob
.MemoryAllocationModule
->EntryPoint
;
132 gDxeCoreFileName
= &DxeCoreHob
.MemoryAllocationModule
->ModuleName
;
134 // Initialize the fields for an internal driver
136 Image
= &mCorePrivateImage
;
138 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)DxeCoreEntryPoint
;
139 Image
->ImageBasePage
= DxeCoreImageBaseAddress
;
140 Image
->NumberOfPages
= (UINTN
)(EFI_SIZE_TO_PAGES((UINTN
)(DxeCoreImageLength
)));
141 Image
->Tpl
= gEfiCurrentTpl
;
142 Image
->Info
.SystemTable
= gST
;
143 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)DxeCoreImageBaseAddress
;
144 Image
->Info
.ImageSize
= DxeCoreImageLength
;
147 // Install the protocol interfaces for this image
149 Status
= CoreInstallProtocolInterface (
151 &gEfiLoadedImageProtocolGuid
,
152 EFI_NATIVE_INTERFACE
,
155 ASSERT_EFI_ERROR (Status
);
157 mCurrentImage
= Image
;
160 // Fill in DXE globals
162 gDxeCoreImageHandle
= Image
->Handle
;
163 gDxeCoreLoadedImage
= &Image
->Info
;
166 // Export DXE Core PE Loader functionality
168 return CoreInstallProtocolInterface (
169 &mLoadPe32PrivateData
.Handle
,
170 &gEfiLoadPeImageProtocolGuid
,
171 EFI_NATIVE_INTERFACE
,
172 &mLoadPe32PrivateData
.Pe32Image
178 CoreShutdownImageServices (
185 Transfer control of runtime images to runtime service
193 EFI_SUCCESS - Function successfully returned
198 LOADED_IMAGE_PRIVATE_DATA
*Image
;
201 // The Runtime AP is required for the core to function!
203 ASSERT (gRuntime
!= NULL
);
205 for (Link
= mRuntimeImageList
.ForwardLink
; Link
!= &mRuntimeImageList
; Link
= Link
->ForwardLink
) {
206 Image
= CR (Link
, LOADED_IMAGE_PRIVATE_DATA
, Link
, LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
);
207 if (Image
->RuntimeFixupValid
) {
208 gRuntime
->RegisterImage (
210 (UINT64
)(UINTN
)(Image
->Info
.ImageBase
),
211 (EFI_SIZE_TO_PAGES ((UINTN
)Image
->Info
.ImageSize
)),
225 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
226 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
227 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
234 Loads, relocates, and invokes a PE/COFF image
238 Pe32Handle - The handle of PE32 image
239 Image - PE image to be loaded
240 DstBuffer - The buffer to store the image
241 EntryPoint - A pointer to the entry point
242 Attribute - The bit mask of attributes to set for the load PE image
246 EFI_SUCCESS - The file was loaded, relocated, and invoked
248 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
250 EFI_INVALID_PARAMETER - Invalid parameter
252 EFI_BUFFER_TOO_SMALL - Buffer for image is too small
259 ZeroMem (&Image
->ImageContext
, sizeof (Image
->ImageContext
));
261 Image
->ImageContext
.Handle
= Pe32Handle
;
262 Image
->ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)CoreReadImageFile
;
265 // Get information about the image being loaded
267 Status
= gEfiPeiPeCoffLoader
->GetImageInfo (gEfiPeiPeCoffLoader
, &Image
->ImageContext
);
268 if (EFI_ERROR (Status
)) {
272 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image
->ImageContext
.Machine
)) {
274 // The PE/COFF loader can support loading image types that can be executed.
275 // If we loaded an image type that we can not execute return EFI_UNSUPORTED.
277 return EFI_UNSUPPORTED
;
282 // Allocate memory of the correct memory type aligned on the required image boundry
285 if (DstBuffer
== 0) {
287 // Allocate Destination Buffer as caller did not pass it in
290 if (Image
->ImageContext
.SectionAlignment
> EFI_PAGE_SIZE
) {
291 Size
= (UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
;
293 Size
= (UINTN
)Image
->ImageContext
.ImageSize
;
296 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES (Size
);
299 // If the image relocations have not been stripped, then load at any address.
300 // Otherwise load at the address at which it was linked.
302 Status
= CoreAllocatePages (
303 (Image
->ImageContext
.RelocationsStripped
) ? AllocateAddress
: AllocateAnyPages
,
304 Image
->ImageContext
.ImageCodeMemoryType
,
305 Image
->NumberOfPages
,
306 &Image
->ImageContext
.ImageAddress
308 if (EFI_ERROR (Status
)) {
312 Image
->ImageBasePage
= Image
->ImageContext
.ImageAddress
;
316 // Caller provided the destination buffer
319 if (Image
->ImageContext
.RelocationsStripped
&& (Image
->ImageContext
.ImageAddress
!= DstBuffer
)) {
321 // If the image relocations were stripped, and the caller provided a
322 // destination buffer address that does not match the address that the
323 // image is linked at, then the image cannot be loaded.
325 return EFI_INVALID_PARAMETER
;
328 if (Image
->NumberOfPages
!= 0 &&
329 Image
->NumberOfPages
<
330 (EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
))) {
331 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
332 return EFI_BUFFER_TOO_SMALL
;
335 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
336 Image
->ImageContext
.ImageAddress
= DstBuffer
;
337 Image
->ImageBasePage
= Image
->ImageContext
.ImageAddress
;
340 Image
->ImageContext
.ImageAddress
=
341 (Image
->ImageContext
.ImageAddress
+ Image
->ImageContext
.SectionAlignment
- 1) &
342 ~((UINTN
)Image
->ImageContext
.SectionAlignment
- 1);
345 // Load the image from the file into the allocated memory
347 Status
= gEfiPeiPeCoffLoader
->LoadImage (gEfiPeiPeCoffLoader
, &Image
->ImageContext
);
348 if (EFI_ERROR (Status
)) {
353 // If this is a Runtime Driver, then allocate memory for the FixupData that
354 // is used to relocate the image when SetVirtualAddressMap() is called. The
355 // relocation is done by the Runtime AP.
357 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) {
358 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
359 Image
->ImageContext
.FixupData
= CoreAllocateRuntimePool ((UINTN
)(Image
->ImageContext
.FixupDataSize
));
360 if (Image
->ImageContext
.FixupData
== NULL
) {
361 Status
= EFI_OUT_OF_RESOURCES
;
366 // Make a list off all the RT images so we can let the RT AP know about them
368 Image
->RuntimeFixupValid
= TRUE
;
369 Image
->RuntimeFixup
= Image
->ImageContext
.FixupData
;
370 InsertTailList (&mRuntimeImageList
, &Image
->Link
);
375 // Relocate the image in memory
377 Status
= gEfiPeiPeCoffLoader
->RelocateImage (gEfiPeiPeCoffLoader
, &Image
->ImageContext
);
378 if (EFI_ERROR (Status
)) {
383 // Flush the Instruction Cache
385 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
, (UINTN
)Image
->ImageContext
.ImageSize
);
388 // Copy the machine type from the context to the image private data. This
389 // is needed during image unload to know if we should call an EBC protocol
390 // to unload the image.
392 Image
->Machine
= Image
->ImageContext
.Machine
;
395 // Get the image entry point. If it's an EBC image, then call into the
396 // interpreter to create a thunk for the entry point and use the returned
397 // value for the entry point.
399 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)Image
->ImageContext
.EntryPoint
;
400 if (Image
->ImageContext
.Machine
== EFI_IMAGE_MACHINE_EBC
) {
402 // Locate the EBC interpreter protocol
404 Status
= CoreLocateProtocol (&gEfiEbcProtocolGuid
, NULL
, (VOID
**)&Image
->Ebc
);
405 if (EFI_ERROR(Status
)) {
410 // Register a callback for flushing the instruction cache so that created
411 // thunks can be flushed.
413 Status
= Image
->Ebc
->RegisterICacheFlush (Image
->Ebc
, (EBC_ICACHE_FLUSH
)InvalidateInstructionCacheRange
);
414 if (EFI_ERROR(Status
)) {
419 // Create a thunk for the image's entry point. This will be the new
420 // entry point for the image.
422 Status
= Image
->Ebc
->CreateThunk (
425 (VOID
*)(UINTN
)Image
->ImageContext
.EntryPoint
,
426 (VOID
**)&Image
->EntryPoint
428 if (EFI_ERROR(Status
)) {
434 // Fill in the image information for the Loaded Image Protocol
436 Image
->Type
= Image
->ImageContext
.ImageType
;
437 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
;
438 Image
->Info
.ImageSize
= Image
->ImageContext
.ImageSize
;
439 Image
->Info
.ImageCodeType
= Image
->ImageContext
.ImageCodeMemoryType
;
440 Image
->Info
.ImageDataType
= Image
->ImageContext
.ImageDataMemoryType
;
443 // Fill in the entry point of the image if it is available
445 if (EntryPoint
!= NULL
) {
446 *EntryPoint
= Image
->ImageContext
.EntryPoint
;
450 // Print the load address and the PDB file name if it is available
457 CHAR8 EfiFileName
[256];
459 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Loading driver at 0x%10p EntryPoint=0x%10p ", (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
, (VOID
*)(UINTN
)Image
->ImageContext
.EntryPoint
));
460 if (Image
->ImageContext
.PdbPointer
!= NULL
) {
462 for (Index
= 0; Image
->ImageContext
.PdbPointer
[Index
] != 0; Index
++) {
463 if (Image
->ImageContext
.PdbPointer
[Index
] == '\\') {
464 StartIndex
= Index
+ 1;
468 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
470 for (Index
= 0; Index
< sizeof (EfiFileName
); Index
++) {
471 EfiFileName
[Index
] = Image
->ImageContext
.PdbPointer
[Index
+ StartIndex
];
472 if (EfiFileName
[Index
] == 0) {
473 EfiFileName
[Index
] = '.';
475 if (EfiFileName
[Index
] == '.') {
476 EfiFileName
[Index
+ 1] = 'e';
477 EfiFileName
[Index
+ 2] = 'f';
478 EfiFileName
[Index
+ 3] = 'i';
479 EfiFileName
[Index
+ 4] = 0;
483 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "%a", EfiFileName
)); // &Image->ImageContext.PdbPointer[StartIndex]));
485 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "\n"));
495 CoreFreePages (Image
->ImageContext
.ImageAddress
, Image
->NumberOfPages
);
500 LOADED_IMAGE_PRIVATE_DATA
*
501 CoreLoadedImageInfo (
502 IN EFI_HANDLE ImageHandle
508 Get the image's private data from its handle.
512 ImageHandle - The image handle
516 Return the image private data associated with ImageHandle.
521 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
522 LOADED_IMAGE_PRIVATE_DATA
*Image
;
524 Status
= CoreHandleProtocol (
526 &gEfiLoadedImageProtocolGuid
,
527 (VOID
**)&LoadedImage
529 if (!EFI_ERROR (Status
)) {
530 Image
= LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage
);
532 DEBUG ((EFI_D_LOAD
, "CoreLoadedImageInfo: Not an ImageHandle %x\n", ImageHandle
));
541 CoreLoadImageCommon (
542 IN BOOLEAN BootPolicy
,
543 IN EFI_HANDLE ParentImageHandle
,
544 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
545 IN VOID
*SourceBuffer OPTIONAL
,
547 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
548 IN OUT UINTN
*NumberOfPages OPTIONAL
,
549 OUT EFI_HANDLE
*ImageHandle
,
550 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
557 Loads an EFI image into memory and returns a handle to the image.
561 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
562 and that the boot manager is attempting to load FilePath as a boot selection.
563 ParentImageHandle - The caller's image handle.
564 FilePath - The specific file path from which the image is loaded.
565 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
566 the image to be loaded.
567 SourceSize - The size in bytes of SourceBuffer.
568 DstBuffer - The buffer to store the image
569 NumberOfPages - If not NULL, a pointer to the image's page number, if this number
570 is not enough, return EFI_BUFFER_TOO_SMALL and this parameter contain
572 ImageHandle - Pointer to the returned image handle that is created when the image
573 is successfully loaded.
574 EntryPoint - A pointer to the entry point
575 Attribute - The bit mask of attributes to set for the load PE image
579 EFI_SUCCESS - The image was loaded into memory.
580 EFI_NOT_FOUND - The FilePath was not found.
581 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
582 EFI_BUFFER_TOO_SMALL - The buffer is too small
583 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
584 parsed to locate the proper protocol for loading the file.
585 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
588 LOADED_IMAGE_PRIVATE_DATA
*Image
;
589 LOADED_IMAGE_PRIVATE_DATA
*ParentImage
;
590 IMAGE_FILE_HANDLE FHand
;
592 EFI_STATUS SecurityStatus
;
593 EFI_HANDLE DeviceHandle
;
594 UINT32 AuthenticationStatus
;
595 EFI_DEVICE_PATH_PROTOCOL
*OriginalFilePath
;
596 EFI_DEVICE_PATH_PROTOCOL
*HandleFilePath
;
599 SecurityStatus
= EFI_SUCCESS
;
601 ASSERT (gEfiCurrentTpl
< EFI_TPL_NOTIFY
);
605 // The caller must pass in a valid ParentImageHandle
607 if (ImageHandle
== NULL
|| ParentImageHandle
== NULL
) {
608 return EFI_INVALID_PARAMETER
;
611 ParentImage
= CoreLoadedImageInfo (ParentImageHandle
);
612 if (ParentImage
== NULL
) {
613 DEBUG((EFI_D_LOAD
|EFI_D_ERROR
, "LoadImageEx: Parent handle not an image handle\n"));
614 return EFI_INVALID_PARAMETER
;
618 // Get simple read access to the source file
620 OriginalFilePath
= FilePath
;
621 Status
= CoreOpenImageFile (
628 &AuthenticationStatus
630 if (Status
== EFI_ALREADY_STARTED
) {
633 } else if (EFI_ERROR (Status
)) {
638 // Verify the Authentication Status through the Security Architectural Protocol
640 if ((gSecurity
!= NULL
) && (OriginalFilePath
!= NULL
)) {
641 SecurityStatus
= gSecurity
->FileAuthenticationState (
643 AuthenticationStatus
,
646 if (EFI_ERROR (SecurityStatus
) && SecurityStatus
!= EFI_SECURITY_VIOLATION
) {
647 Status
= SecurityStatus
;
655 // Allocate a new image structure
657 Image
= CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA
));
659 return EFI_OUT_OF_RESOURCES
;
663 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
665 Status
= CoreHandleProtocol (DeviceHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&HandleFilePath
);
666 if (!EFI_ERROR (Status
)) {
667 FilePathSize
= CoreDevicePathSize (HandleFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
668 FilePath
= (EFI_DEVICE_PATH_PROTOCOL
*) ( ((UINT8
*)FilePath
) + FilePathSize
);
672 // Initialize the fields for an internal driver
674 Image
->Signature
= LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
;
675 Image
->Info
.SystemTable
= gST
;
676 Image
->Info
.DeviceHandle
= DeviceHandle
;
677 Image
->Info
.Revision
= EFI_LOADED_IMAGE_INFORMATION_REVISION
;
678 Image
->Info
.FilePath
= CoreDuplicateDevicePath (FilePath
);
679 Image
->Info
.ParentHandle
= ParentImageHandle
;
681 if (NumberOfPages
!= NULL
) {
682 Image
->NumberOfPages
= *NumberOfPages
;
684 Image
->NumberOfPages
= 0 ;
688 // Install the protocol interfaces for this image
689 // don't fire notifications yet
691 Status
= CoreInstallProtocolInterfaceNotify (
693 &gEfiLoadedImageProtocolGuid
,
694 EFI_NATIVE_INTERFACE
,
698 if (EFI_ERROR (Status
)) {
703 // Load the image. If EntryPoint is Null, it will not be set.
705 Status
= CoreLoadPeImage (&FHand
, Image
, DstBuffer
, EntryPoint
, Attribute
);
706 if (EFI_ERROR (Status
)) {
707 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_OUT_OF_RESOURCES
)) {
708 if (NumberOfPages
!= NULL
) {
709 *NumberOfPages
= Image
->NumberOfPages
;
716 // Register the image in the Debug Image Info Table if the attribute is set
718 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
) {
719 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL
, &Image
->Info
, Image
->Handle
);
723 //Reinstall loaded image protocol to fire any notifications
725 Status
= CoreReinstallProtocolInterface (
727 &gEfiLoadedImageProtocolGuid
,
731 if (EFI_ERROR (Status
)) {
737 // Success. Return the image handle
739 *ImageHandle
= Image
->Handle
;
743 // All done accessing the source file
744 // If we allocated the Source buffer, free it
746 if (FHand
.FreeBuffer
) {
747 CoreFreePool (FHand
.Source
);
751 // There was an error. If there's an Image structure, free it
753 if (EFI_ERROR (Status
)) {
755 CoreUnloadAndCloseImage (Image
, (BOOLEAN
)(DstBuffer
== 0));
758 } else if (EFI_ERROR (SecurityStatus
)) {
759 Status
= SecurityStatus
;
770 IN BOOLEAN BootPolicy
,
771 IN EFI_HANDLE ParentImageHandle
,
772 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
773 IN VOID
*SourceBuffer OPTIONAL
,
775 OUT EFI_HANDLE
*ImageHandle
781 Loads an EFI image into memory and returns a handle to the image.
785 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
786 and that the boot manager is attempting to load FilePath as a boot selection.
787 ParentImageHandle - The caller's image handle.
788 FilePath - The specific file path from which the image is loaded.
789 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
790 the image to be loaded.
791 SourceSize - The size in bytes of SourceBuffer.
792 ImageHandle - Pointer to the returned image handle that is created when the image
793 is successfully loaded.
797 EFI_SUCCESS - The image was loaded into memory.
798 EFI_NOT_FOUND - The FilePath was not found.
799 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
800 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
801 parsed to locate the proper protocol for loading the file.
802 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
807 PERF_START (NULL
, "LoadImage", NULL
, 0);
809 Status
= CoreLoadImageCommon (
815 (EFI_PHYSICAL_ADDRESS
)NULL
,
819 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
| EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
822 PERF_END (NULL
, "LoadImage", NULL
, 0);
831 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
832 IN EFI_HANDLE ParentImageHandle
,
833 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
834 IN VOID
*SourceBuffer OPTIONAL
,
836 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
837 OUT UINTN
*NumberOfPages OPTIONAL
,
838 OUT EFI_HANDLE
*ImageHandle
,
839 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
846 Loads an EFI image into memory and returns a handle to the image with extended parameters.
850 This - Calling context
851 ParentImageHandle - The caller's image handle.
852 FilePath - The specific file path from which the image is loaded.
853 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
854 the image to be loaded.
855 SourceSize - The size in bytes of SourceBuffer.
856 DstBuffer - The buffer to store the image.
857 NumberOfPages - For input, specifies the space size of the image by caller if not NULL.
858 For output, specifies the actual space size needed.
859 ImageHandle - Image handle for output.
860 EntryPoint - Image entry point for output.
861 Attribute - The bit mask of attributes to set for the load PE image.
865 EFI_SUCCESS - The image was loaded into memory.
866 EFI_NOT_FOUND - The FilePath was not found.
867 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
868 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
869 parsed to locate the proper protocol for loading the file.
870 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
873 return CoreLoadImageCommon (
893 IN EFI_HANDLE ImageHandle
,
894 OUT UINTN
*ExitDataSize
,
895 OUT CHAR16
**ExitData OPTIONAL
901 Transfer control to a loaded image's entry point.
905 ImageHandle - Handle of image to be started.
907 ExitDataSize - Pointer of the size to ExitData
909 ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated
910 Unicode string, optionally followed by additional binary data. The string
911 is a description that the caller may use to further indicate the reason for
916 EFI_INVALID_PARAMETER - Invalid parameter
918 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
920 EFI_SUCCESS - Successfully transfer control to the image's entry point.
925 LOADED_IMAGE_PRIVATE_DATA
*Image
;
926 LOADED_IMAGE_PRIVATE_DATA
*LastImage
;
927 UINT64 HandleDatabaseKey
;
930 Image
= CoreLoadedImageInfo (ImageHandle
);
931 if (Image
== NULL_HANDLE
|| Image
->Started
) {
932 return EFI_INVALID_PARAMETER
;
936 // Don't profile Objects or invalid start requests
938 PERF_START (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
942 // Push the current start image context, and
943 // link the current image to the head. This is the
944 // only image that can call Exit()
946 HandleDatabaseKey
= CoreGetHandleDatabaseKey ();
947 LastImage
= mCurrentImage
;
948 mCurrentImage
= Image
;
949 Image
->Tpl
= gEfiCurrentTpl
;
952 // Set long jump for Exit() support
953 // JumpContext must be aligned on a CPU specific boundary.
954 // Overallocate the buffer and force the required alignment
956 Image
->JumpBuffer
= CoreAllocateBootServicesPool (sizeof (*Image
->JumpContext
) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
957 if (Image
->JumpBuffer
== NULL
) {
958 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
959 return EFI_OUT_OF_RESOURCES
;
961 Image
->JumpContext
= (VOID
*)((UINTN
)(ALIGN_POINTER (Image
->JumpBuffer
, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
)) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
963 SetJumpFlag
= SetJump (Image
->JumpContext
);
965 // The initial call to SetJump() must always return 0.
966 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
970 // Call the image's entry point
972 Image
->Started
= TRUE
;
973 Image
->Status
= Image
->EntryPoint (ImageHandle
, Image
->Info
.SystemTable
);
976 // Add some debug information if the image returned with error.
977 // This make the user aware and check if the driver image have already released
978 // all the resource in this situation.
981 if (EFI_ERROR (Image
->Status
)) {
982 DEBUG ((EFI_D_ERROR
, "Error: Image at %10p start failed: %r\n", Image
->Info
.ImageBase
, Image
->Status
));
987 // If the image returns, exit it through Exit()
989 CoreExit (ImageHandle
, Image
->Status
, 0, NULL
);
993 // Image has completed. Verify the tpl is the same
995 ASSERT (Image
->Tpl
== gEfiCurrentTpl
);
996 CoreRestoreTpl (Image
->Tpl
);
998 CoreFreePool (Image
->JumpBuffer
);
1001 // Pop the current start image context
1003 mCurrentImage
= LastImage
;
1006 // Go connect any handles that were created or modified while the image executed.
1008 CoreConnectHandlesByKey (HandleDatabaseKey
);
1011 // Handle the image's returned ExitData
1013 DEBUG_CODE_BEGIN ();
1014 if (Image
->ExitDataSize
!= 0 || Image
->ExitData
!= NULL
) {
1018 "StartImage: ExitDataSize %d, ExitData %x",
1019 Image
->ExitDataSize
,
1022 if (Image
->ExitData
!= NULL
) {
1023 DEBUG ((EFI_D_LOAD
, " (%hs)", Image
->ExitData
));
1025 DEBUG ((EFI_D_LOAD
, "\n"));
1030 // Return the exit data to the caller
1032 if (ExitData
!= NULL
&& ExitDataSize
!= NULL
) {
1033 *ExitDataSize
= Image
->ExitDataSize
;
1034 *ExitData
= Image
->ExitData
;
1037 // Caller doesn't want the exit data, free it
1039 CoreFreePool (Image
->ExitData
);
1040 Image
->ExitData
= NULL
;
1044 // Save the Status because Image will get destroyed if it is unloaded.
1046 Status
= Image
->Status
;
1049 // If the image returned an error, or if the image is an application
1052 if (EFI_ERROR (Image
->Status
) || Image
->Type
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1053 CoreUnloadAndCloseImage (Image
, TRUE
);
1059 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
1065 CoreUnloadAndCloseImage (
1066 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
1071 Routine Description:
1073 Unloads EFI image from memory.
1078 FreePage - Free allocated pages
1088 EFI_HANDLE
*HandleBuffer
;
1090 EFI_GUID
**ProtocolGuidArray
;
1092 UINTN ProtocolIndex
;
1093 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfo
;
1094 UINTN OpenInfoCount
;
1095 UINTN OpenInfoIndex
;
1097 if (Image
->Ebc
!= NULL
) {
1099 // If EBC protocol exists we must perform cleanups for this image.
1101 Image
->Ebc
->UnloadImage (Image
->Ebc
, Image
->Handle
);
1105 // Unload image, free Image->ImageContext->ModHandle
1107 gEfiPeiPeCoffLoader
->UnloadImage (gEfiPeiPeCoffLoader
, &Image
->ImageContext
);
1110 // Free our references to the image handle
1112 if (Image
->Handle
!= NULL_HANDLE
) {
1114 Status
= CoreLocateHandleBuffer (
1121 if (!EFI_ERROR (Status
)) {
1122 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
1123 Status
= CoreProtocolsPerHandle (
1124 HandleBuffer
[HandleIndex
],
1128 if (!EFI_ERROR (Status
)) {
1129 for (ProtocolIndex
= 0; ProtocolIndex
< ArrayCount
; ProtocolIndex
++) {
1130 Status
= CoreOpenProtocolInformation (
1131 HandleBuffer
[HandleIndex
],
1132 ProtocolGuidArray
[ProtocolIndex
],
1136 if (!EFI_ERROR (Status
)) {
1137 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
1138 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== Image
->Handle
) {
1139 Status
= CoreCloseProtocol (
1140 HandleBuffer
[HandleIndex
],
1141 ProtocolGuidArray
[ProtocolIndex
],
1143 OpenInfo
[OpenInfoIndex
].ControllerHandle
1147 if (OpenInfo
!= NULL
) {
1148 CoreFreePool(OpenInfo
);
1152 if (ProtocolGuidArray
!= NULL
) {
1153 CoreFreePool(ProtocolGuidArray
);
1157 if (HandleBuffer
!= NULL
) {
1158 CoreFreePool (HandleBuffer
);
1162 CoreRemoveDebugImageInfoEntry (Image
->Handle
);
1164 Status
= CoreUninstallProtocolInterface (
1166 &gEfiLoadedImageProtocolGuid
,
1171 if (Image
->RuntimeFixupValid
) {
1173 // Remove the Image from the Runtime Image list as we are about to Free it!
1175 RemoveEntryList (&Image
->Link
);
1179 // Free the Image from memory
1181 if ((Image
->ImageBasePage
!= 0) && FreePage
) {
1182 CoreFreePages (Image
->ImageBasePage
, Image
->NumberOfPages
);
1186 // Done with the Image structure
1188 if (Image
->Info
.FilePath
!= NULL
) {
1189 CoreFreePool (Image
->Info
.FilePath
);
1192 if (Image
->FixupData
!= NULL
) {
1193 CoreFreePool (Image
->FixupData
);
1196 CoreFreePool (Image
);
1204 IN EFI_HANDLE ImageHandle
,
1205 IN EFI_STATUS Status
,
1206 IN UINTN ExitDataSize
,
1207 IN CHAR16
*ExitData OPTIONAL
1211 Routine Description:
1213 Terminates the currently loaded EFI image and returns control to boot services.
1217 ImageHandle - Handle that identifies the image. This parameter is passed to the image
1219 Status - The image's exit code.
1220 ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is
1222 ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string,
1223 optionally followed by additional binary data. The string is a
1224 description that the caller may use to further indicate the reason for
1229 EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image.
1231 EFI_SUCCESS - Successfully terminates the currently loaded EFI image.
1233 EFI_ACCESS_DENIED - Should never reach there.
1235 EFI_OUT_OF_RESOURCES - Could not allocate pool
1239 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1241 Image
= CoreLoadedImageInfo (ImageHandle
);
1242 if (Image
== NULL_HANDLE
) {
1243 return EFI_INVALID_PARAMETER
;
1246 if (!Image
->Started
) {
1248 // The image has not been started so just free its resources
1250 CoreUnloadAndCloseImage (Image
, TRUE
);
1255 // Image has been started, verify this image can exit
1257 if (Image
!= mCurrentImage
) {
1258 DEBUG ((EFI_D_LOAD
|EFI_D_ERROR
, "Exit: Image is not exitable image\n"));
1259 return EFI_INVALID_PARAMETER
;
1265 Image
->Status
= Status
;
1268 // If there's ExitData info, move it
1270 if (ExitData
!= NULL
) {
1271 Image
->ExitDataSize
= ExitDataSize
;
1272 Image
->ExitData
= CoreAllocateBootServicesPool (Image
->ExitDataSize
);
1273 if (Image
->ExitData
== NULL
) {
1274 return EFI_OUT_OF_RESOURCES
;
1276 CopyMem (Image
->ExitData
, ExitData
, Image
->ExitDataSize
);
1280 // return to StartImage
1282 LongJump (Image
->JumpContext
, (UINTN
)-1);
1285 // If we return from LongJump, then it is an error
1288 return EFI_ACCESS_DENIED
;
1296 IN EFI_HANDLE ImageHandle
1300 Routine Description:
1306 ImageHandle - Handle that identifies the image to be unloaded.
1310 EFI_SUCCESS - The image has been unloaded.
1311 EFI_UNSUPPORTED - The image has been sarted, and does not support unload.
1312 EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle.
1317 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1319 Image
= CoreLoadedImageInfo (ImageHandle
);
1320 if (Image
== NULL
) {
1322 // The image handle is not valid
1324 return EFI_INVALID_PARAMETER
;
1327 if (Image
->Started
) {
1329 // The image has been started, request it to unload.
1331 Status
= EFI_UNSUPPORTED
;
1332 if (Image
->Info
.Unload
!= NULL
) {
1333 Status
= Image
->Info
.Unload (ImageHandle
);
1338 // This Image hasn't been started, thus it can be unloaded
1340 Status
= EFI_SUCCESS
;
1344 if (!EFI_ERROR (Status
)) {
1346 // if the Image was not started or Unloaded O.K. then clean up
1348 CoreUnloadAndCloseImage (Image
, TRUE
);
1358 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
1359 IN EFI_HANDLE ImageHandle
1363 Routine Description:
1365 Unload the specified image.
1369 This - Indicates the calling context.
1371 ImageHandle - The specified image handle.
1375 EFI_INVALID_PARAMETER - Image handle is NULL.
1377 EFI_UNSUPPORTED - Attempt to unload an unsupported image.
1379 EFI_SUCCESS - Image successfully unloaded.
1383 return CoreUnloadImage (ImageHandle
);