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 EFI_LOCK mBsExitLock
= EFI_INITIALIZE_LOCK_VARIABLE(EFI_TPL_NOTIFY
);
28 EFI_LOCK mBsUnloadImageLock
= EFI_INITIALIZE_LOCK_VARIABLE(EFI_TPL_NOTIFY
);
30 LOADED_IMAGE_PRIVATE_DATA
*mCurrentImage
= NULL
;
32 LOAD_PE32_IMAGE_PRIVATE_DATA mLoadPe32PrivateData
= {
33 LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE
,
43 // This code is needed to build the Image handle for the DXE Core
45 LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage
= {
46 LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
, // Signature
48 EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
, // Image type
49 TRUE
, // If entrypoint has been called
52 EFI_LOADED_IMAGE_INFORMATION_REVISION
, // Revision
53 NULL
, // Parent handle
54 NULL
, // System handle
56 NULL
, // Device handle
65 EfiBootServicesCode
, // ImageCodeType
66 EfiBootServicesData
// ImageDataType
68 (EFI_PHYSICAL_ADDRESS
)0, // ImageBasePage
72 EFI_SUCCESS
, // Status
84 CoreInitializeImageServices (
91 Add the Image Services to EFI Boot Services Table and install the protocol
92 interfaces for this image.
96 HobStart - The HOB to initialize
105 LOADED_IMAGE_PRIVATE_DATA
*Image
;
106 EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress
;
107 UINT64 DxeCoreImageLength
;
108 VOID
*DxeCoreEntryPoint
;
109 EFI_PEI_HOB_POINTERS DxeCoreHob
;
111 // Searching for image hob
113 DxeCoreHob
.Raw
= HobStart
;
114 while ((DxeCoreHob
.Raw
= GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, DxeCoreHob
.Raw
)) != NULL
) {
115 if (CompareGuid (&DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.Name
, &gEfiHobMemoryAllocModuleGuid
)) {
121 DxeCoreHob
.Raw
= GET_NEXT_HOB (DxeCoreHob
);
123 ASSERT (DxeCoreHob
.Raw
!= NULL
);
125 DxeCoreImageBaseAddress
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryBaseAddress
;
126 DxeCoreImageLength
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryLength
;
127 DxeCoreEntryPoint
= (VOID
*) (UINTN
) DxeCoreHob
.MemoryAllocationModule
->EntryPoint
;
128 gDxeCoreFileName
= &DxeCoreHob
.MemoryAllocationModule
->ModuleName
;
130 // Initialize the fields for an internal driver
132 Image
= &mCorePrivateImage
;
134 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)DxeCoreEntryPoint
;
135 Image
->ImageBasePage
= DxeCoreImageBaseAddress
;
136 Image
->NumberOfPages
= (UINTN
)(EFI_SIZE_TO_PAGES((UINTN
)(DxeCoreImageLength
)));
137 Image
->Tpl
= gEfiCurrentTpl
;
138 Image
->Info
.SystemTable
= gST
;
139 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)DxeCoreImageBaseAddress
;
140 Image
->Info
.ImageSize
= DxeCoreImageLength
;
143 // Install the protocol interfaces for this image
145 Status
= CoreInstallProtocolInterface (
147 &gEfiLoadedImageProtocolGuid
,
148 EFI_NATIVE_INTERFACE
,
151 ASSERT_EFI_ERROR (Status
);
153 mCurrentImage
= Image
;
156 // Fill in DXE globals
158 gDxeCoreImageHandle
= Image
->Handle
;
159 gDxeCoreLoadedImage
= &Image
->Info
;
162 // Export DXE Core PE Loader functionality
164 return CoreInstallProtocolInterface (
165 &mLoadPe32PrivateData
.Handle
,
166 &gEfiLoadPeImageProtocolGuid
,
167 EFI_NATIVE_INTERFACE
,
168 &mLoadPe32PrivateData
.Pe32Image
175 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
176 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
177 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
184 Loads, relocates, and invokes a PE/COFF image
188 Pe32Handle - The handle of PE32 image
189 Image - PE image to be loaded
190 DstBuffer - The buffer to store the image
191 EntryPoint - A pointer to the entry point
192 Attribute - The bit mask of attributes to set for the load PE image
196 EFI_SUCCESS - The file was loaded, relocated, and invoked
198 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
200 EFI_INVALID_PARAMETER - Invalid parameter
202 EFI_BUFFER_TOO_SMALL - Buffer for image is too small
207 BOOLEAN DstBufAlocated
;
210 ZeroMem (&Image
->ImageContext
, sizeof (Image
->ImageContext
));
212 Image
->ImageContext
.Handle
= Pe32Handle
;
213 Image
->ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)CoreReadImageFile
;
216 // Get information about the image being loaded
218 Status
= gEfiPeiPeCoffLoader
->GetImageInfo (gEfiPeiPeCoffLoader
, &Image
->ImageContext
);
219 if (EFI_ERROR (Status
)) {
223 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image
->ImageContext
.Machine
)) {
225 // The PE/COFF loader can support loading image types that can be executed.
226 // If we loaded an image type that we can not execute return EFI_UNSUPORTED.
228 return EFI_UNSUPPORTED
;
233 // Allocate memory of the correct memory type aligned on the required image boundry
235 DstBufAlocated
= FALSE
;
236 if (DstBuffer
== 0) {
238 // Allocate Destination Buffer as caller did not pass it in
241 if (Image
->ImageContext
.SectionAlignment
> EFI_PAGE_SIZE
) {
242 Size
= (UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
;
244 Size
= (UINTN
)Image
->ImageContext
.ImageSize
;
247 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES (Size
);
250 // If the image relocations have not been stripped, then load at any address.
251 // Otherwise load at the address at which it was linked.
253 // Memory below 1MB should be treated reserved for CSM and there should be
254 // no modules whose preferred load addresses are below 1MB.
256 Status
= EFI_OUT_OF_RESOURCES
;
257 if (Image
->ImageContext
.ImageAddress
>= 0x100000 || Image
->ImageContext
.RelocationsStripped
) {
258 Status
= CoreAllocatePages (
260 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
261 Image
->NumberOfPages
,
262 &Image
->ImageContext
.ImageAddress
265 if (EFI_ERROR (Status
) && !Image
->ImageContext
.RelocationsStripped
) {
266 Status
= CoreAllocatePages (
268 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
269 Image
->NumberOfPages
,
270 &Image
->ImageContext
.ImageAddress
273 if (EFI_ERROR (Status
)) {
276 DstBufAlocated
= TRUE
;
279 // Caller provided the destination buffer
282 if (Image
->ImageContext
.RelocationsStripped
&& (Image
->ImageContext
.ImageAddress
!= DstBuffer
)) {
284 // If the image relocations were stripped, and the caller provided a
285 // destination buffer address that does not match the address that the
286 // image is linked at, then the image cannot be loaded.
288 return EFI_INVALID_PARAMETER
;
291 if (Image
->NumberOfPages
!= 0 &&
292 Image
->NumberOfPages
<
293 (EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
))) {
294 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
295 return EFI_BUFFER_TOO_SMALL
;
298 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
299 Image
->ImageContext
.ImageAddress
= DstBuffer
;
302 Image
->ImageBasePage
= Image
->ImageContext
.ImageAddress
;
303 Image
->ImageContext
.ImageAddress
=
304 (Image
->ImageContext
.ImageAddress
+ Image
->ImageContext
.SectionAlignment
- 1) &
305 ~((UINTN
)Image
->ImageContext
.SectionAlignment
- 1);
308 // Load the image from the file into the allocated memory
310 Status
= gEfiPeiPeCoffLoader
->LoadImage (gEfiPeiPeCoffLoader
, &Image
->ImageContext
);
311 if (EFI_ERROR (Status
)) {
316 // If this is a Runtime Driver, then allocate memory for the FixupData that
317 // is used to relocate the image when SetVirtualAddressMap() is called. The
318 // relocation is done by the Runtime AP.
320 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) {
321 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
322 Image
->ImageContext
.FixupData
= CoreAllocateRuntimePool ((UINTN
)(Image
->ImageContext
.FixupDataSize
));
323 if (Image
->ImageContext
.FixupData
== NULL
) {
324 Status
= EFI_OUT_OF_RESOURCES
;
331 // Relocate the image in memory
333 Status
= gEfiPeiPeCoffLoader
->RelocateImage (gEfiPeiPeCoffLoader
, &Image
->ImageContext
);
334 if (EFI_ERROR (Status
)) {
339 // Flush the Instruction Cache
341 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
, (UINTN
)Image
->ImageContext
.ImageSize
);
344 // Copy the machine type from the context to the image private data. This
345 // is needed during image unload to know if we should call an EBC protocol
346 // to unload the image.
348 Image
->Machine
= Image
->ImageContext
.Machine
;
351 // Get the image entry point. If it's an EBC image, then call into the
352 // interpreter to create a thunk for the entry point and use the returned
353 // value for the entry point.
355 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)Image
->ImageContext
.EntryPoint
;
356 if (Image
->ImageContext
.Machine
== EFI_IMAGE_MACHINE_EBC
) {
358 // Locate the EBC interpreter protocol
360 Status
= CoreLocateProtocol (&gEfiEbcProtocolGuid
, NULL
, (VOID
**)&Image
->Ebc
);
361 if (EFI_ERROR(Status
)) {
366 // Register a callback for flushing the instruction cache so that created
367 // thunks can be flushed.
369 Status
= Image
->Ebc
->RegisterICacheFlush (Image
->Ebc
, (EBC_ICACHE_FLUSH
)InvalidateInstructionCacheRange
);
370 if (EFI_ERROR(Status
)) {
375 // Create a thunk for the image's entry point. This will be the new
376 // entry point for the image.
378 Status
= Image
->Ebc
->CreateThunk (
381 (VOID
*)(UINTN
)Image
->ImageContext
.EntryPoint
,
382 (VOID
**)&Image
->EntryPoint
384 if (EFI_ERROR(Status
)) {
390 // Fill in the image information for the Loaded Image Protocol
392 Image
->Type
= Image
->ImageContext
.ImageType
;
393 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
;
394 Image
->Info
.ImageSize
= Image
->ImageContext
.ImageSize
;
395 Image
->Info
.ImageCodeType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
);
396 Image
->Info
.ImageDataType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageDataMemoryType
);
397 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) {
398 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
400 // Make a list off all the RT images so we can let the RT AP know about them.
402 Image
->RuntimeData
= CoreAllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY
));
403 if (Image
->RuntimeData
== NULL
) {
406 Image
->RuntimeData
->ImageBase
= Image
->Info
.ImageBase
;
407 Image
->RuntimeData
->ImageSize
= (UINT64
) (Image
->Info
.ImageSize
);
408 Image
->RuntimeData
->RelocationData
= Image
->ImageContext
.FixupData
;
409 Image
->RuntimeData
->Handle
= Image
->Handle
;
410 InsertTailList (&gRuntime
->ImageHead
, &Image
->RuntimeData
->Link
);
415 // Fill in the entry point of the image if it is available
417 if (EntryPoint
!= NULL
) {
418 *EntryPoint
= Image
->ImageContext
.EntryPoint
;
422 // Print the load address and the PDB file name if it is available
429 CHAR8 EfiFileName
[256];
431 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
));
432 if (Image
->ImageContext
.PdbPointer
!= NULL
) {
434 for (Index
= 0; Image
->ImageContext
.PdbPointer
[Index
] != 0; Index
++) {
435 if (Image
->ImageContext
.PdbPointer
[Index
] == '\\') {
436 StartIndex
= Index
+ 1;
440 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
442 for (Index
= 0; Index
< sizeof (EfiFileName
); Index
++) {
443 EfiFileName
[Index
] = Image
->ImageContext
.PdbPointer
[Index
+ StartIndex
];
444 if (EfiFileName
[Index
] == 0) {
445 EfiFileName
[Index
] = '.';
447 if (EfiFileName
[Index
] == '.') {
448 EfiFileName
[Index
+ 1] = 'e';
449 EfiFileName
[Index
+ 2] = 'f';
450 EfiFileName
[Index
+ 3] = 'i';
451 EfiFileName
[Index
+ 4] = 0;
455 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "%a", EfiFileName
)); // &Image->ImageContext.PdbPointer[StartIndex]));
457 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "\n"));
469 if (DstBufAlocated
) {
470 CoreFreePages (Image
->ImageContext
.ImageAddress
, Image
->NumberOfPages
);
473 if (Image
->ImageContext
.FixupData
!= NULL
) {
474 CoreFreePool (Image
->ImageContext
.FixupData
);
481 LOADED_IMAGE_PRIVATE_DATA
*
482 CoreLoadedImageInfo (
483 IN EFI_HANDLE ImageHandle
489 Get the image's private data from its handle.
493 ImageHandle - The image handle
497 Return the image private data associated with ImageHandle.
502 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
503 LOADED_IMAGE_PRIVATE_DATA
*Image
;
505 Status
= CoreHandleProtocol (
507 &gEfiLoadedImageProtocolGuid
,
508 (VOID
**)&LoadedImage
510 if (!EFI_ERROR (Status
)) {
511 Image
= LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage
);
513 DEBUG ((EFI_D_LOAD
, "CoreLoadedImageInfo: Not an ImageHandle %x\n", ImageHandle
));
522 CoreLoadImageCommon (
523 IN BOOLEAN BootPolicy
,
524 IN EFI_HANDLE ParentImageHandle
,
525 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
526 IN VOID
*SourceBuffer OPTIONAL
,
528 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
529 IN OUT UINTN
*NumberOfPages OPTIONAL
,
530 OUT EFI_HANDLE
*ImageHandle
,
531 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
538 Loads an EFI image into memory and returns a handle to the image.
542 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
543 and that the boot manager is attempting to load FilePath as a boot selection.
544 ParentImageHandle - The caller's image handle.
545 FilePath - The specific file path from which the image is loaded.
546 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
547 the image to be loaded.
548 SourceSize - The size in bytes of SourceBuffer.
549 DstBuffer - The buffer to store the image
550 NumberOfPages - If not NULL, a pointer to the image's page number, if this number
551 is not enough, return EFI_BUFFER_TOO_SMALL and this parameter contain
553 ImageHandle - Pointer to the returned image handle that is created when the image
554 is successfully loaded.
555 EntryPoint - A pointer to the entry point
556 Attribute - The bit mask of attributes to set for the load PE image
560 EFI_SUCCESS - The image was loaded into memory.
561 EFI_NOT_FOUND - The FilePath was not found.
562 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
563 EFI_BUFFER_TOO_SMALL - The buffer is too small
564 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
565 parsed to locate the proper protocol for loading the file.
566 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
569 LOADED_IMAGE_PRIVATE_DATA
*Image
;
570 LOADED_IMAGE_PRIVATE_DATA
*ParentImage
;
571 IMAGE_FILE_HANDLE FHand
;
573 EFI_STATUS SecurityStatus
;
574 EFI_HANDLE DeviceHandle
;
575 UINT32 AuthenticationStatus
;
576 EFI_DEVICE_PATH_PROTOCOL
*OriginalFilePath
;
577 EFI_DEVICE_PATH_PROTOCOL
*HandleFilePath
;
580 SecurityStatus
= EFI_SUCCESS
;
582 ASSERT (gEfiCurrentTpl
< EFI_TPL_NOTIFY
);
586 // The caller must pass in a valid ParentImageHandle
588 if (ImageHandle
== NULL
|| ParentImageHandle
== NULL
) {
589 return EFI_INVALID_PARAMETER
;
592 ParentImage
= CoreLoadedImageInfo (ParentImageHandle
);
593 if (ParentImage
== NULL
) {
594 DEBUG((EFI_D_LOAD
|EFI_D_ERROR
, "LoadImageEx: Parent handle not an image handle\n"));
595 return EFI_INVALID_PARAMETER
;
599 // Get simple read access to the source file
601 OriginalFilePath
= FilePath
;
602 Status
= CoreOpenImageFile (
609 &AuthenticationStatus
611 if (Status
== EFI_ALREADY_STARTED
) {
614 } else if (EFI_ERROR (Status
)) {
619 // Verify the Authentication Status through the Security Architectural Protocol
621 if ((gSecurity
!= NULL
) && (OriginalFilePath
!= NULL
)) {
622 SecurityStatus
= gSecurity
->FileAuthenticationState (
624 AuthenticationStatus
,
627 if (EFI_ERROR (SecurityStatus
) && SecurityStatus
!= EFI_SECURITY_VIOLATION
) {
628 Status
= SecurityStatus
;
636 // Allocate a new image structure
638 Image
= CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA
));
640 return EFI_OUT_OF_RESOURCES
;
644 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
646 Status
= CoreHandleProtocol (DeviceHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&HandleFilePath
);
647 if (!EFI_ERROR (Status
)) {
648 FilePathSize
= CoreDevicePathSize (HandleFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
649 FilePath
= (EFI_DEVICE_PATH_PROTOCOL
*) ( ((UINT8
*)FilePath
) + FilePathSize
);
653 // Initialize the fields for an internal driver
655 Image
->Signature
= LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
;
656 Image
->Info
.SystemTable
= gST
;
657 Image
->Info
.DeviceHandle
= DeviceHandle
;
658 Image
->Info
.Revision
= EFI_LOADED_IMAGE_INFORMATION_REVISION
;
659 Image
->Info
.FilePath
= CoreDuplicateDevicePath (FilePath
);
660 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 gEfiPeiPeCoffLoader
->UnloadImage (gEfiPeiPeCoffLoader
, &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
->FixupData
!= NULL
) {
1177 CoreFreePool (Image
->FixupData
);
1180 CoreFreePool (Image
);
1188 IN EFI_HANDLE ImageHandle
,
1189 IN EFI_STATUS Status
,
1190 IN UINTN ExitDataSize
,
1191 IN CHAR16
*ExitData OPTIONAL
1195 Routine Description:
1197 Terminates the currently loaded EFI image and returns control to boot services.
1201 ImageHandle - Handle that identifies the image. This parameter is passed to the image
1203 Status - The image's exit code.
1204 ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is
1206 ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string,
1207 optionally followed by additional binary data. The string is a
1208 description that the caller may use to further indicate the reason for
1213 EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image.
1215 EFI_SUCCESS - Successfully terminates the currently loaded EFI image.
1217 EFI_ACCESS_DENIED - Should never reach there.
1219 EFI_OUT_OF_RESOURCES - Could not allocate pool
1223 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1225 EfiAcquireLock (&mBsExitLock
);
1227 Image
= CoreLoadedImageInfo (ImageHandle
);
1228 if (Image
== NULL_HANDLE
) {
1229 Status
= EFI_INVALID_PARAMETER
;
1233 if (!Image
->Started
) {
1235 // The image has not been started so just free its resources
1237 CoreUnloadAndCloseImage (Image
, TRUE
);
1238 Status
= EFI_SUCCESS
;
1243 // Image has been started, verify this image can exit
1245 if (Image
!= mCurrentImage
) {
1246 DEBUG ((EFI_D_LOAD
|EFI_D_ERROR
, "Exit: Image is not exitable image\n"));
1247 Status
= EFI_INVALID_PARAMETER
;
1254 Image
->Status
= Status
;
1257 // If there's ExitData info, move it
1259 if (ExitData
!= NULL
) {
1260 Image
->ExitDataSize
= ExitDataSize
;
1261 Image
->ExitData
= CoreAllocateBootServicesPool (Image
->ExitDataSize
);
1262 if (Image
->ExitData
== NULL
) {
1263 Status
= EFI_OUT_OF_RESOURCES
;
1266 CopyMem (Image
->ExitData
, ExitData
, Image
->ExitDataSize
);
1269 EfiReleaseLock (&mBsExitLock
);
1271 // return to StartImage
1273 LongJump (Image
->JumpContext
, (UINTN
)-1);
1276 // If we return from LongJump, then it is an error
1279 Status
= EFI_ACCESS_DENIED
;
1281 EfiReleaseLock (&mBsExitLock
);
1290 IN EFI_HANDLE ImageHandle
1294 Routine Description:
1300 ImageHandle - Handle that identifies the image to be unloaded.
1304 EFI_SUCCESS - The image has been unloaded.
1305 EFI_UNSUPPORTED - The image has been sarted, and does not support unload.
1306 EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle.
1311 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1313 EfiAcquireLock (&mBsUnloadImageLock
);
1315 Image
= CoreLoadedImageInfo (ImageHandle
);
1316 if (Image
== NULL
) {
1318 // The image handle is not valid
1320 Status
= EFI_INVALID_PARAMETER
;
1324 if (Image
->Started
) {
1326 // The image has been started, request it to unload.
1328 Status
= EFI_UNSUPPORTED
;
1329 if (Image
->Info
.Unload
!= NULL
) {
1330 Status
= Image
->Info
.Unload (ImageHandle
);
1335 // This Image hasn't been started, thus it can be unloaded
1337 Status
= EFI_SUCCESS
;
1341 if (!EFI_ERROR (Status
)) {
1343 // if the Image was not started or Unloaded O.K. then clean up
1345 CoreUnloadAndCloseImage (Image
, TRUE
);
1349 EfiReleaseLock (&mBsUnloadImageLock
);
1357 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
1358 IN EFI_HANDLE ImageHandle
1362 Routine Description:
1364 Unload the specified image.
1368 This - Indicates the calling context.
1370 ImageHandle - The specified image handle.
1374 EFI_INVALID_PARAMETER - Image handle is NULL.
1376 EFI_UNSUPPORTED - Attempt to unload an unsupported image.
1378 EFI_SUCCESS - Image successfully unloaded.
1382 return CoreUnloadImage (ImageHandle
);