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
80 FALSE
, // RuntimeFixupValid
82 { NULL
, NULL
}, // Link
87 CoreInitializeImageServices (
94 Add the Image Services to EFI Boot Services Table and install the protocol
95 interfaces for this image.
99 HobStart - The HOB to initialize
108 LOADED_IMAGE_PRIVATE_DATA
*Image
;
109 EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress
;
110 UINT64 DxeCoreImageLength
;
111 VOID
*DxeCoreEntryPoint
;
112 EFI_PEI_HOB_POINTERS DxeCoreHob
;
114 // Searching for image hob
116 DxeCoreHob
.Raw
= HobStart
;
117 while ((DxeCoreHob
.Raw
= GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, DxeCoreHob
.Raw
)) != NULL
) {
118 if (CompareGuid (&DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.Name
, &gEfiHobMemoryAllocModuleGuid
)) {
124 DxeCoreHob
.Raw
= GET_NEXT_HOB (DxeCoreHob
);
126 ASSERT (DxeCoreHob
.Raw
!= NULL
);
128 DxeCoreImageBaseAddress
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryBaseAddress
;
129 DxeCoreImageLength
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryLength
;
130 DxeCoreEntryPoint
= (VOID
*) (UINTN
) DxeCoreHob
.MemoryAllocationModule
->EntryPoint
;
131 gDxeCoreFileName
= &DxeCoreHob
.MemoryAllocationModule
->ModuleName
;
133 // Initialize the fields for an internal driver
135 Image
= &mCorePrivateImage
;
137 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)DxeCoreEntryPoint
;
138 Image
->ImageBasePage
= DxeCoreImageBaseAddress
;
139 Image
->NumberOfPages
= (UINTN
)(EFI_SIZE_TO_PAGES((UINTN
)(DxeCoreImageLength
)));
140 Image
->Tpl
= gEfiCurrentTpl
;
141 Image
->Info
.SystemTable
= gST
;
142 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)DxeCoreImageBaseAddress
;
143 Image
->Info
.ImageSize
= DxeCoreImageLength
;
146 // Install the protocol interfaces for this image
148 Status
= CoreInstallProtocolInterface (
150 &gEfiLoadedImageProtocolGuid
,
151 EFI_NATIVE_INTERFACE
,
154 ASSERT_EFI_ERROR (Status
);
156 mCurrentImage
= Image
;
159 // Fill in DXE globals
161 gDxeCoreImageHandle
= Image
->Handle
;
162 gDxeCoreLoadedImage
= &Image
->Info
;
165 // Export DXE Core PE Loader functionality
167 return CoreInstallProtocolInterface (
168 &mLoadPe32PrivateData
.Handle
,
169 &gEfiLoadPeImageProtocolGuid
,
170 EFI_NATIVE_INTERFACE
,
171 &mLoadPe32PrivateData
.Pe32Image
177 CoreShutdownImageServices (
184 Transfer control of runtime images to runtime service
192 EFI_SUCCESS - Function successfully returned
197 LOADED_IMAGE_PRIVATE_DATA
*Image
;
200 // The Runtime AP is required for the core to function!
202 ASSERT (gRuntime
!= NULL
);
204 for (Link
= mRuntimeImageList
.ForwardLink
; Link
!= &mRuntimeImageList
; Link
= Link
->ForwardLink
) {
205 Image
= CR (Link
, LOADED_IMAGE_PRIVATE_DATA
, Link
, LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
);
206 if (Image
->RuntimeFixupValid
) {
207 gRuntime
->RegisterImage (
209 (UINT64
)(UINTN
)(Image
->Info
.ImageBase
),
210 (EFI_SIZE_TO_PAGES ((UINTN
)Image
->Info
.ImageSize
)),
224 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
225 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
226 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
233 Loads, relocates, and invokes a PE/COFF image
237 Pe32Handle - The handle of PE32 image
238 Image - PE image to be loaded
239 DstBuffer - The buffer to store the image
240 EntryPoint - A pointer to the entry point
241 Attribute - The bit mask of attributes to set for the load PE image
245 EFI_SUCCESS - The file was loaded, relocated, and invoked
247 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
249 EFI_INVALID_PARAMETER - Invalid parameter
251 EFI_BUFFER_TOO_SMALL - Buffer for image is too small
258 ZeroMem (&Image
->ImageContext
, sizeof (Image
->ImageContext
));
260 Image
->ImageContext
.Handle
= Pe32Handle
;
261 Image
->ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)CoreReadImageFile
;
264 // Get information about the image being loaded
266 Status
= gEfiPeiPeCoffLoader
->GetImageInfo (gEfiPeiPeCoffLoader
, &Image
->ImageContext
);
267 if (EFI_ERROR (Status
)) {
271 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image
->ImageContext
.Machine
)) {
273 // The PE/COFF loader can support loading image types that can be executed.
274 // If we loaded an image type that we can not execute return EFI_UNSUPORTED.
276 return EFI_UNSUPPORTED
;
281 // Allocate memory of the correct memory type aligned on the required image boundry
284 if (DstBuffer
== 0) {
286 // Allocate Destination Buffer as caller did not pass it in
289 if (Image
->ImageContext
.SectionAlignment
> EFI_PAGE_SIZE
) {
290 Size
= (UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
;
292 Size
= (UINTN
)Image
->ImageContext
.ImageSize
;
295 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES (Size
);
298 // If the image relocations have not been stripped, then load at any address.
299 // Otherwise load at the address at which it was linked.
301 Status
= CoreAllocatePages (
302 (Image
->ImageContext
.RelocationsStripped
) ? AllocateAddress
: AllocateAnyPages
,
303 Image
->ImageContext
.ImageCodeMemoryType
,
304 Image
->NumberOfPages
,
305 &Image
->ImageContext
.ImageAddress
307 if (EFI_ERROR (Status
)) {
311 Image
->ImageBasePage
= Image
->ImageContext
.ImageAddress
;
315 // Caller provided the destination buffer
318 if (Image
->ImageContext
.RelocationsStripped
&& (Image
->ImageContext
.ImageAddress
!= DstBuffer
)) {
320 // If the image relocations were stripped, and the caller provided a
321 // destination buffer address that does not match the address that the
322 // image is linked at, then the image cannot be loaded.
324 return EFI_INVALID_PARAMETER
;
327 if (Image
->NumberOfPages
!= 0 &&
328 Image
->NumberOfPages
<
329 (EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
))) {
330 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
331 return EFI_BUFFER_TOO_SMALL
;
334 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
335 Image
->ImageContext
.ImageAddress
= DstBuffer
;
336 Image
->ImageBasePage
= Image
->ImageContext
.ImageAddress
;
339 Image
->ImageContext
.ImageAddress
=
340 (Image
->ImageContext
.ImageAddress
+ Image
->ImageContext
.SectionAlignment
- 1) &
341 ~((UINTN
)Image
->ImageContext
.SectionAlignment
- 1);
344 // Load the image from the file into the allocated memory
346 Status
= gEfiPeiPeCoffLoader
->LoadImage (gEfiPeiPeCoffLoader
, &Image
->ImageContext
);
347 if (EFI_ERROR (Status
)) {
352 // If this is a Runtime Driver, then allocate memory for the FixupData that
353 // is used to relocate the image when SetVirtualAddressMap() is called. The
354 // relocation is done by the Runtime AP.
356 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) {
357 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
358 Image
->ImageContext
.FixupData
= CoreAllocateRuntimePool ((UINTN
)(Image
->ImageContext
.FixupDataSize
));
359 if (Image
->ImageContext
.FixupData
== NULL
) {
360 Status
= EFI_OUT_OF_RESOURCES
;
365 // Make a list off all the RT images so we can let the RT AP know about them
367 Image
->RuntimeFixupValid
= TRUE
;
368 Image
->RuntimeFixup
= Image
->ImageContext
.FixupData
;
369 InsertTailList (&mRuntimeImageList
, &Image
->Link
);
374 // Relocate the image in memory
376 Status
= gEfiPeiPeCoffLoader
->RelocateImage (gEfiPeiPeCoffLoader
, &Image
->ImageContext
);
377 if (EFI_ERROR (Status
)) {
382 // Flush the Instruction Cache
384 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
, (UINTN
)Image
->ImageContext
.ImageSize
);
387 // Copy the machine type from the context to the image private data. This
388 // is needed during image unload to know if we should call an EBC protocol
389 // to unload the image.
391 Image
->Machine
= Image
->ImageContext
.Machine
;
394 // Get the image entry point. If it's an EBC image, then call into the
395 // interpreter to create a thunk for the entry point and use the returned
396 // value for the entry point.
398 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)Image
->ImageContext
.EntryPoint
;
399 if (Image
->ImageContext
.Machine
== EFI_IMAGE_MACHINE_EBC
) {
401 // Locate the EBC interpreter protocol
403 Status
= CoreLocateProtocol (&gEfiEbcProtocolGuid
, NULL
, (VOID
**)&Image
->Ebc
);
404 if (EFI_ERROR(Status
)) {
409 // Register a callback for flushing the instruction cache so that created
410 // thunks can be flushed.
412 Status
= Image
->Ebc
->RegisterICacheFlush (Image
->Ebc
, (EBC_ICACHE_FLUSH
)InvalidateInstructionCacheRange
);
413 if (EFI_ERROR(Status
)) {
418 // Create a thunk for the image's entry point. This will be the new
419 // entry point for the image.
421 Status
= Image
->Ebc
->CreateThunk (
424 (VOID
*)(UINTN
)Image
->ImageContext
.EntryPoint
,
425 (VOID
**)&Image
->EntryPoint
427 if (EFI_ERROR(Status
)) {
433 // Fill in the image information for the Loaded Image Protocol
435 Image
->Type
= Image
->ImageContext
.ImageType
;
436 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
;
437 Image
->Info
.ImageSize
= Image
->ImageContext
.ImageSize
;
438 Image
->Info
.ImageCodeType
= Image
->ImageContext
.ImageCodeMemoryType
;
439 Image
->Info
.ImageDataType
= Image
->ImageContext
.ImageDataMemoryType
;
442 // Fill in the entry point of the image if it is available
444 if (EntryPoint
!= NULL
) {
445 *EntryPoint
= Image
->ImageContext
.EntryPoint
;
449 // Print the load address and the PDB file name if it is available
456 CHAR8 EfiFileName
[256];
458 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Loading driver at 0x%08x EntryPoint=0x%08x ", (UINTN
)Image
->ImageContext
.ImageAddress
, (UINTN
)Image
->ImageContext
.EntryPoint
));
459 if (Image
->ImageContext
.PdbPointer
!= NULL
) {
461 for (Index
= 0; Image
->ImageContext
.PdbPointer
[Index
] != 0; Index
++) {
462 if (Image
->ImageContext
.PdbPointer
[Index
] == '\\') {
463 StartIndex
= Index
+ 1;
467 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
469 for (Index
= 0; Index
< sizeof (EfiFileName
); Index
++) {
470 EfiFileName
[Index
] = Image
->ImageContext
.PdbPointer
[Index
+ StartIndex
];
471 if (EfiFileName
[Index
] == 0) {
472 EfiFileName
[Index
] = '.';
474 if (EfiFileName
[Index
] == '.') {
475 EfiFileName
[Index
+ 1] = 'e';
476 EfiFileName
[Index
+ 2] = 'f';
477 EfiFileName
[Index
+ 3] = 'i';
478 EfiFileName
[Index
+ 4] = 0;
482 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "%a", EfiFileName
)); // &Image->ImageContext.PdbPointer[StartIndex]));
484 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "\n"));
494 CoreFreePages (Image
->ImageContext
.ImageAddress
, Image
->NumberOfPages
);
499 LOADED_IMAGE_PRIVATE_DATA
*
500 CoreLoadedImageInfo (
501 IN EFI_HANDLE ImageHandle
507 Get the image's private data from its handle.
511 ImageHandle - The image handle
515 Return the image private data associated with ImageHandle.
520 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
521 LOADED_IMAGE_PRIVATE_DATA
*Image
;
523 Status
= CoreHandleProtocol (
525 &gEfiLoadedImageProtocolGuid
,
526 (VOID
**)&LoadedImage
528 if (!EFI_ERROR (Status
)) {
529 Image
= LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage
);
531 DEBUG ((EFI_D_LOAD
, "CoreLoadedImageInfo: Not an ImageHandle %x\n", ImageHandle
));
540 CoreLoadImageCommon (
541 IN BOOLEAN BootPolicy
,
542 IN EFI_HANDLE ParentImageHandle
,
543 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
544 IN VOID
*SourceBuffer OPTIONAL
,
546 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
547 IN OUT UINTN
*NumberOfPages OPTIONAL
,
548 OUT EFI_HANDLE
*ImageHandle
,
549 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
556 Loads an EFI image into memory and returns a handle to the image.
560 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
561 and that the boot manager is attempting to load FilePath as a boot selection.
562 ParentImageHandle - The caller's image handle.
563 FilePath - The specific file path from which the image is loaded.
564 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
565 the image to be loaded.
566 SourceSize - The size in bytes of SourceBuffer.
567 DstBuffer - The buffer to store the image
568 NumberOfPages - If not NULL, a pointer to the image's page number, if this number
569 is not enough, return EFI_BUFFER_TOO_SMALL and this parameter contain
571 ImageHandle - Pointer to the returned image handle that is created when the image
572 is successfully loaded.
573 EntryPoint - A pointer to the entry point
574 Attribute - The bit mask of attributes to set for the load PE image
578 EFI_SUCCESS - The image was loaded into memory.
579 EFI_NOT_FOUND - The FilePath was not found.
580 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
581 EFI_BUFFER_TOO_SMALL - The buffer is too small
582 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
583 parsed to locate the proper protocol for loading the file.
584 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
587 LOADED_IMAGE_PRIVATE_DATA
*Image
;
588 LOADED_IMAGE_PRIVATE_DATA
*ParentImage
;
589 IMAGE_FILE_HANDLE FHand
;
591 EFI_STATUS SecurityStatus
;
592 EFI_HANDLE DeviceHandle
;
593 UINT32 AuthenticationStatus
;
594 EFI_DEVICE_PATH_PROTOCOL
*OriginalFilePath
;
595 EFI_DEVICE_PATH_PROTOCOL
*HandleFilePath
;
598 SecurityStatus
= EFI_SUCCESS
;
600 ASSERT (gEfiCurrentTpl
< EFI_TPL_NOTIFY
);
604 // The caller must pass in a valid ParentImageHandle
606 if (ImageHandle
== NULL
|| ParentImageHandle
== NULL
) {
607 return EFI_INVALID_PARAMETER
;
610 ParentImage
= CoreLoadedImageInfo (ParentImageHandle
);
611 if (ParentImage
== NULL
) {
612 DEBUG((EFI_D_LOAD
|EFI_D_ERROR
, "LoadImageEx: Parent handle not an image handle\n"));
613 return EFI_INVALID_PARAMETER
;
617 // Get simple read access to the source file
619 OriginalFilePath
= FilePath
;
620 Status
= CoreOpenImageFile (
627 &AuthenticationStatus
629 if (Status
== EFI_ALREADY_STARTED
) {
632 } else if (EFI_ERROR (Status
)) {
637 // Verify the Authentication Status through the Security Architectural Protocol
639 if ((gSecurity
!= NULL
) && (OriginalFilePath
!= NULL
)) {
640 SecurityStatus
= gSecurity
->FileAuthenticationState (
642 AuthenticationStatus
,
645 if (EFI_ERROR (SecurityStatus
) && SecurityStatus
!= EFI_SECURITY_VIOLATION
) {
646 Status
= SecurityStatus
;
654 // Allocate a new image structure
656 Image
= CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA
));
658 return EFI_OUT_OF_RESOURCES
;
662 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
664 Status
= CoreHandleProtocol (DeviceHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&HandleFilePath
);
665 if (!EFI_ERROR (Status
)) {
666 FilePathSize
= CoreDevicePathSize (HandleFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
667 FilePath
= (EFI_DEVICE_PATH_PROTOCOL
*) ( ((UINT8
*)FilePath
) + FilePathSize
);
671 // Initialize the fields for an internal driver
673 Image
->Signature
= LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
;
674 Image
->Info
.SystemTable
= gST
;
675 Image
->Info
.DeviceHandle
= DeviceHandle
;
676 Image
->Info
.Revision
= EFI_LOADED_IMAGE_INFORMATION_REVISION
;
677 Image
->Info
.FilePath
= CoreDuplicateDevicePath (FilePath
);
678 Image
->Info
.ParentHandle
= ParentImageHandle
;
680 if (NumberOfPages
!= NULL
) {
681 Image
->NumberOfPages
= *NumberOfPages
;
683 Image
->NumberOfPages
= 0 ;
687 // Install the protocol interfaces for this image
688 // don't fire notifications yet
690 Status
= CoreInstallProtocolInterfaceNotify (
692 &gEfiLoadedImageProtocolGuid
,
693 EFI_NATIVE_INTERFACE
,
697 if (EFI_ERROR (Status
)) {
702 // Load the image. If EntryPoint is Null, it will not be set.
704 Status
= CoreLoadPeImage (&FHand
, Image
, DstBuffer
, EntryPoint
, Attribute
);
705 if (EFI_ERROR (Status
)) {
706 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_OUT_OF_RESOURCES
)) {
707 if (NumberOfPages
!= NULL
) {
708 *NumberOfPages
= Image
->NumberOfPages
;
715 // Register the image in the Debug Image Info Table if the attribute is set
717 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
) {
718 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL
, &Image
->Info
, Image
->Handle
);
722 //Reinstall loaded image protocol to fire any notifications
724 Status
= CoreReinstallProtocolInterface (
726 &gEfiLoadedImageProtocolGuid
,
730 if (EFI_ERROR (Status
)) {
736 // Success. Return the image handle
738 *ImageHandle
= Image
->Handle
;
742 // All done accessing the source file
743 // If we allocated the Source buffer, free it
745 if (FHand
.FreeBuffer
) {
746 CoreFreePool (FHand
.Source
);
750 // There was an error. If there's an Image structure, free it
752 if (EFI_ERROR (Status
)) {
754 CoreUnloadAndCloseImage (Image
, (BOOLEAN
)(DstBuffer
== 0));
757 } else if (EFI_ERROR (SecurityStatus
)) {
758 Status
= SecurityStatus
;
769 IN BOOLEAN BootPolicy
,
770 IN EFI_HANDLE ParentImageHandle
,
771 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
772 IN VOID
*SourceBuffer OPTIONAL
,
774 OUT EFI_HANDLE
*ImageHandle
780 Loads an EFI image into memory and returns a handle to the image.
784 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
785 and that the boot manager is attempting to load FilePath as a boot selection.
786 ParentImageHandle - The caller's image handle.
787 FilePath - The specific file path from which the image is loaded.
788 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
789 the image to be loaded.
790 SourceSize - The size in bytes of SourceBuffer.
791 ImageHandle - Pointer to the returned image handle that is created when the image
792 is successfully loaded.
796 EFI_SUCCESS - The image was loaded into memory.
797 EFI_NOT_FOUND - The FilePath was not found.
798 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
799 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
800 parsed to locate the proper protocol for loading the file.
801 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
806 PERF_START (NULL
, "LoadImage", NULL
, 0);
808 Status
= CoreLoadImageCommon (
814 (EFI_PHYSICAL_ADDRESS
)NULL
,
818 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
| EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
821 PERF_END (NULL
, "LoadImage", NULL
, 0);
830 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
831 IN EFI_HANDLE ParentImageHandle
,
832 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
833 IN VOID
*SourceBuffer OPTIONAL
,
835 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
836 OUT UINTN
*NumberOfPages OPTIONAL
,
837 OUT EFI_HANDLE
*ImageHandle
,
838 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
845 Loads an EFI image into memory and returns a handle to the image with extended parameters.
849 This - Calling context
850 ParentImageHandle - The caller's image handle.
851 FilePath - The specific file path from which the image is loaded.
852 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
853 the image to be loaded.
854 SourceSize - The size in bytes of SourceBuffer.
855 DstBuffer - The buffer to store the image.
856 NumberOfPages - For input, specifies the space size of the image by caller if not NULL.
857 For output, specifies the actual space size needed.
858 ImageHandle - Image handle for output.
859 EntryPoint - Image entry point for output.
860 Attribute - The bit mask of attributes to set for the load PE image.
864 EFI_SUCCESS - The image was loaded into memory.
865 EFI_NOT_FOUND - The FilePath was not found.
866 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
867 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
868 parsed to locate the proper protocol for loading the file.
869 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
872 return CoreLoadImageCommon (
892 IN EFI_HANDLE ImageHandle
,
893 OUT UINTN
*ExitDataSize
,
894 OUT CHAR16
**ExitData OPTIONAL
900 Transfer control to a loaded image's entry point.
904 ImageHandle - Handle of image to be started.
906 ExitDataSize - Pointer of the size to ExitData
908 ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated
909 Unicode string, optionally followed by additional binary data. The string
910 is a description that the caller may use to further indicate the reason for
915 EFI_INVALID_PARAMETER - Invalid parameter
917 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
919 EFI_SUCCESS - Successfully transfer control to the image's entry point.
924 LOADED_IMAGE_PRIVATE_DATA
*Image
;
925 LOADED_IMAGE_PRIVATE_DATA
*LastImage
;
926 UINT64 HandleDatabaseKey
;
929 Image
= CoreLoadedImageInfo (ImageHandle
);
930 if (Image
== NULL_HANDLE
|| Image
->Started
) {
931 return EFI_INVALID_PARAMETER
;
935 // Don't profile Objects or invalid start requests
937 PERF_START (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
941 // Push the current start image context, and
942 // link the current image to the head. This is the
943 // only image that can call Exit()
945 HandleDatabaseKey
= CoreGetHandleDatabaseKey ();
946 LastImage
= mCurrentImage
;
947 mCurrentImage
= Image
;
948 Image
->Tpl
= gEfiCurrentTpl
;
951 // Set long jump for Exit() support
953 Image
->JumpContext
= CoreAllocateBootServicesPool (sizeof (*Image
->JumpContext
));
954 if (Image
->JumpContext
== NULL
) {
955 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
956 return EFI_OUT_OF_RESOURCES
;
959 SetJumpFlag
= SetJump (Image
->JumpContext
);
961 // The initial call to SetJump() must always return 0.
962 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
966 // Call the image's entry point
968 Image
->Started
= TRUE
;
969 Image
->Status
= Image
->EntryPoint (ImageHandle
, Image
->Info
.SystemTable
);
972 // Add some debug information if the image returned with error.
973 // This make the user aware and check if the driver image have already released
974 // all the resource in this situation.
977 if (EFI_ERROR (Image
->Status
)) {
978 DEBUG ((EFI_D_ERROR
, "Error: Image at %08X start failed: %x\n", Image
->Info
.ImageBase
, Image
->Status
));
983 // If the image returns, exit it through Exit()
985 CoreExit (ImageHandle
, Image
->Status
, 0, NULL
);
989 // Image has completed. Verify the tpl is the same
991 ASSERT (Image
->Tpl
== gEfiCurrentTpl
);
992 CoreRestoreTpl (Image
->Tpl
);
994 CoreFreePool (Image
->JumpContext
);
997 // Pop the current start image context
999 mCurrentImage
= LastImage
;
1002 // Go connect any handles that were created or modified while the image executed.
1004 CoreConnectHandlesByKey (HandleDatabaseKey
);
1007 // Handle the image's returned ExitData
1009 DEBUG_CODE_BEGIN ();
1010 if (Image
->ExitDataSize
!= 0 || Image
->ExitData
!= NULL
) {
1014 "StartImage: ExitDataSize %d, ExitData %x",
1015 Image
->ExitDataSize
,
1018 if (Image
->ExitData
!= NULL
) {
1019 DEBUG ((EFI_D_LOAD
, " (%hs)", Image
->ExitData
));
1021 DEBUG ((EFI_D_LOAD
, "\n"));
1026 // Return the exit data to the caller
1028 if (ExitData
!= NULL
&& ExitDataSize
!= NULL
) {
1029 *ExitDataSize
= Image
->ExitDataSize
;
1030 *ExitData
= Image
->ExitData
;
1033 // Caller doesn't want the exit data, free it
1035 CoreFreePool (Image
->ExitData
);
1036 Image
->ExitData
= NULL
;
1040 // Save the Status because Image will get destroyed if it is unloaded.
1042 Status
= Image
->Status
;
1045 // If the image returned an error, or if the image is an application
1048 if (EFI_ERROR (Image
->Status
) || Image
->Type
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1049 CoreUnloadAndCloseImage (Image
, TRUE
);
1055 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
1061 CoreUnloadAndCloseImage (
1062 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
1067 Routine Description:
1069 Unloads EFI image from memory.
1074 FreePage - Free allocated pages
1084 EFI_HANDLE
*HandleBuffer
;
1086 EFI_GUID
**ProtocolGuidArray
;
1088 UINTN ProtocolIndex
;
1089 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfo
;
1090 UINTN OpenInfoCount
;
1091 UINTN OpenInfoIndex
;
1093 if (Image
->Ebc
!= NULL
) {
1095 // If EBC protocol exists we must perform cleanups for this image.
1097 Image
->Ebc
->UnloadImage (Image
->Ebc
, Image
->Handle
);
1101 // Unload image, free Image->ImageContext->ModHandle
1103 gEfiPeiPeCoffLoader
->UnloadImage (gEfiPeiPeCoffLoader
, &Image
->ImageContext
);
1106 // Free our references to the image handle
1108 if (Image
->Handle
!= NULL_HANDLE
) {
1110 Status
= CoreLocateHandleBuffer (
1117 if (!EFI_ERROR (Status
)) {
1118 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
1119 Status
= CoreProtocolsPerHandle (
1120 HandleBuffer
[HandleIndex
],
1124 if (!EFI_ERROR (Status
)) {
1125 for (ProtocolIndex
= 0; ProtocolIndex
< ArrayCount
; ProtocolIndex
++) {
1126 Status
= CoreOpenProtocolInformation (
1127 HandleBuffer
[HandleIndex
],
1128 ProtocolGuidArray
[ProtocolIndex
],
1132 if (!EFI_ERROR (Status
)) {
1133 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
1134 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== Image
->Handle
) {
1135 Status
= CoreCloseProtocol (
1136 HandleBuffer
[HandleIndex
],
1137 ProtocolGuidArray
[ProtocolIndex
],
1139 OpenInfo
[OpenInfoIndex
].ControllerHandle
1143 if (OpenInfo
!= NULL
) {
1144 CoreFreePool(OpenInfo
);
1148 if (ProtocolGuidArray
!= NULL
) {
1149 CoreFreePool(ProtocolGuidArray
);
1153 if (HandleBuffer
!= NULL
) {
1154 CoreFreePool (HandleBuffer
);
1158 CoreRemoveDebugImageInfoEntry (Image
->Handle
);
1160 Status
= CoreUninstallProtocolInterface (
1162 &gEfiLoadedImageProtocolGuid
,
1167 if (Image
->RuntimeFixupValid
) {
1169 // Remove the Image from the Runtime Image list as we are about to Free it!
1171 RemoveEntryList (&Image
->Link
);
1175 // Free the Image from memory
1177 if ((Image
->ImageBasePage
!= 0) && FreePage
) {
1178 CoreFreePages (Image
->ImageBasePage
, Image
->NumberOfPages
);
1182 // Done with the Image structure
1184 if (Image
->Info
.FilePath
!= NULL
) {
1185 CoreFreePool (Image
->Info
.FilePath
);
1188 if (Image
->FixupData
!= NULL
) {
1189 CoreFreePool (Image
->FixupData
);
1192 CoreFreePool (Image
);
1200 IN EFI_HANDLE ImageHandle
,
1201 IN EFI_STATUS Status
,
1202 IN UINTN ExitDataSize
,
1203 IN CHAR16
*ExitData OPTIONAL
1207 Routine Description:
1209 Terminates the currently loaded EFI image and returns control to boot services.
1213 ImageHandle - Handle that identifies the image. This parameter is passed to the image
1215 Status - The image's exit code.
1216 ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is
1218 ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string,
1219 optionally followed by additional binary data. The string is a
1220 description that the caller may use to further indicate the reason for
1225 EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image.
1227 EFI_SUCCESS - Successfully terminates the currently loaded EFI image.
1229 EFI_ACCESS_DENIED - Should never reach there.
1231 EFI_OUT_OF_RESOURCES - Could not allocate pool
1235 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1237 Image
= CoreLoadedImageInfo (ImageHandle
);
1238 if (Image
== NULL_HANDLE
) {
1239 return EFI_INVALID_PARAMETER
;
1242 if (!Image
->Started
) {
1244 // The image has not been started so just free its resources
1246 CoreUnloadAndCloseImage (Image
, TRUE
);
1251 // Image has been started, verify this image can exit
1253 if (Image
!= mCurrentImage
) {
1254 DEBUG ((EFI_D_LOAD
|EFI_D_ERROR
, "Exit: Image is not exitable image\n"));
1255 return EFI_INVALID_PARAMETER
;
1261 Image
->Status
= Status
;
1264 // If there's ExitData info, move it
1266 if (ExitData
!= NULL
) {
1267 Image
->ExitDataSize
= ExitDataSize
;
1268 Image
->ExitData
= CoreAllocateBootServicesPool (Image
->ExitDataSize
);
1269 if (Image
->ExitData
== NULL
) {
1270 return EFI_OUT_OF_RESOURCES
;
1272 CopyMem (Image
->ExitData
, ExitData
, Image
->ExitDataSize
);
1276 // return to StartImage
1278 LongJump (Image
->JumpContext
, (UINTN
)-1);
1281 // If we return from LongJump, then it is an error
1284 return EFI_ACCESS_DENIED
;
1292 IN EFI_HANDLE ImageHandle
1296 Routine Description:
1302 ImageHandle - Handle that identifies the image to be unloaded.
1306 EFI_SUCCESS - The image has been unloaded.
1307 EFI_UNSUPPORTED - The image has been sarted, and does not support unload.
1308 EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle.
1313 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1315 Image
= CoreLoadedImageInfo (ImageHandle
);
1316 if (Image
== NULL
) {
1318 // The image handle is not valid
1320 return EFI_INVALID_PARAMETER
;
1323 if (Image
->Started
) {
1325 // The image has been started, request it to unload.
1327 Status
= EFI_UNSUPPORTED
;
1328 if (Image
->Info
.Unload
!= NULL
) {
1329 Status
= Image
->Info
.Unload (ImageHandle
);
1334 // This Image hasn't been started, thus it can be unloaded
1336 Status
= EFI_SUCCESS
;
1340 if (!EFI_ERROR (Status
)) {
1342 // if the Image was not started or Unloaded O.K. then clean up
1344 CoreUnloadAndCloseImage (Image
, TRUE
);
1354 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
1355 IN EFI_HANDLE ImageHandle
1359 Routine Description:
1361 Unload the specified image.
1365 This - Indicates the calling context.
1367 ImageHandle - The specified image handle.
1371 EFI_INVALID_PARAMETER - Image handle is NULL.
1373 EFI_UNSUPPORTED - Attempt to unload an unsupported image.
1375 EFI_SUCCESS - Image successfully unloaded.
1379 return CoreUnloadImage (ImageHandle
);