3 Copyright (c) 2006 - 2007, 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
77 NULL
, // DeviceHandleDevicePath
82 CoreInitializeImageServices (
89 Add the Image Services to EFI Boot Services Table and install the protocol
90 interfaces for this image.
94 HobStart - The HOB to initialize
103 LOADED_IMAGE_PRIVATE_DATA
*Image
;
104 EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress
;
105 UINT64 DxeCoreImageLength
;
106 VOID
*DxeCoreEntryPoint
;
107 EFI_PEI_HOB_POINTERS DxeCoreHob
;
109 // Searching for image hob
111 DxeCoreHob
.Raw
= HobStart
;
112 while ((DxeCoreHob
.Raw
= GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, DxeCoreHob
.Raw
)) != NULL
) {
113 if (CompareGuid (&DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.Name
, &gEfiHobMemoryAllocModuleGuid
)) {
119 DxeCoreHob
.Raw
= GET_NEXT_HOB (DxeCoreHob
);
121 ASSERT (DxeCoreHob
.Raw
!= NULL
);
123 DxeCoreImageBaseAddress
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryBaseAddress
;
124 DxeCoreImageLength
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryLength
;
125 DxeCoreEntryPoint
= (VOID
*) (UINTN
) DxeCoreHob
.MemoryAllocationModule
->EntryPoint
;
126 gDxeCoreFileName
= &DxeCoreHob
.MemoryAllocationModule
->ModuleName
;
128 // Initialize the fields for an internal driver
130 Image
= &mCorePrivateImage
;
132 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)DxeCoreEntryPoint
;
133 Image
->ImageBasePage
= DxeCoreImageBaseAddress
;
134 Image
->NumberOfPages
= (UINTN
)(EFI_SIZE_TO_PAGES((UINTN
)(DxeCoreImageLength
)));
135 Image
->Tpl
= gEfiCurrentTpl
;
136 Image
->Info
.SystemTable
= gDxeCoreST
;
137 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)DxeCoreImageBaseAddress
;
138 Image
->Info
.ImageSize
= DxeCoreImageLength
;
141 // Install the protocol interfaces for this image
143 Status
= CoreInstallProtocolInterface (
145 &gEfiLoadedImageProtocolGuid
,
146 EFI_NATIVE_INTERFACE
,
149 ASSERT_EFI_ERROR (Status
);
151 mCurrentImage
= Image
;
154 // Fill in DXE globals
156 gDxeCoreImageHandle
= Image
->Handle
;
157 gDxeCoreLoadedImage
= &Image
->Info
;
160 // Export DXE Core PE Loader functionality
162 return CoreInstallProtocolInterface (
163 &mLoadPe32PrivateData
.Handle
,
164 &gEfiLoadPeImageProtocolGuid
,
165 EFI_NATIVE_INTERFACE
,
166 &mLoadPe32PrivateData
.Pe32Image
173 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
174 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
175 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
182 Loads, relocates, and invokes a PE/COFF image
186 Pe32Handle - The handle of PE32 image
187 Image - PE image to be loaded
188 DstBuffer - The buffer to store the image
189 EntryPoint - A pointer to the entry point
190 Attribute - The bit mask of attributes to set for the load PE image
194 EFI_SUCCESS - The file was loaded, relocated, and invoked
196 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
198 EFI_INVALID_PARAMETER - Invalid parameter
200 EFI_BUFFER_TOO_SMALL - Buffer for image is too small
205 BOOLEAN DstBufAlocated
;
208 ZeroMem (&Image
->ImageContext
, sizeof (Image
->ImageContext
));
210 Image
->ImageContext
.Handle
= Pe32Handle
;
211 Image
->ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)CoreReadImageFile
;
214 // Get information about the image being loaded
216 Status
= PeCoffLoaderGetImageInfo (&Image
->ImageContext
);
217 if (EFI_ERROR (Status
)) {
221 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image
->ImageContext
.Machine
)) {
223 // The PE/COFF loader can support loading image types that can be executed.
224 // If we loaded an image type that we can not execute return EFI_UNSUPORTED.
226 return EFI_UNSUPPORTED
;
231 // Allocate memory of the correct memory type aligned on the required image boundry
233 DstBufAlocated
= FALSE
;
234 if (DstBuffer
== 0) {
236 // Allocate Destination Buffer as caller did not pass it in
239 if (Image
->ImageContext
.SectionAlignment
> EFI_PAGE_SIZE
) {
240 Size
= (UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
;
242 Size
= (UINTN
)Image
->ImageContext
.ImageSize
;
245 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES (Size
);
248 // If the image relocations have not been stripped, then load at any address.
249 // Otherwise load at the address at which it was linked.
251 // Memory below 1MB should be treated reserved for CSM and there should be
252 // no modules whose preferred load addresses are below 1MB.
254 Status
= EFI_OUT_OF_RESOURCES
;
255 if (Image
->ImageContext
.ImageAddress
>= 0x100000 || Image
->ImageContext
.RelocationsStripped
) {
256 Status
= CoreAllocatePages (
258 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
259 Image
->NumberOfPages
,
260 &Image
->ImageContext
.ImageAddress
263 if (EFI_ERROR (Status
) && !Image
->ImageContext
.RelocationsStripped
) {
264 Status
= CoreAllocatePages (
266 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
267 Image
->NumberOfPages
,
268 &Image
->ImageContext
.ImageAddress
271 if (EFI_ERROR (Status
)) {
274 DstBufAlocated
= TRUE
;
277 // Caller provided the destination buffer
280 if (Image
->ImageContext
.RelocationsStripped
&& (Image
->ImageContext
.ImageAddress
!= DstBuffer
)) {
282 // If the image relocations were stripped, and the caller provided a
283 // destination buffer address that does not match the address that the
284 // image is linked at, then the image cannot be loaded.
286 return EFI_INVALID_PARAMETER
;
289 if (Image
->NumberOfPages
!= 0 &&
290 Image
->NumberOfPages
<
291 (EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
))) {
292 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
293 return EFI_BUFFER_TOO_SMALL
;
296 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
297 Image
->ImageContext
.ImageAddress
= DstBuffer
;
300 Image
->ImageBasePage
= Image
->ImageContext
.ImageAddress
;
301 Image
->ImageContext
.ImageAddress
=
302 (Image
->ImageContext
.ImageAddress
+ Image
->ImageContext
.SectionAlignment
- 1) &
303 ~((UINTN
)Image
->ImageContext
.SectionAlignment
- 1);
306 // Load the image from the file into the allocated memory
308 Status
= PeCoffLoaderLoadImage (&Image
->ImageContext
);
309 if (EFI_ERROR (Status
)) {
314 // If this is a Runtime Driver, then allocate memory for the FixupData that
315 // is used to relocate the image when SetVirtualAddressMap() is called. The
316 // relocation is done by the Runtime AP.
318 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) {
319 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
320 Image
->ImageContext
.FixupData
= CoreAllocateRuntimePool ((UINTN
)(Image
->ImageContext
.FixupDataSize
));
321 if (Image
->ImageContext
.FixupData
== NULL
) {
322 Status
= EFI_OUT_OF_RESOURCES
;
329 // Relocate the image in memory
331 Status
= PeCoffLoaderRelocateImage (&Image
->ImageContext
);
332 if (EFI_ERROR (Status
)) {
337 // Flush the Instruction Cache
339 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
, (UINTN
)Image
->ImageContext
.ImageSize
);
342 // Copy the machine type from the context to the image private data. This
343 // is needed during image unload to know if we should call an EBC protocol
344 // to unload the image.
346 Image
->Machine
= Image
->ImageContext
.Machine
;
349 // Get the image entry point. If it's an EBC image, then call into the
350 // interpreter to create a thunk for the entry point and use the returned
351 // value for the entry point.
353 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)Image
->ImageContext
.EntryPoint
;
354 if (Image
->ImageContext
.Machine
== EFI_IMAGE_MACHINE_EBC
) {
356 // Locate the EBC interpreter protocol
358 Status
= CoreLocateProtocol (&gEfiEbcProtocolGuid
, NULL
, (VOID
**)&Image
->Ebc
);
359 if (EFI_ERROR(Status
)) {
364 // Register a callback for flushing the instruction cache so that created
365 // thunks can be flushed.
367 Status
= Image
->Ebc
->RegisterICacheFlush (Image
->Ebc
, (EBC_ICACHE_FLUSH
)InvalidateInstructionCacheRange
);
368 if (EFI_ERROR(Status
)) {
373 // Create a thunk for the image's entry point. This will be the new
374 // entry point for the image.
376 Status
= Image
->Ebc
->CreateThunk (
379 (VOID
*)(UINTN
)Image
->ImageContext
.EntryPoint
,
380 (VOID
**)&Image
->EntryPoint
382 if (EFI_ERROR(Status
)) {
388 // Fill in the image information for the Loaded Image Protocol
390 Image
->Type
= Image
->ImageContext
.ImageType
;
391 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
;
392 Image
->Info
.ImageSize
= Image
->ImageContext
.ImageSize
;
393 Image
->Info
.ImageCodeType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
);
394 Image
->Info
.ImageDataType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageDataMemoryType
);
395 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) {
396 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
398 // Make a list off all the RT images so we can let the RT AP know about them.
400 Image
->RuntimeData
= CoreAllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY
));
401 if (Image
->RuntimeData
== NULL
) {
404 Image
->RuntimeData
->ImageBase
= Image
->Info
.ImageBase
;
405 Image
->RuntimeData
->ImageSize
= (UINT64
) (Image
->Info
.ImageSize
);
406 Image
->RuntimeData
->RelocationData
= Image
->ImageContext
.FixupData
;
407 Image
->RuntimeData
->Handle
= Image
->Handle
;
408 InsertTailList (&gRuntime
->ImageHead
, &Image
->RuntimeData
->Link
);
413 // Fill in the entry point of the image if it is available
415 if (EntryPoint
!= NULL
) {
416 *EntryPoint
= Image
->ImageContext
.EntryPoint
;
420 // Print the load address and the PDB file name if it is available
427 CHAR8 EfiFileName
[256];
429 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
));
430 if (Image
->ImageContext
.PdbPointer
!= NULL
) {
432 for (Index
= 0; Image
->ImageContext
.PdbPointer
[Index
] != 0; Index
++) {
433 if (Image
->ImageContext
.PdbPointer
[Index
] == '\\') {
434 StartIndex
= Index
+ 1;
438 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
440 for (Index
= 0; Index
< sizeof (EfiFileName
); Index
++) {
441 EfiFileName
[Index
] = Image
->ImageContext
.PdbPointer
[Index
+ StartIndex
];
442 if (EfiFileName
[Index
] == 0) {
443 EfiFileName
[Index
] = '.';
445 if (EfiFileName
[Index
] == '.') {
446 EfiFileName
[Index
+ 1] = 'e';
447 EfiFileName
[Index
+ 2] = 'f';
448 EfiFileName
[Index
+ 3] = 'i';
449 EfiFileName
[Index
+ 4] = 0;
453 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "%a", EfiFileName
)); // &Image->ImageContext.PdbPointer[StartIndex]));
455 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "\n"));
467 if (DstBufAlocated
) {
468 CoreFreePages (Image
->ImageContext
.ImageAddress
, Image
->NumberOfPages
);
471 if (Image
->ImageContext
.FixupData
!= NULL
) {
472 CoreFreePool (Image
->ImageContext
.FixupData
);
479 LOADED_IMAGE_PRIVATE_DATA
*
480 CoreLoadedImageInfo (
481 IN EFI_HANDLE ImageHandle
487 Get the image's private data from its handle.
491 ImageHandle - The image handle
495 Return the image private data associated with ImageHandle.
500 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
501 LOADED_IMAGE_PRIVATE_DATA
*Image
;
503 Status
= CoreHandleProtocol (
505 &gEfiLoadedImageProtocolGuid
,
506 (VOID
**)&LoadedImage
508 if (!EFI_ERROR (Status
)) {
509 Image
= LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage
);
511 DEBUG ((EFI_D_LOAD
, "CoreLoadedImageInfo: Not an ImageHandle %x\n", ImageHandle
));
520 CoreLoadImageCommon (
521 IN BOOLEAN BootPolicy
,
522 IN EFI_HANDLE ParentImageHandle
,
523 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
524 IN VOID
*SourceBuffer OPTIONAL
,
526 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
527 IN OUT UINTN
*NumberOfPages OPTIONAL
,
528 OUT EFI_HANDLE
*ImageHandle
,
529 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
536 Loads an EFI image into memory and returns a handle to the image.
540 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
541 and that the boot manager is attempting to load FilePath as a boot selection.
542 ParentImageHandle - The caller's image handle.
543 FilePath - The specific file path from which the image is loaded.
544 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
545 the image to be loaded.
546 SourceSize - The size in bytes of SourceBuffer.
547 DstBuffer - The buffer to store the image
548 NumberOfPages - If not NULL, a pointer to the image's page number, if this number
549 is not enough, return EFI_BUFFER_TOO_SMALL and this parameter contain
551 ImageHandle - Pointer to the returned image handle that is created when the image
552 is successfully loaded.
553 EntryPoint - A pointer to the entry point
554 Attribute - The bit mask of attributes to set for the load PE image
558 EFI_SUCCESS - The image was loaded into memory.
559 EFI_NOT_FOUND - The FilePath was not found.
560 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
561 EFI_BUFFER_TOO_SMALL - The buffer is too small
562 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
563 parsed to locate the proper protocol for loading the file.
564 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
567 LOADED_IMAGE_PRIVATE_DATA
*Image
;
568 LOADED_IMAGE_PRIVATE_DATA
*ParentImage
;
569 IMAGE_FILE_HANDLE FHand
;
571 EFI_STATUS SecurityStatus
;
572 EFI_HANDLE DeviceHandle
;
573 UINT32 AuthenticationStatus
;
574 EFI_DEVICE_PATH_PROTOCOL
*OriginalFilePath
;
575 EFI_DEVICE_PATH_PROTOCOL
*HandleFilePath
;
578 SecurityStatus
= EFI_SUCCESS
;
580 ASSERT (gEfiCurrentTpl
< TPL_NOTIFY
);
584 // The caller must pass in a valid ParentImageHandle
586 if (ImageHandle
== NULL
|| ParentImageHandle
== NULL
) {
587 return EFI_INVALID_PARAMETER
;
590 ParentImage
= CoreLoadedImageInfo (ParentImageHandle
);
591 if (ParentImage
== NULL
) {
592 DEBUG((EFI_D_LOAD
|EFI_D_ERROR
, "LoadImageEx: Parent handle not an image handle\n"));
593 return EFI_INVALID_PARAMETER
;
597 // Get simple read access to the source file
599 OriginalFilePath
= FilePath
;
600 Status
= CoreOpenImageFile (
607 &AuthenticationStatus
609 if (Status
== EFI_ALREADY_STARTED
) {
612 } else if (EFI_ERROR (Status
)) {
617 // Verify the Authentication Status through the Security Architectural Protocol
619 if ((gSecurity
!= NULL
) && (OriginalFilePath
!= NULL
)) {
620 SecurityStatus
= gSecurity
->FileAuthenticationState (
622 AuthenticationStatus
,
625 if (EFI_ERROR (SecurityStatus
) && SecurityStatus
!= EFI_SECURITY_VIOLATION
) {
626 Status
= SecurityStatus
;
634 // Allocate a new image structure
636 Image
= CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA
));
638 return EFI_OUT_OF_RESOURCES
;
642 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
644 Status
= CoreHandleProtocol (DeviceHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&HandleFilePath
);
645 if (!EFI_ERROR (Status
)) {
646 FilePathSize
= CoreDevicePathSize (HandleFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
647 FilePath
= (EFI_DEVICE_PATH_PROTOCOL
*) ( ((UINT8
*)FilePath
) + FilePathSize
);
648 Image
->DeviceHandleDevicePath
= CoreDuplicateDevicePath (HandleFilePath
);
652 // Initialize the fields for an internal driver
654 Image
->Signature
= LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
;
655 Image
->Info
.SystemTable
= gDxeCoreST
;
656 Image
->Info
.DeviceHandle
= DeviceHandle
;
657 Image
->Info
.Revision
= EFI_LOADED_IMAGE_INFORMATION_REVISION
;
658 Image
->Info
.FilePath
= CoreDuplicateDevicePath (FilePath
);
659 Image
->Info
.ParentHandle
= ParentImageHandle
;
662 if (NumberOfPages
!= NULL
) {
663 Image
->NumberOfPages
= *NumberOfPages
;
665 Image
->NumberOfPages
= 0 ;
669 // Install the protocol interfaces for this image
670 // don't fire notifications yet
672 Status
= CoreInstallProtocolInterfaceNotify (
674 &gEfiLoadedImageProtocolGuid
,
675 EFI_NATIVE_INTERFACE
,
679 if (EFI_ERROR (Status
)) {
684 // Load the image. If EntryPoint is Null, it will not be set.
686 Status
= CoreLoadPeImage (&FHand
, Image
, DstBuffer
, EntryPoint
, Attribute
);
687 if (EFI_ERROR (Status
)) {
688 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_OUT_OF_RESOURCES
)) {
689 if (NumberOfPages
!= NULL
) {
690 *NumberOfPages
= Image
->NumberOfPages
;
697 // Register the image in the Debug Image Info Table if the attribute is set
699 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
) {
700 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL
, &Image
->Info
, Image
->Handle
);
704 //Reinstall loaded image protocol to fire any notifications
706 Status
= CoreReinstallProtocolInterface (
708 &gEfiLoadedImageProtocolGuid
,
712 if (EFI_ERROR (Status
)) {
718 // Success. Return the image handle
720 *ImageHandle
= Image
->Handle
;
724 // All done accessing the source file
725 // If we allocated the Source buffer, free it
727 if (FHand
.FreeBuffer
) {
728 CoreFreePool (FHand
.Source
);
732 // There was an error. If there's an Image structure, free it
734 if (EFI_ERROR (Status
)) {
736 CoreUnloadAndCloseImage (Image
, (BOOLEAN
)(DstBuffer
== 0));
739 } else if (EFI_ERROR (SecurityStatus
)) {
740 Status
= SecurityStatus
;
751 IN BOOLEAN BootPolicy
,
752 IN EFI_HANDLE ParentImageHandle
,
753 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
754 IN VOID
*SourceBuffer OPTIONAL
,
756 OUT EFI_HANDLE
*ImageHandle
762 Loads an EFI image into memory and returns a handle to the image.
766 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
767 and that the boot manager is attempting to load FilePath as a boot selection.
768 ParentImageHandle - The caller's image handle.
769 FilePath - The specific file path from which the image is loaded.
770 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
771 the image to be loaded.
772 SourceSize - The size in bytes of SourceBuffer.
773 ImageHandle - Pointer to the returned image handle that is created when the image
774 is successfully loaded.
778 EFI_SUCCESS - The image was loaded into memory.
779 EFI_NOT_FOUND - The FilePath was not found.
780 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
781 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
782 parsed to locate the proper protocol for loading the file.
783 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
788 PERF_START (NULL
, "LoadImage", NULL
, 0);
790 Status
= CoreLoadImageCommon (
796 (EFI_PHYSICAL_ADDRESS
)NULL
,
800 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
| EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
803 PERF_END (NULL
, "LoadImage", NULL
, 0);
812 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
813 IN EFI_HANDLE ParentImageHandle
,
814 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
815 IN VOID
*SourceBuffer OPTIONAL
,
817 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
818 OUT UINTN
*NumberOfPages OPTIONAL
,
819 OUT EFI_HANDLE
*ImageHandle
,
820 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
827 Loads an EFI image into memory and returns a handle to the image with extended parameters.
831 This - Calling context
832 ParentImageHandle - The caller's image handle.
833 FilePath - The specific file path from which the image is loaded.
834 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
835 the image to be loaded.
836 SourceSize - The size in bytes of SourceBuffer.
837 DstBuffer - The buffer to store the image.
838 NumberOfPages - For input, specifies the space size of the image by caller if not NULL.
839 For output, specifies the actual space size needed.
840 ImageHandle - Image handle for output.
841 EntryPoint - Image entry point for output.
842 Attribute - The bit mask of attributes to set for the load PE image.
846 EFI_SUCCESS - The image was loaded into memory.
847 EFI_NOT_FOUND - The FilePath was not found.
848 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
849 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
850 parsed to locate the proper protocol for loading the file.
851 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
854 return CoreLoadImageCommon (
874 IN EFI_HANDLE ImageHandle
,
875 OUT UINTN
*ExitDataSize
,
876 OUT CHAR16
**ExitData OPTIONAL
882 Transfer control to a loaded image's entry point.
886 ImageHandle - Handle of image to be started.
888 ExitDataSize - Pointer of the size to ExitData
890 ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated
891 Unicode string, optionally followed by additional binary data. The string
892 is a description that the caller may use to further indicate the reason for
897 EFI_INVALID_PARAMETER - Invalid parameter
899 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
901 EFI_SUCCESS - Successfully transfer control to the image's entry point.
906 LOADED_IMAGE_PRIVATE_DATA
*Image
;
907 LOADED_IMAGE_PRIVATE_DATA
*LastImage
;
908 UINT64 HandleDatabaseKey
;
911 Image
= CoreLoadedImageInfo (ImageHandle
);
912 if (Image
== NULL_HANDLE
|| Image
->Started
) {
913 return EFI_INVALID_PARAMETER
;
917 // Don't profile Objects or invalid start requests
919 PERF_START (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
923 // Push the current start image context, and
924 // link the current image to the head. This is the
925 // only image that can call Exit()
927 HandleDatabaseKey
= CoreGetHandleDatabaseKey ();
928 LastImage
= mCurrentImage
;
929 mCurrentImage
= Image
;
930 Image
->Tpl
= gEfiCurrentTpl
;
933 // Set long jump for Exit() support
934 // JumpContext must be aligned on a CPU specific boundary.
935 // Overallocate the buffer and force the required alignment
937 Image
->JumpBuffer
= CoreAllocateBootServicesPool (sizeof (BASE_LIBRARY_JUMP_BUFFER
) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
938 if (Image
->JumpBuffer
== NULL
) {
939 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
940 return EFI_OUT_OF_RESOURCES
;
942 Image
->JumpContext
= ALIGN_POINTER (Image
->JumpBuffer
, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
944 SetJumpFlag
= SetJump (Image
->JumpContext
);
946 // The initial call to SetJump() must always return 0.
947 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
951 // Call the image's entry point
953 Image
->Started
= TRUE
;
954 Image
->Status
= Image
->EntryPoint (ImageHandle
, Image
->Info
.SystemTable
);
957 // Add some debug information if the image returned with error.
958 // This make the user aware and check if the driver image have already released
959 // all the resource in this situation.
962 if (EFI_ERROR (Image
->Status
)) {
963 DEBUG ((EFI_D_ERROR
, "Error: Image at %10p start failed: %r\n", Image
->Info
.ImageBase
, Image
->Status
));
968 // If the image returns, exit it through Exit()
970 CoreExit (ImageHandle
, Image
->Status
, 0, NULL
);
974 // Image has completed. Verify the tpl is the same
976 ASSERT (Image
->Tpl
== gEfiCurrentTpl
);
977 CoreRestoreTpl (Image
->Tpl
);
979 CoreFreePool (Image
->JumpBuffer
);
982 // Pop the current start image context
984 mCurrentImage
= LastImage
;
987 // Go connect any handles that were created or modified while the image executed.
989 CoreConnectHandlesByKey (HandleDatabaseKey
);
992 // Handle the image's returned ExitData
995 if (Image
->ExitDataSize
!= 0 || Image
->ExitData
!= NULL
) {
999 "StartImage: ExitDataSize %d, ExitData %x",
1000 Image
->ExitDataSize
,
1003 if (Image
->ExitData
!= NULL
) {
1004 DEBUG ((EFI_D_LOAD
, " (%hs)", Image
->ExitData
));
1006 DEBUG ((EFI_D_LOAD
, "\n"));
1011 // Return the exit data to the caller
1013 if (ExitData
!= NULL
&& ExitDataSize
!= NULL
) {
1014 *ExitDataSize
= Image
->ExitDataSize
;
1015 *ExitData
= Image
->ExitData
;
1018 // Caller doesn't want the exit data, free it
1020 CoreFreePool (Image
->ExitData
);
1021 Image
->ExitData
= NULL
;
1025 // Save the Status because Image will get destroyed if it is unloaded.
1027 Status
= Image
->Status
;
1030 // If the image returned an error, or if the image is an application
1033 if (EFI_ERROR (Image
->Status
) || Image
->Type
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1034 CoreUnloadAndCloseImage (Image
, TRUE
);
1040 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
1046 CoreUnloadAndCloseImage (
1047 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
1052 Routine Description:
1054 Unloads EFI image from memory.
1059 FreePage - Free allocated pages
1069 EFI_HANDLE
*HandleBuffer
;
1071 EFI_GUID
**ProtocolGuidArray
;
1073 UINTN ProtocolIndex
;
1074 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfo
;
1075 UINTN OpenInfoCount
;
1076 UINTN OpenInfoIndex
;
1078 if (Image
->Ebc
!= NULL
) {
1080 // If EBC protocol exists we must perform cleanups for this image.
1082 Image
->Ebc
->UnloadImage (Image
->Ebc
, Image
->Handle
);
1086 // Unload image, free Image->ImageContext->ModHandle
1088 PeCoffLoaderUnloadImage (&Image
->ImageContext
);
1091 // Free our references to the image handle
1093 if (Image
->Handle
!= NULL_HANDLE
) {
1095 Status
= CoreLocateHandleBuffer (
1102 if (!EFI_ERROR (Status
)) {
1103 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
1104 Status
= CoreProtocolsPerHandle (
1105 HandleBuffer
[HandleIndex
],
1109 if (!EFI_ERROR (Status
)) {
1110 for (ProtocolIndex
= 0; ProtocolIndex
< ArrayCount
; ProtocolIndex
++) {
1111 Status
= CoreOpenProtocolInformation (
1112 HandleBuffer
[HandleIndex
],
1113 ProtocolGuidArray
[ProtocolIndex
],
1117 if (!EFI_ERROR (Status
)) {
1118 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
1119 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== Image
->Handle
) {
1120 Status
= CoreCloseProtocol (
1121 HandleBuffer
[HandleIndex
],
1122 ProtocolGuidArray
[ProtocolIndex
],
1124 OpenInfo
[OpenInfoIndex
].ControllerHandle
1128 if (OpenInfo
!= NULL
) {
1129 CoreFreePool(OpenInfo
);
1133 if (ProtocolGuidArray
!= NULL
) {
1134 CoreFreePool(ProtocolGuidArray
);
1138 if (HandleBuffer
!= NULL
) {
1139 CoreFreePool (HandleBuffer
);
1143 CoreRemoveDebugImageInfoEntry (Image
->Handle
);
1145 Status
= CoreUninstallProtocolInterface (
1147 &gEfiLoadedImageProtocolGuid
,
1152 if (Image
->RuntimeData
!= NULL
) {
1153 if (Image
->RuntimeData
->Link
.ForwardLink
!= NULL
) {
1155 // Remove the Image from the Runtime Image list as we are about to Free it!
1157 RemoveEntryList (&Image
->RuntimeData
->Link
);
1159 CoreFreePool (Image
->RuntimeData
);
1163 // Free the Image from memory
1165 if ((Image
->ImageBasePage
!= 0) && FreePage
) {
1166 CoreFreePages (Image
->ImageBasePage
, Image
->NumberOfPages
);
1170 // Done with the Image structure
1172 if (Image
->Info
.FilePath
!= NULL
) {
1173 CoreFreePool (Image
->Info
.FilePath
);
1176 if (Image
->DeviceHandleDevicePath
!= NULL
) {
1177 CoreFreePool (Image
->DeviceHandleDevicePath
);
1180 if (Image
->FixupData
!= NULL
) {
1181 CoreFreePool (Image
->FixupData
);
1184 CoreFreePool (Image
);
1192 IN EFI_HANDLE ImageHandle
,
1193 IN EFI_STATUS Status
,
1194 IN UINTN ExitDataSize
,
1195 IN CHAR16
*ExitData OPTIONAL
1199 Routine Description:
1201 Terminates the currently loaded EFI image and returns control to boot services.
1205 ImageHandle - Handle that identifies the image. This parameter is passed to the image
1207 Status - The image's exit code.
1208 ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is
1210 ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string,
1211 optionally followed by additional binary data. The string is a
1212 description that the caller may use to further indicate the reason for
1217 EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image.
1219 EFI_SUCCESS - Successfully terminates the currently loaded EFI image.
1221 EFI_ACCESS_DENIED - Should never reach there.
1223 EFI_OUT_OF_RESOURCES - Could not allocate pool
1227 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1231 // Prevent possible reentrance to this function
1232 // for the same ImageHandle
1234 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1236 Image
= CoreLoadedImageInfo (ImageHandle
);
1237 if (Image
== NULL_HANDLE
) {
1238 Status
= EFI_INVALID_PARAMETER
;
1242 if (!Image
->Started
) {
1244 // The image has not been started so just free its resources
1246 CoreUnloadAndCloseImage (Image
, TRUE
);
1247 Status
= EFI_SUCCESS
;
1252 // Image has been started, verify this image can exit
1254 if (Image
!= mCurrentImage
) {
1255 DEBUG ((EFI_D_LOAD
|EFI_D_ERROR
, "Exit: Image is not exitable image\n"));
1256 Status
= EFI_INVALID_PARAMETER
;
1263 Image
->Status
= Status
;
1266 // If there's ExitData info, move it
1268 if (ExitData
!= NULL
) {
1269 Image
->ExitDataSize
= ExitDataSize
;
1270 Image
->ExitData
= CoreAllocateBootServicesPool (Image
->ExitDataSize
);
1271 if (Image
->ExitData
== NULL
) {
1272 Status
= EFI_OUT_OF_RESOURCES
;
1275 CopyMem (Image
->ExitData
, ExitData
, Image
->ExitDataSize
);
1278 CoreRestoreTpl (OldTpl
);
1280 // return to StartImage
1282 LongJump (Image
->JumpContext
, (UINTN
)-1);
1285 // If we return from LongJump, then it is an error
1288 Status
= EFI_ACCESS_DENIED
;
1290 CoreRestoreTpl (OldTpl
);
1299 IN EFI_HANDLE ImageHandle
1303 Routine Description:
1309 ImageHandle - Handle that identifies the image to be unloaded.
1313 EFI_SUCCESS - The image has been unloaded.
1314 EFI_UNSUPPORTED - The image has been sarted, and does not support unload.
1315 EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle.
1320 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1324 // Prevent possible reentrance to this function
1325 // for the same ImageHandle
1327 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1329 Image
= CoreLoadedImageInfo (ImageHandle
);
1330 if (Image
== NULL
) {
1332 // The image handle is not valid
1334 Status
= EFI_INVALID_PARAMETER
;
1338 if (Image
->Started
) {
1340 // The image has been started, request it to unload.
1342 Status
= EFI_UNSUPPORTED
;
1343 if (Image
->Info
.Unload
!= NULL
) {
1344 Status
= Image
->Info
.Unload (ImageHandle
);
1349 // This Image hasn't been started, thus it can be unloaded
1351 Status
= EFI_SUCCESS
;
1355 if (!EFI_ERROR (Status
)) {
1357 // if the Image was not started or Unloaded O.K. then clean up
1359 CoreUnloadAndCloseImage (Image
, TRUE
);
1363 CoreRestoreTpl (OldTpl
);
1371 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
1372 IN EFI_HANDLE ImageHandle
1376 Routine Description:
1378 Unload the specified image.
1382 This - Indicates the calling context.
1384 ImageHandle - The specified image handle.
1388 EFI_INVALID_PARAMETER - Image handle is NULL.
1390 EFI_UNSUPPORTED - Attempt to unload an unsupported image.
1392 EFI_SUCCESS - Image successfully unloaded.
1396 return CoreUnloadImage (ImageHandle
);