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
27 LOADED_IMAGE_PRIVATE_DATA
*mCurrentImage
= NULL
;
29 LOAD_PE32_IMAGE_PRIVATE_DATA mLoadPe32PrivateData
= {
30 LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE
,
40 // This code is needed to build the Image handle for the DXE Core
42 LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage
= {
43 LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
, // Signature
45 EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
, // Image type
46 TRUE
, // If entrypoint has been called
49 EFI_LOADED_IMAGE_INFORMATION_REVISION
, // Revision
50 NULL
, // Parent handle
51 NULL
, // System handle
53 NULL
, // Device handle
62 EfiBootServicesCode
, // ImageCodeType
63 EfiBootServicesData
// ImageDataType
65 (EFI_PHYSICAL_ADDRESS
)0, // ImageBasePage
69 EFI_SUCCESS
, // Status
81 CoreInitializeImageServices (
88 Add the Image Services to EFI Boot Services Table and install the protocol
89 interfaces for this image.
93 HobStart - The HOB to initialize
102 LOADED_IMAGE_PRIVATE_DATA
*Image
;
103 EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress
;
104 UINT64 DxeCoreImageLength
;
105 VOID
*DxeCoreEntryPoint
;
106 EFI_PEI_HOB_POINTERS DxeCoreHob
;
108 // Searching for image hob
110 DxeCoreHob
.Raw
= HobStart
;
111 while ((DxeCoreHob
.Raw
= GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, DxeCoreHob
.Raw
)) != NULL
) {
112 if (CompareGuid (&DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.Name
, &gEfiHobMemoryAllocModuleGuid
)) {
118 DxeCoreHob
.Raw
= GET_NEXT_HOB (DxeCoreHob
);
120 ASSERT (DxeCoreHob
.Raw
!= NULL
);
122 DxeCoreImageBaseAddress
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryBaseAddress
;
123 DxeCoreImageLength
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryLength
;
124 DxeCoreEntryPoint
= (VOID
*) (UINTN
) DxeCoreHob
.MemoryAllocationModule
->EntryPoint
;
125 gDxeCoreFileName
= &DxeCoreHob
.MemoryAllocationModule
->ModuleName
;
127 // Initialize the fields for an internal driver
129 Image
= &mCorePrivateImage
;
131 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)DxeCoreEntryPoint
;
132 Image
->ImageBasePage
= DxeCoreImageBaseAddress
;
133 Image
->NumberOfPages
= (UINTN
)(EFI_SIZE_TO_PAGES((UINTN
)(DxeCoreImageLength
)));
134 Image
->Tpl
= gEfiCurrentTpl
;
135 Image
->Info
.SystemTable
= gST
;
136 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)DxeCoreImageBaseAddress
;
137 Image
->Info
.ImageSize
= DxeCoreImageLength
;
140 // Install the protocol interfaces for this image
142 Status
= CoreInstallProtocolInterface (
144 &gEfiLoadedImageProtocolGuid
,
145 EFI_NATIVE_INTERFACE
,
148 ASSERT_EFI_ERROR (Status
);
150 mCurrentImage
= Image
;
153 // Fill in DXE globals
155 gDxeCoreImageHandle
= Image
->Handle
;
156 gDxeCoreLoadedImage
= &Image
->Info
;
159 // Export DXE Core PE Loader functionality
161 return CoreInstallProtocolInterface (
162 &mLoadPe32PrivateData
.Handle
,
163 &gEfiLoadPeImageProtocolGuid
,
164 EFI_NATIVE_INTERFACE
,
165 &mLoadPe32PrivateData
.Pe32Image
172 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
173 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
174 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
181 Loads, relocates, and invokes a PE/COFF image
185 Pe32Handle - The handle of PE32 image
186 Image - PE image to be loaded
187 DstBuffer - The buffer to store the image
188 EntryPoint - A pointer to the entry point
189 Attribute - The bit mask of attributes to set for the load PE image
193 EFI_SUCCESS - The file was loaded, relocated, and invoked
195 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
197 EFI_INVALID_PARAMETER - Invalid parameter
199 EFI_BUFFER_TOO_SMALL - Buffer for image is too small
204 BOOLEAN DstBufAlocated
;
207 ZeroMem (&Image
->ImageContext
, sizeof (Image
->ImageContext
));
209 Image
->ImageContext
.Handle
= Pe32Handle
;
210 Image
->ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)CoreReadImageFile
;
213 // Get information about the image being loaded
215 Status
= gEfiPeiPeCoffLoader
->GetImageInfo (gEfiPeiPeCoffLoader
, &Image
->ImageContext
);
216 if (EFI_ERROR (Status
)) {
220 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image
->ImageContext
.Machine
)) {
222 // The PE/COFF loader can support loading image types that can be executed.
223 // If we loaded an image type that we can not execute return EFI_UNSUPORTED.
225 return EFI_UNSUPPORTED
;
230 // Allocate memory of the correct memory type aligned on the required image boundry
232 DstBufAlocated
= FALSE
;
233 if (DstBuffer
== 0) {
235 // Allocate Destination Buffer as caller did not pass it in
238 if (Image
->ImageContext
.SectionAlignment
> EFI_PAGE_SIZE
) {
239 Size
= (UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
;
241 Size
= (UINTN
)Image
->ImageContext
.ImageSize
;
244 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES (Size
);
247 // If the image relocations have not been stripped, then load at any address.
248 // Otherwise load at the address at which it was linked.
250 Status
= CoreAllocatePages (
251 (Image
->ImageContext
.RelocationsStripped
) ? AllocateAddress
: AllocateAnyPages
,
252 Image
->ImageContext
.ImageCodeMemoryType
,
253 Image
->NumberOfPages
,
254 &Image
->ImageContext
.ImageAddress
256 if (EFI_ERROR (Status
)) {
259 DstBufAlocated
= TRUE
;
263 // Caller provided the destination buffer
266 if (Image
->ImageContext
.RelocationsStripped
&& (Image
->ImageContext
.ImageAddress
!= DstBuffer
)) {
268 // If the image relocations were stripped, and the caller provided a
269 // destination buffer address that does not match the address that the
270 // image is linked at, then the image cannot be loaded.
272 return EFI_INVALID_PARAMETER
;
275 if (Image
->NumberOfPages
!= 0 &&
276 Image
->NumberOfPages
<
277 (EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
))) {
278 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
279 return EFI_BUFFER_TOO_SMALL
;
282 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
283 Image
->ImageContext
.ImageAddress
= DstBuffer
;
286 Image
->ImageBasePage
= Image
->ImageContext
.ImageAddress
;
287 Image
->ImageContext
.ImageAddress
=
288 (Image
->ImageContext
.ImageAddress
+ Image
->ImageContext
.SectionAlignment
- 1) &
289 ~((UINTN
)Image
->ImageContext
.SectionAlignment
- 1);
292 // Load the image from the file into the allocated memory
294 Status
= gEfiPeiPeCoffLoader
->LoadImage (gEfiPeiPeCoffLoader
, &Image
->ImageContext
);
295 if (EFI_ERROR (Status
)) {
300 // If this is a Runtime Driver, then allocate memory for the FixupData that
301 // is used to relocate the image when SetVirtualAddressMap() is called. The
302 // relocation is done by the Runtime AP.
304 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) {
305 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
306 Image
->ImageContext
.FixupData
= CoreAllocateRuntimePool ((UINTN
)(Image
->ImageContext
.FixupDataSize
));
307 if (Image
->ImageContext
.FixupData
== NULL
) {
308 Status
= EFI_OUT_OF_RESOURCES
;
315 // Relocate the image in memory
317 Status
= gEfiPeiPeCoffLoader
->RelocateImage (gEfiPeiPeCoffLoader
, &Image
->ImageContext
);
318 if (EFI_ERROR (Status
)) {
323 // Flush the Instruction Cache
325 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
, (UINTN
)Image
->ImageContext
.ImageSize
);
328 // Copy the machine type from the context to the image private data. This
329 // is needed during image unload to know if we should call an EBC protocol
330 // to unload the image.
332 Image
->Machine
= Image
->ImageContext
.Machine
;
335 // Get the image entry point. If it's an EBC image, then call into the
336 // interpreter to create a thunk for the entry point and use the returned
337 // value for the entry point.
339 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)Image
->ImageContext
.EntryPoint
;
340 if (Image
->ImageContext
.Machine
== EFI_IMAGE_MACHINE_EBC
) {
342 // Locate the EBC interpreter protocol
344 Status
= CoreLocateProtocol (&gEfiEbcProtocolGuid
, NULL
, (VOID
**)&Image
->Ebc
);
345 if (EFI_ERROR(Status
)) {
350 // Register a callback for flushing the instruction cache so that created
351 // thunks can be flushed.
353 Status
= Image
->Ebc
->RegisterICacheFlush (Image
->Ebc
, (EBC_ICACHE_FLUSH
)InvalidateInstructionCacheRange
);
354 if (EFI_ERROR(Status
)) {
359 // Create a thunk for the image's entry point. This will be the new
360 // entry point for the image.
362 Status
= Image
->Ebc
->CreateThunk (
365 (VOID
*)(UINTN
)Image
->ImageContext
.EntryPoint
,
366 (VOID
**)&Image
->EntryPoint
368 if (EFI_ERROR(Status
)) {
374 // Fill in the image information for the Loaded Image Protocol
376 Image
->Type
= Image
->ImageContext
.ImageType
;
377 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
;
378 Image
->Info
.ImageSize
= Image
->ImageContext
.ImageSize
;
379 Image
->Info
.ImageCodeType
= Image
->ImageContext
.ImageCodeMemoryType
;
380 Image
->Info
.ImageDataType
= Image
->ImageContext
.ImageDataMemoryType
;
381 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) {
382 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
384 // Make a list off all the RT images so we can let the RT AP know about them.
386 Image
->RuntimeData
= CoreAllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY
));
387 if (Image
->RuntimeData
== NULL
) {
390 Image
->RuntimeData
->ImageBase
= Image
->Info
.ImageBase
;
391 Image
->RuntimeData
->ImageSize
= (UINT64
) (Image
->Info
.ImageSize
);
392 Image
->RuntimeData
->RelocationData
= Image
->ImageContext
.FixupData
;
393 Image
->RuntimeData
->Handle
= Image
->Handle
;
394 InsertTailList (&gRuntime
->ImageHead
, &Image
->RuntimeData
->Link
);
399 // Fill in the entry point of the image if it is available
401 if (EntryPoint
!= NULL
) {
402 *EntryPoint
= Image
->ImageContext
.EntryPoint
;
406 // Print the load address and the PDB file name if it is available
413 CHAR8 EfiFileName
[256];
415 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
));
416 if (Image
->ImageContext
.PdbPointer
!= NULL
) {
418 for (Index
= 0; Image
->ImageContext
.PdbPointer
[Index
] != 0; Index
++) {
419 if (Image
->ImageContext
.PdbPointer
[Index
] == '\\') {
420 StartIndex
= Index
+ 1;
424 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
426 for (Index
= 0; Index
< sizeof (EfiFileName
); Index
++) {
427 EfiFileName
[Index
] = Image
->ImageContext
.PdbPointer
[Index
+ StartIndex
];
428 if (EfiFileName
[Index
] == 0) {
429 EfiFileName
[Index
] = '.';
431 if (EfiFileName
[Index
] == '.') {
432 EfiFileName
[Index
+ 1] = 'e';
433 EfiFileName
[Index
+ 2] = 'f';
434 EfiFileName
[Index
+ 3] = 'i';
435 EfiFileName
[Index
+ 4] = 0;
439 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "%a", EfiFileName
)); // &Image->ImageContext.PdbPointer[StartIndex]));
441 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "\n"));
453 if (DstBufAlocated
) {
454 CoreFreePages (Image
->ImageContext
.ImageAddress
, Image
->NumberOfPages
);
457 if (Image
->ImageContext
.FixupData
!= NULL
) {
458 CoreFreePool (Image
->ImageContext
.FixupData
);
465 LOADED_IMAGE_PRIVATE_DATA
*
466 CoreLoadedImageInfo (
467 IN EFI_HANDLE ImageHandle
473 Get the image's private data from its handle.
477 ImageHandle - The image handle
481 Return the image private data associated with ImageHandle.
486 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
487 LOADED_IMAGE_PRIVATE_DATA
*Image
;
489 Status
= CoreHandleProtocol (
491 &gEfiLoadedImageProtocolGuid
,
492 (VOID
**)&LoadedImage
494 if (!EFI_ERROR (Status
)) {
495 Image
= LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage
);
497 DEBUG ((EFI_D_LOAD
, "CoreLoadedImageInfo: Not an ImageHandle %x\n", ImageHandle
));
506 CoreLoadImageCommon (
507 IN BOOLEAN BootPolicy
,
508 IN EFI_HANDLE ParentImageHandle
,
509 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
510 IN VOID
*SourceBuffer OPTIONAL
,
512 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
513 IN OUT UINTN
*NumberOfPages OPTIONAL
,
514 OUT EFI_HANDLE
*ImageHandle
,
515 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
522 Loads an EFI image into memory and returns a handle to the image.
526 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
527 and that the boot manager is attempting to load FilePath as a boot selection.
528 ParentImageHandle - The caller's image handle.
529 FilePath - The specific file path from which the image is loaded.
530 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
531 the image to be loaded.
532 SourceSize - The size in bytes of SourceBuffer.
533 DstBuffer - The buffer to store the image
534 NumberOfPages - If not NULL, a pointer to the image's page number, if this number
535 is not enough, return EFI_BUFFER_TOO_SMALL and this parameter contain
537 ImageHandle - Pointer to the returned image handle that is created when the image
538 is successfully loaded.
539 EntryPoint - A pointer to the entry point
540 Attribute - The bit mask of attributes to set for the load PE image
544 EFI_SUCCESS - The image was loaded into memory.
545 EFI_NOT_FOUND - The FilePath was not found.
546 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
547 EFI_BUFFER_TOO_SMALL - The buffer is too small
548 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
549 parsed to locate the proper protocol for loading the file.
550 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
553 LOADED_IMAGE_PRIVATE_DATA
*Image
;
554 LOADED_IMAGE_PRIVATE_DATA
*ParentImage
;
555 IMAGE_FILE_HANDLE FHand
;
557 EFI_STATUS SecurityStatus
;
558 EFI_HANDLE DeviceHandle
;
559 UINT32 AuthenticationStatus
;
560 EFI_DEVICE_PATH_PROTOCOL
*OriginalFilePath
;
561 EFI_DEVICE_PATH_PROTOCOL
*HandleFilePath
;
564 SecurityStatus
= EFI_SUCCESS
;
566 ASSERT (gEfiCurrentTpl
< EFI_TPL_NOTIFY
);
570 // The caller must pass in a valid ParentImageHandle
572 if (ImageHandle
== NULL
|| ParentImageHandle
== NULL
) {
573 return EFI_INVALID_PARAMETER
;
576 ParentImage
= CoreLoadedImageInfo (ParentImageHandle
);
577 if (ParentImage
== NULL
) {
578 DEBUG((EFI_D_LOAD
|EFI_D_ERROR
, "LoadImageEx: Parent handle not an image handle\n"));
579 return EFI_INVALID_PARAMETER
;
583 // Get simple read access to the source file
585 OriginalFilePath
= FilePath
;
586 Status
= CoreOpenImageFile (
593 &AuthenticationStatus
595 if (Status
== EFI_ALREADY_STARTED
) {
598 } else if (EFI_ERROR (Status
)) {
603 // Verify the Authentication Status through the Security Architectural Protocol
605 if ((gSecurity
!= NULL
) && (OriginalFilePath
!= NULL
)) {
606 SecurityStatus
= gSecurity
->FileAuthenticationState (
608 AuthenticationStatus
,
611 if (EFI_ERROR (SecurityStatus
) && SecurityStatus
!= EFI_SECURITY_VIOLATION
) {
612 Status
= SecurityStatus
;
620 // Allocate a new image structure
622 Image
= CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA
));
624 return EFI_OUT_OF_RESOURCES
;
628 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
630 Status
= CoreHandleProtocol (DeviceHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&HandleFilePath
);
631 if (!EFI_ERROR (Status
)) {
632 FilePathSize
= CoreDevicePathSize (HandleFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
633 FilePath
= (EFI_DEVICE_PATH_PROTOCOL
*) ( ((UINT8
*)FilePath
) + FilePathSize
);
637 // Initialize the fields for an internal driver
639 Image
->Signature
= LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
;
640 Image
->Info
.SystemTable
= gST
;
641 Image
->Info
.DeviceHandle
= DeviceHandle
;
642 Image
->Info
.Revision
= EFI_LOADED_IMAGE_INFORMATION_REVISION
;
643 Image
->Info
.FilePath
= CoreDuplicateDevicePath (FilePath
);
644 Image
->Info
.ParentHandle
= ParentImageHandle
;
646 if (NumberOfPages
!= NULL
) {
647 Image
->NumberOfPages
= *NumberOfPages
;
649 Image
->NumberOfPages
= 0 ;
653 // Install the protocol interfaces for this image
654 // don't fire notifications yet
656 Status
= CoreInstallProtocolInterfaceNotify (
658 &gEfiLoadedImageProtocolGuid
,
659 EFI_NATIVE_INTERFACE
,
663 if (EFI_ERROR (Status
)) {
668 // Load the image. If EntryPoint is Null, it will not be set.
670 Status
= CoreLoadPeImage (&FHand
, Image
, DstBuffer
, EntryPoint
, Attribute
);
671 if (EFI_ERROR (Status
)) {
672 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_OUT_OF_RESOURCES
)) {
673 if (NumberOfPages
!= NULL
) {
674 *NumberOfPages
= Image
->NumberOfPages
;
681 // Register the image in the Debug Image Info Table if the attribute is set
683 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
) {
684 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL
, &Image
->Info
, Image
->Handle
);
688 //Reinstall loaded image protocol to fire any notifications
690 Status
= CoreReinstallProtocolInterface (
692 &gEfiLoadedImageProtocolGuid
,
696 if (EFI_ERROR (Status
)) {
702 // Success. Return the image handle
704 *ImageHandle
= Image
->Handle
;
708 // All done accessing the source file
709 // If we allocated the Source buffer, free it
711 if (FHand
.FreeBuffer
) {
712 CoreFreePool (FHand
.Source
);
716 // There was an error. If there's an Image structure, free it
718 if (EFI_ERROR (Status
)) {
720 CoreUnloadAndCloseImage (Image
, (BOOLEAN
)(DstBuffer
== 0));
723 } else if (EFI_ERROR (SecurityStatus
)) {
724 Status
= SecurityStatus
;
735 IN BOOLEAN BootPolicy
,
736 IN EFI_HANDLE ParentImageHandle
,
737 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
738 IN VOID
*SourceBuffer OPTIONAL
,
740 OUT EFI_HANDLE
*ImageHandle
746 Loads an EFI image into memory and returns a handle to the image.
750 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
751 and that the boot manager is attempting to load FilePath as a boot selection.
752 ParentImageHandle - The caller's image handle.
753 FilePath - The specific file path from which the image is loaded.
754 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
755 the image to be loaded.
756 SourceSize - The size in bytes of SourceBuffer.
757 ImageHandle - Pointer to the returned image handle that is created when the image
758 is successfully loaded.
762 EFI_SUCCESS - The image was loaded into memory.
763 EFI_NOT_FOUND - The FilePath was not found.
764 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
765 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
766 parsed to locate the proper protocol for loading the file.
767 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
772 PERF_START (NULL
, "LoadImage", NULL
, 0);
774 Status
= CoreLoadImageCommon (
780 (EFI_PHYSICAL_ADDRESS
)NULL
,
784 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
| EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
787 PERF_END (NULL
, "LoadImage", NULL
, 0);
796 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
797 IN EFI_HANDLE ParentImageHandle
,
798 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
799 IN VOID
*SourceBuffer OPTIONAL
,
801 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
802 OUT UINTN
*NumberOfPages OPTIONAL
,
803 OUT EFI_HANDLE
*ImageHandle
,
804 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
811 Loads an EFI image into memory and returns a handle to the image with extended parameters.
815 This - Calling context
816 ParentImageHandle - The caller's image handle.
817 FilePath - The specific file path from which the image is loaded.
818 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
819 the image to be loaded.
820 SourceSize - The size in bytes of SourceBuffer.
821 DstBuffer - The buffer to store the image.
822 NumberOfPages - For input, specifies the space size of the image by caller if not NULL.
823 For output, specifies the actual space size needed.
824 ImageHandle - Image handle for output.
825 EntryPoint - Image entry point for output.
826 Attribute - The bit mask of attributes to set for the load PE image.
830 EFI_SUCCESS - The image was loaded into memory.
831 EFI_NOT_FOUND - The FilePath was not found.
832 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
833 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
834 parsed to locate the proper protocol for loading the file.
835 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
838 return CoreLoadImageCommon (
858 IN EFI_HANDLE ImageHandle
,
859 OUT UINTN
*ExitDataSize
,
860 OUT CHAR16
**ExitData OPTIONAL
866 Transfer control to a loaded image's entry point.
870 ImageHandle - Handle of image to be started.
872 ExitDataSize - Pointer of the size to ExitData
874 ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated
875 Unicode string, optionally followed by additional binary data. The string
876 is a description that the caller may use to further indicate the reason for
881 EFI_INVALID_PARAMETER - Invalid parameter
883 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
885 EFI_SUCCESS - Successfully transfer control to the image's entry point.
890 LOADED_IMAGE_PRIVATE_DATA
*Image
;
891 LOADED_IMAGE_PRIVATE_DATA
*LastImage
;
892 UINT64 HandleDatabaseKey
;
895 Image
= CoreLoadedImageInfo (ImageHandle
);
896 if (Image
== NULL_HANDLE
|| Image
->Started
) {
897 return EFI_INVALID_PARAMETER
;
901 // Don't profile Objects or invalid start requests
903 PERF_START (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
907 // Push the current start image context, and
908 // link the current image to the head. This is the
909 // only image that can call Exit()
911 HandleDatabaseKey
= CoreGetHandleDatabaseKey ();
912 LastImage
= mCurrentImage
;
913 mCurrentImage
= Image
;
914 Image
->Tpl
= gEfiCurrentTpl
;
917 // Set long jump for Exit() support
918 // JumpContext must be aligned on a CPU specific boundary.
919 // Overallocate the buffer and force the required alignment
921 Image
->JumpBuffer
= CoreAllocateBootServicesPool (sizeof (BASE_LIBRARY_JUMP_BUFFER
) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
922 if (Image
->JumpBuffer
== NULL
) {
923 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
924 return EFI_OUT_OF_RESOURCES
;
926 Image
->JumpContext
= ALIGN_POINTER (Image
->JumpBuffer
, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
928 SetJumpFlag
= SetJump (Image
->JumpContext
);
930 // The initial call to SetJump() must always return 0.
931 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
935 // Call the image's entry point
937 Image
->Started
= TRUE
;
938 Image
->Status
= Image
->EntryPoint (ImageHandle
, Image
->Info
.SystemTable
);
941 // Add some debug information if the image returned with error.
942 // This make the user aware and check if the driver image have already released
943 // all the resource in this situation.
946 if (EFI_ERROR (Image
->Status
)) {
947 DEBUG ((EFI_D_ERROR
, "Error: Image at %10p start failed: %r\n", Image
->Info
.ImageBase
, Image
->Status
));
952 // If the image returns, exit it through Exit()
954 CoreExit (ImageHandle
, Image
->Status
, 0, NULL
);
958 // Image has completed. Verify the tpl is the same
960 ASSERT (Image
->Tpl
== gEfiCurrentTpl
);
961 CoreRestoreTpl (Image
->Tpl
);
963 CoreFreePool (Image
->JumpBuffer
);
966 // Pop the current start image context
968 mCurrentImage
= LastImage
;
971 // Go connect any handles that were created or modified while the image executed.
973 CoreConnectHandlesByKey (HandleDatabaseKey
);
976 // Handle the image's returned ExitData
979 if (Image
->ExitDataSize
!= 0 || Image
->ExitData
!= NULL
) {
983 "StartImage: ExitDataSize %d, ExitData %x",
987 if (Image
->ExitData
!= NULL
) {
988 DEBUG ((EFI_D_LOAD
, " (%hs)", Image
->ExitData
));
990 DEBUG ((EFI_D_LOAD
, "\n"));
995 // Return the exit data to the caller
997 if (ExitData
!= NULL
&& ExitDataSize
!= NULL
) {
998 *ExitDataSize
= Image
->ExitDataSize
;
999 *ExitData
= Image
->ExitData
;
1002 // Caller doesn't want the exit data, free it
1004 CoreFreePool (Image
->ExitData
);
1005 Image
->ExitData
= NULL
;
1009 // Save the Status because Image will get destroyed if it is unloaded.
1011 Status
= Image
->Status
;
1014 // If the image returned an error, or if the image is an application
1017 if (EFI_ERROR (Image
->Status
) || Image
->Type
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1018 CoreUnloadAndCloseImage (Image
, TRUE
);
1024 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
1030 CoreUnloadAndCloseImage (
1031 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
1036 Routine Description:
1038 Unloads EFI image from memory.
1043 FreePage - Free allocated pages
1053 EFI_HANDLE
*HandleBuffer
;
1055 EFI_GUID
**ProtocolGuidArray
;
1057 UINTN ProtocolIndex
;
1058 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfo
;
1059 UINTN OpenInfoCount
;
1060 UINTN OpenInfoIndex
;
1062 if (Image
->Ebc
!= NULL
) {
1064 // If EBC protocol exists we must perform cleanups for this image.
1066 Image
->Ebc
->UnloadImage (Image
->Ebc
, Image
->Handle
);
1070 // Unload image, free Image->ImageContext->ModHandle
1072 gEfiPeiPeCoffLoader
->UnloadImage (gEfiPeiPeCoffLoader
, &Image
->ImageContext
);
1075 // Free our references to the image handle
1077 if (Image
->Handle
!= NULL_HANDLE
) {
1079 Status
= CoreLocateHandleBuffer (
1086 if (!EFI_ERROR (Status
)) {
1087 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
1088 Status
= CoreProtocolsPerHandle (
1089 HandleBuffer
[HandleIndex
],
1093 if (!EFI_ERROR (Status
)) {
1094 for (ProtocolIndex
= 0; ProtocolIndex
< ArrayCount
; ProtocolIndex
++) {
1095 Status
= CoreOpenProtocolInformation (
1096 HandleBuffer
[HandleIndex
],
1097 ProtocolGuidArray
[ProtocolIndex
],
1101 if (!EFI_ERROR (Status
)) {
1102 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
1103 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== Image
->Handle
) {
1104 Status
= CoreCloseProtocol (
1105 HandleBuffer
[HandleIndex
],
1106 ProtocolGuidArray
[ProtocolIndex
],
1108 OpenInfo
[OpenInfoIndex
].ControllerHandle
1112 if (OpenInfo
!= NULL
) {
1113 CoreFreePool(OpenInfo
);
1117 if (ProtocolGuidArray
!= NULL
) {
1118 CoreFreePool(ProtocolGuidArray
);
1122 if (HandleBuffer
!= NULL
) {
1123 CoreFreePool (HandleBuffer
);
1127 CoreRemoveDebugImageInfoEntry (Image
->Handle
);
1129 Status
= CoreUninstallProtocolInterface (
1131 &gEfiLoadedImageProtocolGuid
,
1136 if (Image
->RuntimeData
!= NULL
) {
1137 if (Image
->RuntimeData
->Link
.ForwardLink
!= NULL
) {
1139 // Remove the Image from the Runtime Image list as we are about to Free it!
1141 RemoveEntryList (&Image
->RuntimeData
->Link
);
1143 CoreFreePool (Image
->RuntimeData
);
1147 // Free the Image from memory
1149 if ((Image
->ImageBasePage
!= 0) && FreePage
) {
1150 CoreFreePages (Image
->ImageBasePage
, Image
->NumberOfPages
);
1154 // Done with the Image structure
1156 if (Image
->Info
.FilePath
!= NULL
) {
1157 CoreFreePool (Image
->Info
.FilePath
);
1160 if (Image
->FixupData
!= NULL
) {
1161 CoreFreePool (Image
->FixupData
);
1164 CoreFreePool (Image
);
1172 IN EFI_HANDLE ImageHandle
,
1173 IN EFI_STATUS Status
,
1174 IN UINTN ExitDataSize
,
1175 IN CHAR16
*ExitData OPTIONAL
1179 Routine Description:
1181 Terminates the currently loaded EFI image and returns control to boot services.
1185 ImageHandle - Handle that identifies the image. This parameter is passed to the image
1187 Status - The image's exit code.
1188 ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is
1190 ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string,
1191 optionally followed by additional binary data. The string is a
1192 description that the caller may use to further indicate the reason for
1197 EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image.
1199 EFI_SUCCESS - Successfully terminates the currently loaded EFI image.
1201 EFI_ACCESS_DENIED - Should never reach there.
1203 EFI_OUT_OF_RESOURCES - Could not allocate pool
1207 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1209 Image
= CoreLoadedImageInfo (ImageHandle
);
1210 if (Image
== NULL_HANDLE
) {
1211 return EFI_INVALID_PARAMETER
;
1214 if (!Image
->Started
) {
1216 // The image has not been started so just free its resources
1218 CoreUnloadAndCloseImage (Image
, TRUE
);
1223 // Image has been started, verify this image can exit
1225 if (Image
!= mCurrentImage
) {
1226 DEBUG ((EFI_D_LOAD
|EFI_D_ERROR
, "Exit: Image is not exitable image\n"));
1227 return EFI_INVALID_PARAMETER
;
1233 Image
->Status
= Status
;
1236 // If there's ExitData info, move it
1238 if (ExitData
!= NULL
) {
1239 Image
->ExitDataSize
= ExitDataSize
;
1240 Image
->ExitData
= CoreAllocateBootServicesPool (Image
->ExitDataSize
);
1241 if (Image
->ExitData
== NULL
) {
1242 return EFI_OUT_OF_RESOURCES
;
1244 CopyMem (Image
->ExitData
, ExitData
, Image
->ExitDataSize
);
1248 // return to StartImage
1250 LongJump (Image
->JumpContext
, (UINTN
)-1);
1253 // If we return from LongJump, then it is an error
1256 return EFI_ACCESS_DENIED
;
1264 IN EFI_HANDLE ImageHandle
1268 Routine Description:
1274 ImageHandle - Handle that identifies the image to be unloaded.
1278 EFI_SUCCESS - The image has been unloaded.
1279 EFI_UNSUPPORTED - The image has been sarted, and does not support unload.
1280 EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle.
1285 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1287 Image
= CoreLoadedImageInfo (ImageHandle
);
1288 if (Image
== NULL
) {
1290 // The image handle is not valid
1292 return EFI_INVALID_PARAMETER
;
1295 if (Image
->Started
) {
1297 // The image has been started, request it to unload.
1299 Status
= EFI_UNSUPPORTED
;
1300 if (Image
->Info
.Unload
!= NULL
) {
1301 Status
= Image
->Info
.Unload (ImageHandle
);
1306 // This Image hasn't been started, thus it can be unloaded
1308 Status
= EFI_SUCCESS
;
1312 if (!EFI_ERROR (Status
)) {
1314 // if the Image was not started or Unloaded O.K. then clean up
1316 CoreUnloadAndCloseImage (Image
, TRUE
);
1326 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
1327 IN EFI_HANDLE ImageHandle
1331 Routine Description:
1333 Unload the specified image.
1337 This - Indicates the calling context.
1339 ImageHandle - The specified image handle.
1343 EFI_INVALID_PARAMETER - Image handle is NULL.
1345 EFI_UNSUPPORTED - Attempt to unload an unsupported image.
1347 EFI_SUCCESS - Image successfully unloaded.
1351 return CoreUnloadImage (ImageHandle
);