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
)) {
272 // Allocate memory of the correct memory type aligned on the required image boundry
275 if (DstBuffer
== 0) {
277 // Allocate Destination Buffer as caller did not pass it in
280 if (Image
->ImageContext
.SectionAlignment
> EFI_PAGE_SIZE
) {
281 Size
= (UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
;
283 Size
= (UINTN
)Image
->ImageContext
.ImageSize
;
286 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES (Size
);
289 // If the image relocations have not been stripped, then load at any address.
290 // Otherwise load at the address at which it was linked.
292 Status
= CoreAllocatePages (
293 (Image
->ImageContext
.RelocationsStripped
) ? AllocateAddress
: AllocateAnyPages
,
294 Image
->ImageContext
.ImageCodeMemoryType
,
295 Image
->NumberOfPages
,
296 &Image
->ImageContext
.ImageAddress
298 if (EFI_ERROR (Status
)) {
302 Image
->ImageBasePage
= Image
->ImageContext
.ImageAddress
;
306 // Caller provided the destination buffer
309 if (Image
->ImageContext
.RelocationsStripped
&& (Image
->ImageContext
.ImageAddress
!= DstBuffer
)) {
311 // If the image relocations were stripped, and the caller provided a
312 // destination buffer address that does not match the address that the
313 // image is linked at, then the image cannot be loaded.
315 return EFI_INVALID_PARAMETER
;
318 if (Image
->NumberOfPages
!= 0 &&
319 Image
->NumberOfPages
<
320 (EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
))) {
321 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
322 return EFI_BUFFER_TOO_SMALL
;
325 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
326 Image
->ImageContext
.ImageAddress
= DstBuffer
;
327 Image
->ImageBasePage
= Image
->ImageContext
.ImageAddress
;
330 Image
->ImageContext
.ImageAddress
=
331 (Image
->ImageContext
.ImageAddress
+ Image
->ImageContext
.SectionAlignment
- 1) &
332 ~((UINTN
)Image
->ImageContext
.SectionAlignment
- 1);
335 // Load the image from the file into the allocated memory
337 Status
= gEfiPeiPeCoffLoader
->LoadImage (gEfiPeiPeCoffLoader
, &Image
->ImageContext
);
338 if (EFI_ERROR (Status
)) {
343 // If this is a Runtime Driver, then allocate memory for the FixupData that
344 // is used to relocate the image when SetVirtualAddressMap() is called. The
345 // relocation is done by the Runtime AP.
347 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) {
348 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
349 Image
->ImageContext
.FixupData
= CoreAllocateRuntimePool ((UINTN
)(Image
->ImageContext
.FixupDataSize
));
350 if (Image
->ImageContext
.FixupData
== NULL
) {
351 Status
= EFI_OUT_OF_RESOURCES
;
356 // Make a list off all the RT images so we can let the RT AP know about them
358 Image
->RuntimeFixupValid
= TRUE
;
359 Image
->RuntimeFixup
= Image
->ImageContext
.FixupData
;
360 InsertTailList (&mRuntimeImageList
, &Image
->Link
);
365 // Relocate the image in memory
367 Status
= gEfiPeiPeCoffLoader
->RelocateImage (gEfiPeiPeCoffLoader
, &Image
->ImageContext
);
368 if (EFI_ERROR (Status
)) {
373 // Flush the Instruction Cache
375 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
, (UINTN
)Image
->ImageContext
.ImageSize
);
378 // Copy the machine type from the context to the image private data. This
379 // is needed during image unload to know if we should call an EBC protocol
380 // to unload the image.
382 Image
->Machine
= Image
->ImageContext
.Machine
;
385 // Get the image entry point. If it's an EBC image, then call into the
386 // interpreter to create a thunk for the entry point and use the returned
387 // value for the entry point.
389 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)Image
->ImageContext
.EntryPoint
;
390 if (Image
->ImageContext
.Machine
== EFI_IMAGE_MACHINE_EBC
) {
392 // Locate the EBC interpreter protocol
394 Status
= CoreLocateProtocol (&gEfiEbcProtocolGuid
, NULL
, (VOID
**)&Image
->Ebc
);
395 if (EFI_ERROR(Status
)) {
400 // Register a callback for flushing the instruction cache so that created
401 // thunks can be flushed.
403 Status
= Image
->Ebc
->RegisterICacheFlush (Image
->Ebc
, (EBC_ICACHE_FLUSH
)InvalidateInstructionCacheRange
);
404 if (EFI_ERROR(Status
)) {
409 // Create a thunk for the image's entry point. This will be the new
410 // entry point for the image.
412 Status
= Image
->Ebc
->CreateThunk (
415 (VOID
*)(UINTN
)Image
->ImageContext
.EntryPoint
,
416 (VOID
**)&Image
->EntryPoint
418 if (EFI_ERROR(Status
)) {
424 // Fill in the image information for the Loaded Image Protocol
426 Image
->Type
= Image
->ImageContext
.ImageType
;
427 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
;
428 Image
->Info
.ImageSize
= Image
->ImageContext
.ImageSize
;
429 Image
->Info
.ImageCodeType
= Image
->ImageContext
.ImageCodeMemoryType
;
430 Image
->Info
.ImageDataType
= Image
->ImageContext
.ImageDataMemoryType
;
433 // Fill in the entry point of the image if it is available
435 if (EntryPoint
!= NULL
) {
436 *EntryPoint
= Image
->ImageContext
.EntryPoint
;
440 // Print the load address and the PDB file name if it is available
447 CHAR8 EfiFileName
[256];
449 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Loading driver at 0x%08x EntryPoint=0x%08x ", (UINTN
)Image
->ImageContext
.ImageAddress
, (UINTN
)Image
->ImageContext
.EntryPoint
));
450 if (Image
->ImageContext
.PdbPointer
!= NULL
) {
452 for (Index
= 0; Image
->ImageContext
.PdbPointer
[Index
] != 0; Index
++) {
453 if (Image
->ImageContext
.PdbPointer
[Index
] == '\\') {
454 StartIndex
= Index
+ 1;
458 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
460 for (Index
= 0; Index
< sizeof (EfiFileName
); Index
++) {
461 EfiFileName
[Index
] = Image
->ImageContext
.PdbPointer
[Index
+ StartIndex
];
462 if (EfiFileName
[Index
] == 0) {
463 EfiFileName
[Index
] = '.';
465 if (EfiFileName
[Index
] == '.') {
466 EfiFileName
[Index
+ 1] = 'e';
467 EfiFileName
[Index
+ 2] = 'f';
468 EfiFileName
[Index
+ 3] = 'i';
469 EfiFileName
[Index
+ 4] = 0;
473 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "%a", EfiFileName
)); // &Image->ImageContext.PdbPointer[StartIndex]));
475 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "\n"));
485 CoreFreePages (Image
->ImageContext
.ImageAddress
, Image
->NumberOfPages
);
490 LOADED_IMAGE_PRIVATE_DATA
*
491 CoreLoadedImageInfo (
492 IN EFI_HANDLE ImageHandle
498 Get the image's private data from its handle.
502 ImageHandle - The image handle
506 Return the image private data associated with ImageHandle.
511 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
512 LOADED_IMAGE_PRIVATE_DATA
*Image
;
514 Status
= CoreHandleProtocol (
516 &gEfiLoadedImageProtocolGuid
,
517 (VOID
**)&LoadedImage
519 if (!EFI_ERROR (Status
)) {
520 Image
= LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage
);
522 DEBUG ((EFI_D_LOAD
, "CoreLoadedImageInfo: Not an ImageHandle %x\n", ImageHandle
));
531 CoreLoadImageCommon (
532 IN BOOLEAN BootPolicy
,
533 IN EFI_HANDLE ParentImageHandle
,
534 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
535 IN VOID
*SourceBuffer OPTIONAL
,
537 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
538 IN OUT UINTN
*NumberOfPages OPTIONAL
,
539 OUT EFI_HANDLE
*ImageHandle
,
540 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
547 Loads an EFI image into memory and returns a handle to the image.
551 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
552 and that the boot manager is attempting to load FilePath as a boot selection.
553 ParentImageHandle - The caller's image handle.
554 FilePath - The specific file path from which the image is loaded.
555 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
556 the image to be loaded.
557 SourceSize - The size in bytes of SourceBuffer.
558 DstBuffer - The buffer to store the image
559 NumberOfPages - If not NULL, a pointer to the image's page number, if this number
560 is not enough, return EFI_BUFFER_TOO_SMALL and this parameter contain
562 ImageHandle - Pointer to the returned image handle that is created when the image
563 is successfully loaded.
564 EntryPoint - A pointer to the entry point
565 Attribute - The bit mask of attributes to set for the load PE image
569 EFI_SUCCESS - The image was loaded into memory.
570 EFI_NOT_FOUND - The FilePath was not found.
571 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
572 EFI_BUFFER_TOO_SMALL - The buffer is too small
573 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
574 parsed to locate the proper protocol for loading the file.
575 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
578 LOADED_IMAGE_PRIVATE_DATA
*Image
;
579 LOADED_IMAGE_PRIVATE_DATA
*ParentImage
;
580 IMAGE_FILE_HANDLE FHand
;
582 EFI_STATUS SecurityStatus
;
583 EFI_HANDLE DeviceHandle
;
584 UINT32 AuthenticationStatus
;
585 EFI_DEVICE_PATH_PROTOCOL
*OriginalFilePath
;
586 EFI_DEVICE_PATH_PROTOCOL
*HandleFilePath
;
590 ASSERT (gEfiCurrentTpl
< EFI_TPL_NOTIFY
);
594 // The caller must pass in a valid ParentImageHandle
596 if (ImageHandle
== NULL
|| ParentImageHandle
== NULL
) {
597 return EFI_INVALID_PARAMETER
;
600 ParentImage
= CoreLoadedImageInfo (ParentImageHandle
);
601 if (ParentImage
== NULL
) {
602 DEBUG((EFI_D_LOAD
|EFI_D_ERROR
, "LoadImageEx: Parent handle not an image handle\n"));
603 return EFI_INVALID_PARAMETER
;
607 // Get simple read access to the source file
609 OriginalFilePath
= FilePath
;
610 Status
= CoreOpenImageFile (
617 &AuthenticationStatus
619 if (Status
== EFI_ALREADY_STARTED
) {
622 } else if (EFI_ERROR (Status
)) {
627 // Verify the Authentication Status through the Security Architectural Protocol
629 if ((gSecurity
!= NULL
) && (OriginalFilePath
!= NULL
)) {
630 SecurityStatus
= gSecurity
->FileAuthenticationState (
632 AuthenticationStatus
,
635 if (EFI_ERROR (SecurityStatus
) && SecurityStatus
!= EFI_SECURITY_VIOLATION
) {
636 Status
= SecurityStatus
;
644 // Allocate a new image structure
646 Image
= CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA
));
648 return EFI_OUT_OF_RESOURCES
;
652 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
654 Status
= CoreHandleProtocol (DeviceHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&HandleFilePath
);
655 if (!EFI_ERROR (Status
)) {
656 FilePathSize
= CoreDevicePathSize (HandleFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
657 FilePath
= (EFI_DEVICE_PATH_PROTOCOL
*) ( ((UINT8
*)FilePath
) + FilePathSize
);
661 // Initialize the fields for an internal driver
663 Image
->Signature
= LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
;
664 Image
->Info
.SystemTable
= gST
;
665 Image
->Info
.DeviceHandle
= DeviceHandle
;
666 Image
->Info
.Revision
= EFI_LOADED_IMAGE_INFORMATION_REVISION
;
667 Image
->Info
.FilePath
= CoreDuplicateDevicePath (FilePath
);
668 Image
->Info
.ParentHandle
= ParentImageHandle
;
670 if (NumberOfPages
!= NULL
) {
671 Image
->NumberOfPages
= *NumberOfPages
;
673 Image
->NumberOfPages
= 0 ;
677 // Install the protocol interfaces for this image
678 // don't fire notifications yet
680 Status
= CoreInstallProtocolInterfaceNotify (
682 &gEfiLoadedImageProtocolGuid
,
683 EFI_NATIVE_INTERFACE
,
687 if (EFI_ERROR (Status
)) {
692 // Load the image. If EntryPoint is Null, it will not be set.
694 Status
= CoreLoadPeImage (&FHand
, Image
, DstBuffer
, EntryPoint
, Attribute
);
695 if (EFI_ERROR (Status
)) {
696 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_OUT_OF_RESOURCES
)) {
697 if (NumberOfPages
!= NULL
) {
698 *NumberOfPages
= Image
->NumberOfPages
;
705 // Register the image in the Debug Image Info Table if the attribute is set
707 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
) {
708 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL
, &Image
->Info
, Image
->Handle
);
712 //Reinstall loaded image protocol to fire any notifications
714 Status
= CoreReinstallProtocolInterface (
716 &gEfiLoadedImageProtocolGuid
,
720 if (EFI_ERROR (Status
)) {
726 // Success. Return the image handle
728 *ImageHandle
= Image
->Handle
;
732 // All done accessing the source file
733 // If we allocated the Source buffer, free it
735 if (FHand
.FreeBuffer
) {
736 CoreFreePool (FHand
.Source
);
740 // There was an error. If there's an Image structure, free it
742 if (EFI_ERROR (Status
)) {
744 CoreUnloadAndCloseImage (Image
, (BOOLEAN
)(DstBuffer
== 0));
757 IN BOOLEAN BootPolicy
,
758 IN EFI_HANDLE ParentImageHandle
,
759 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
760 IN VOID
*SourceBuffer OPTIONAL
,
762 OUT EFI_HANDLE
*ImageHandle
768 Loads an EFI image into memory and returns a handle to the image.
772 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
773 and that the boot manager is attempting to load FilePath as a boot selection.
774 ParentImageHandle - The caller's image handle.
775 FilePath - The specific file path from which the image is loaded.
776 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
777 the image to be loaded.
778 SourceSize - The size in bytes of SourceBuffer.
779 ImageHandle - Pointer to the returned image handle that is created when the image
780 is successfully loaded.
784 EFI_SUCCESS - The image was loaded into memory.
785 EFI_NOT_FOUND - The FilePath was not found.
786 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
787 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
788 parsed to locate the proper protocol for loading the file.
789 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
794 PERF_START (NULL
, "LoadImage", NULL
, 0);
796 Status
= CoreLoadImageCommon (
802 (EFI_PHYSICAL_ADDRESS
)NULL
,
806 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
| EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
809 PERF_END (NULL
, "LoadImage", NULL
, 0);
818 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
819 IN EFI_HANDLE ParentImageHandle
,
820 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
821 IN VOID
*SourceBuffer OPTIONAL
,
823 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
824 OUT UINTN
*NumberOfPages OPTIONAL
,
825 OUT EFI_HANDLE
*ImageHandle
,
826 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
833 Loads an EFI image into memory and returns a handle to the image with extended parameters.
837 This - Calling context
838 ParentImageHandle - The caller's image handle.
839 FilePath - The specific file path from which the image is loaded.
840 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
841 the image to be loaded.
842 SourceSize - The size in bytes of SourceBuffer.
843 DstBuffer - The buffer to store the image.
844 NumberOfPages - For input, specifies the space size of the image by caller if not NULL.
845 For output, specifies the actual space size needed.
846 ImageHandle - Image handle for output.
847 EntryPoint - Image entry point for output.
848 Attribute - The bit mask of attributes to set for the load PE image.
852 EFI_SUCCESS - The image was loaded into memory.
853 EFI_NOT_FOUND - The FilePath was not found.
854 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
855 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
856 parsed to locate the proper protocol for loading the file.
857 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
860 return CoreLoadImageCommon (
880 IN EFI_HANDLE ImageHandle
,
881 OUT UINTN
*ExitDataSize
,
882 OUT CHAR16
**ExitData OPTIONAL
888 Transfer control to a loaded image's entry point.
892 ImageHandle - Handle of image to be started.
894 ExitDataSize - Pointer of the size to ExitData
896 ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated
897 Unicode string, optionally followed by additional binary data. The string
898 is a description that the caller may use to further indicate the reason for
903 EFI_INVALID_PARAMETER - Invalid parameter
905 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
907 EFI_SUCCESS - Successfully transfer control to the image's entry point.
912 LOADED_IMAGE_PRIVATE_DATA
*Image
;
913 LOADED_IMAGE_PRIVATE_DATA
*LastImage
;
914 UINT64 HandleDatabaseKey
;
917 Image
= CoreLoadedImageInfo (ImageHandle
);
918 if (Image
== NULL_HANDLE
|| Image
->Started
) {
919 return EFI_INVALID_PARAMETER
;
923 // Don't profile Objects or invalid start requests
925 PERF_START (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
927 if (sizeof (UINTN
) == 4 && Image
->Machine
== EFI_IMAGE_MACHINE_X64
) {
928 return EFI_UNSUPPORTED
;
929 } else if (sizeof (UINTN
) == 8 && Image
->Machine
== EFI_IMAGE_MACHINE_IA32
) {
930 return EFI_UNSUPPORTED
;
933 // For orther possible cases
938 // Push the current start image context, and
939 // link the current image to the head. This is the
940 // only image that can call Exit()
942 HandleDatabaseKey
= CoreGetHandleDatabaseKey();
943 LastImage
= mCurrentImage
;
944 mCurrentImage
= Image
;
945 Image
->Tpl
= gEfiCurrentTpl
;
948 // Set long jump for Exit() support
950 Image
->JumpContext
= CoreAllocateBootServicesPool (sizeof (*Image
->JumpContext
));
951 if (Image
->JumpContext
== NULL
) {
952 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
953 return EFI_OUT_OF_RESOURCES
;
956 SetJumpFlag
= SetJump (Image
->JumpContext
);
958 // The initial call to SetJump() must always return 0.
959 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
963 // Call the image's entry point
965 Image
->Started
= TRUE
;
966 Image
->Status
= Image
->EntryPoint (ImageHandle
, Image
->Info
.SystemTable
);
969 // Add some debug information if the image returned with error.
970 // This make the user aware and check if the driver image have already released
971 // all the resource in this situation.
974 if (EFI_ERROR (Image
->Status
)) {
975 DEBUG ((EFI_D_ERROR
, "Error: Image at %08X start failed: %x\n", Image
->Info
.ImageBase
, Image
->Status
));
980 // If the image returns, exit it through Exit()
982 CoreExit (ImageHandle
, Image
->Status
, 0, NULL
);
986 // Image has completed. Verify the tpl is the same
988 ASSERT (Image
->Tpl
== gEfiCurrentTpl
);
989 CoreRestoreTpl (Image
->Tpl
);
991 CoreFreePool (Image
->JumpContext
);
994 // Pop the current start image context
996 mCurrentImage
= LastImage
;
999 // Go connect any handles that were created or modified while the image executed.
1001 CoreConnectHandlesByKey (HandleDatabaseKey
);
1004 // Handle the image's returned ExitData
1007 if (Image
->ExitDataSize
!= 0 || Image
->ExitData
!= NULL
) {
1011 "StartImage: ExitDataSize %d, ExitData %x",
1012 Image
->ExitDataSize
,
1015 if (Image
->ExitData
!= NULL
) {
1016 DEBUG ((EFI_D_LOAD
, " (%hs)", Image
->ExitData
));
1018 DEBUG ((EFI_D_LOAD
, "\n"));
1023 // Return the exit data to the caller
1025 if (ExitData
!= NULL
&& ExitDataSize
!= NULL
) {
1026 *ExitDataSize
= Image
->ExitDataSize
;
1027 *ExitData
= Image
->ExitData
;
1030 // Caller doesn't want the exit data, free it
1032 CoreFreePool (Image
->ExitData
);
1033 Image
->ExitData
= NULL
;
1037 // Save the Status because Image will get destroyed if it is unloaded.
1039 Status
= Image
->Status
;
1042 // If the image returned an error, or if the image is an application
1045 if (EFI_ERROR (Image
->Status
) || Image
->Type
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1046 CoreUnloadAndCloseImage (Image
, TRUE
);
1052 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
1058 CoreUnloadAndCloseImage (
1059 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
1064 Routine Description:
1066 Unloads EFI image from memory.
1071 FreePage - Free allocated pages
1081 EFI_HANDLE
*HandleBuffer
;
1083 EFI_GUID
**ProtocolGuidArray
;
1085 UINTN ProtocolIndex
;
1086 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfo
;
1087 UINTN OpenInfoCount
;
1088 UINTN OpenInfoIndex
;
1090 if (Image
->Ebc
!= NULL
) {
1092 // If EBC protocol exists we must perform cleanups for this image.
1094 Image
->Ebc
->UnloadImage (Image
->Ebc
, Image
->Handle
);
1098 // Unload image, free Image->ImageContext->ModHandle
1100 gEfiPeiPeCoffLoader
->UnloadImage (gEfiPeiPeCoffLoader
, &Image
->ImageContext
);
1103 // Free our references to the image handle
1105 if (Image
->Handle
!= NULL_HANDLE
) {
1107 Status
= CoreLocateHandleBuffer (
1114 if (!EFI_ERROR (Status
)) {
1115 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
1116 Status
= CoreProtocolsPerHandle (
1117 HandleBuffer
[HandleIndex
],
1121 if (!EFI_ERROR (Status
)) {
1122 for (ProtocolIndex
= 0; ProtocolIndex
< ArrayCount
; ProtocolIndex
++) {
1123 Status
= CoreOpenProtocolInformation (
1124 HandleBuffer
[HandleIndex
],
1125 ProtocolGuidArray
[ProtocolIndex
],
1129 if (!EFI_ERROR (Status
)) {
1130 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
1131 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== Image
->Handle
) {
1132 Status
= CoreCloseProtocol (
1133 HandleBuffer
[HandleIndex
],
1134 ProtocolGuidArray
[ProtocolIndex
],
1136 OpenInfo
[OpenInfoIndex
].ControllerHandle
1140 if (OpenInfo
!= NULL
) {
1141 CoreFreePool(OpenInfo
);
1145 if (ProtocolGuidArray
!= NULL
) {
1146 CoreFreePool(ProtocolGuidArray
);
1150 if (HandleBuffer
!= NULL
) {
1151 CoreFreePool (HandleBuffer
);
1155 CoreRemoveDebugImageInfoEntry (Image
->Handle
);
1157 Status
= CoreUninstallProtocolInterface (
1159 &gEfiLoadedImageProtocolGuid
,
1164 if (Image
->RuntimeFixupValid
) {
1166 // Remove the Image from the Runtime Image list as we are about to Free it!
1168 RemoveEntryList (&Image
->Link
);
1172 // Free the Image from memory
1174 if ((Image
->ImageBasePage
!= 0) && FreePage
) {
1175 CoreFreePages (Image
->ImageBasePage
, Image
->NumberOfPages
);
1179 // Done with the Image structure
1181 if (Image
->Info
.FilePath
!= NULL
) {
1182 CoreFreePool (Image
->Info
.FilePath
);
1185 if (Image
->FixupData
!= NULL
) {
1186 CoreFreePool (Image
->FixupData
);
1189 CoreFreePool (Image
);
1197 IN EFI_HANDLE ImageHandle
,
1198 IN EFI_STATUS Status
,
1199 IN UINTN ExitDataSize
,
1200 IN CHAR16
*ExitData OPTIONAL
1204 Routine Description:
1206 Terminates the currently loaded EFI image and returns control to boot services.
1210 ImageHandle - Handle that identifies the image. This parameter is passed to the image
1212 Status - The image¡¯s exit code.
1213 ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is
1215 ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string,
1216 optionally followed by additional binary data. The string is a
1217 description that the caller may use to further indicate the reason for
1222 EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image.
1224 EFI_SUCCESS - Successfully terminates the currently loaded EFI image.
1226 EFI_ACCESS_DENIED - Should never reach there.
1228 EFI_OUT_OF_RESOURCES - Could not allocate pool
1232 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1234 Image
= CoreLoadedImageInfo (ImageHandle
);
1235 if (Image
== NULL_HANDLE
) {
1236 return EFI_INVALID_PARAMETER
;
1239 if (!Image
->Started
) {
1241 // The image has not been started so just free its resources
1243 CoreUnloadAndCloseImage (Image
, TRUE
);
1248 // Image has been started, verify this image can exit
1250 if (Image
!= mCurrentImage
) {
1251 DEBUG ((EFI_D_LOAD
|EFI_D_ERROR
, "Exit: Image is not exitable image\n"));
1252 return EFI_INVALID_PARAMETER
;
1258 Image
->Status
= Status
;
1261 // If there's ExitData info, move it
1263 if (ExitData
!= NULL
) {
1264 Image
->ExitDataSize
= ExitDataSize
;
1265 Image
->ExitData
= CoreAllocateBootServicesPool (Image
->ExitDataSize
);
1266 if (Image
->ExitData
== NULL
) {
1267 return EFI_OUT_OF_RESOURCES
;
1269 CopyMem (Image
->ExitData
, ExitData
, Image
->ExitDataSize
);
1273 // return to StartImage
1275 LongJump (Image
->JumpContext
, (UINTN
)-1);
1278 // If we return from LongJump, then it is an error
1281 return EFI_ACCESS_DENIED
;
1289 IN EFI_HANDLE ImageHandle
1293 Routine Description:
1299 ImageHandle - Handle that identifies the image to be unloaded.
1303 EFI_SUCCESS - The image has been unloaded.
1304 EFI_UNSUPPORTED - The image has been sarted, and does not support unload.
1305 EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle.
1310 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1312 Image
= CoreLoadedImageInfo (ImageHandle
);
1313 if (Image
== NULL
) {
1315 // The image handle is not valid
1317 return EFI_INVALID_PARAMETER
;
1320 if (Image
->Started
) {
1322 // The image has been started, request it to unload.
1324 Status
= EFI_UNSUPPORTED
;
1325 if (Image
->Info
.Unload
!= NULL
) {
1326 Status
= Image
->Info
.Unload (ImageHandle
);
1331 // This Image hasn't been started, thus it can be unloaded
1333 Status
= EFI_SUCCESS
;
1337 if (!EFI_ERROR (Status
)) {
1339 // if the Image was not started or Unloaded O.K. then clean up
1341 CoreUnloadAndCloseImage (Image
, TRUE
);
1351 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
1352 IN EFI_HANDLE ImageHandle
1356 Routine Description:
1358 Unload the specified image.
1362 This - Indicates the calling context.
1364 ImageHandle - The specified image handle.
1368 EFI_INVALID_PARAMETER - Image handle is NULL.
1370 EFI_UNSUPPORTED - Attempt to unload an unsupported image.
1372 EFI_SUCCESS - Image successfully unloaded.
1376 return CoreUnloadImage (ImageHandle
);