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
;
230 // Set EFI memory type based on ImageType
232 switch (Image
->ImageContext
.ImageType
) {
233 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
:
234 Image
->ImageContext
.ImageCodeMemoryType
= EfiLoaderCode
;
235 Image
->ImageContext
.ImageDataMemoryType
= EfiLoaderData
;
237 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
:
238 Image
->ImageContext
.ImageCodeMemoryType
= EfiBootServicesCode
;
239 Image
->ImageContext
.ImageDataMemoryType
= EfiBootServicesData
;
241 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
:
242 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
:
243 Image
->ImageContext
.ImageCodeMemoryType
= EfiRuntimeServicesCode
;
244 Image
->ImageContext
.ImageDataMemoryType
= EfiRuntimeServicesData
;
247 Image
->ImageContext
.ImageError
= IMAGE_ERROR_INVALID_SUBSYSTEM
;
248 return EFI_UNSUPPORTED
;
252 // Allocate memory of the correct memory type aligned on the required image boundry
254 DstBufAlocated
= FALSE
;
255 if (DstBuffer
== 0) {
257 // Allocate Destination Buffer as caller did not pass it in
260 if (Image
->ImageContext
.SectionAlignment
> EFI_PAGE_SIZE
) {
261 Size
= (UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
;
263 Size
= (UINTN
)Image
->ImageContext
.ImageSize
;
266 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES (Size
);
269 // If the image relocations have not been stripped, then load at any address.
270 // Otherwise load at the address at which it was linked.
272 // Memory below 1MB should be treated reserved for CSM and there should be
273 // no modules whose preferred load addresses are below 1MB.
275 Status
= EFI_OUT_OF_RESOURCES
;
276 if (Image
->ImageContext
.ImageAddress
>= 0x100000 || Image
->ImageContext
.RelocationsStripped
) {
277 Status
= CoreAllocatePages (
279 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
280 Image
->NumberOfPages
,
281 &Image
->ImageContext
.ImageAddress
284 if (EFI_ERROR (Status
) && !Image
->ImageContext
.RelocationsStripped
) {
285 Status
= CoreAllocatePages (
287 (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
),
288 Image
->NumberOfPages
,
289 &Image
->ImageContext
.ImageAddress
292 if (EFI_ERROR (Status
)) {
295 DstBufAlocated
= TRUE
;
298 // Caller provided the destination buffer
301 if (Image
->ImageContext
.RelocationsStripped
&& (Image
->ImageContext
.ImageAddress
!= DstBuffer
)) {
303 // If the image relocations were stripped, and the caller provided a
304 // destination buffer address that does not match the address that the
305 // image is linked at, then the image cannot be loaded.
307 return EFI_INVALID_PARAMETER
;
310 if (Image
->NumberOfPages
!= 0 &&
311 Image
->NumberOfPages
<
312 (EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
))) {
313 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
314 return EFI_BUFFER_TOO_SMALL
;
317 Image
->NumberOfPages
= EFI_SIZE_TO_PAGES ((UINTN
)Image
->ImageContext
.ImageSize
+ Image
->ImageContext
.SectionAlignment
);
318 Image
->ImageContext
.ImageAddress
= DstBuffer
;
321 Image
->ImageBasePage
= Image
->ImageContext
.ImageAddress
;
322 Image
->ImageContext
.ImageAddress
=
323 (Image
->ImageContext
.ImageAddress
+ Image
->ImageContext
.SectionAlignment
- 1) &
324 ~((UINTN
)Image
->ImageContext
.SectionAlignment
- 1);
327 // Load the image from the file into the allocated memory
329 Status
= PeCoffLoaderLoadImage (&Image
->ImageContext
);
330 if (EFI_ERROR (Status
)) {
335 // If this is a Runtime Driver, then allocate memory for the FixupData that
336 // is used to relocate the image when SetVirtualAddressMap() is called. The
337 // relocation is done by the Runtime AP.
339 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) {
340 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
341 Image
->ImageContext
.FixupData
= CoreAllocateRuntimePool ((UINTN
)(Image
->ImageContext
.FixupDataSize
));
342 if (Image
->ImageContext
.FixupData
== NULL
) {
343 Status
= EFI_OUT_OF_RESOURCES
;
350 // Relocate the image in memory
352 Status
= PeCoffLoaderRelocateImage (&Image
->ImageContext
);
353 if (EFI_ERROR (Status
)) {
358 // Flush the Instruction Cache
360 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
, (UINTN
)Image
->ImageContext
.ImageSize
);
363 // Copy the machine type from the context to the image private data. This
364 // is needed during image unload to know if we should call an EBC protocol
365 // to unload the image.
367 Image
->Machine
= Image
->ImageContext
.Machine
;
370 // Get the image entry point. If it's an EBC image, then call into the
371 // interpreter to create a thunk for the entry point and use the returned
372 // value for the entry point.
374 Image
->EntryPoint
= (EFI_IMAGE_ENTRY_POINT
)(UINTN
)Image
->ImageContext
.EntryPoint
;
375 if (Image
->ImageContext
.Machine
== EFI_IMAGE_MACHINE_EBC
) {
377 // Locate the EBC interpreter protocol
379 Status
= CoreLocateProtocol (&gEfiEbcProtocolGuid
, NULL
, (VOID
**)&Image
->Ebc
);
380 if (EFI_ERROR(Status
)) {
385 // Register a callback for flushing the instruction cache so that created
386 // thunks can be flushed.
388 Status
= Image
->Ebc
->RegisterICacheFlush (Image
->Ebc
, (EBC_ICACHE_FLUSH
)InvalidateInstructionCacheRange
);
389 if (EFI_ERROR(Status
)) {
394 // Create a thunk for the image's entry point. This will be the new
395 // entry point for the image.
397 Status
= Image
->Ebc
->CreateThunk (
400 (VOID
*)(UINTN
)Image
->ImageContext
.EntryPoint
,
401 (VOID
**)&Image
->EntryPoint
403 if (EFI_ERROR(Status
)) {
409 // Fill in the image information for the Loaded Image Protocol
411 Image
->Type
= Image
->ImageContext
.ImageType
;
412 Image
->Info
.ImageBase
= (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
;
413 Image
->Info
.ImageSize
= Image
->ImageContext
.ImageSize
;
414 Image
->Info
.ImageCodeType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageCodeMemoryType
);
415 Image
->Info
.ImageDataType
= (EFI_MEMORY_TYPE
) (Image
->ImageContext
.ImageDataMemoryType
);
416 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
) {
417 if (Image
->ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
419 // Make a list off all the RT images so we can let the RT AP know about them.
421 Image
->RuntimeData
= CoreAllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY
));
422 if (Image
->RuntimeData
== NULL
) {
425 Image
->RuntimeData
->ImageBase
= Image
->Info
.ImageBase
;
426 Image
->RuntimeData
->ImageSize
= (UINT64
) (Image
->Info
.ImageSize
);
427 Image
->RuntimeData
->RelocationData
= Image
->ImageContext
.FixupData
;
428 Image
->RuntimeData
->Handle
= Image
->Handle
;
429 InsertTailList (&gRuntime
->ImageHead
, &Image
->RuntimeData
->Link
);
434 // Fill in the entry point of the image if it is available
436 if (EntryPoint
!= NULL
) {
437 *EntryPoint
= Image
->ImageContext
.EntryPoint
;
441 // Print the load address and the PDB file name if it is available
448 CHAR8 EfiFileName
[256];
450 if (Image
->ImageContext
.Machine
!= IMAGE_FILE_MACHINE_IA64
) {
451 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
,
452 "Loading driver at 0x%10p EntryPoint=0x%10p ",
453 (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
,
454 (VOID
*)(UINTN
)Image
->ImageContext
.EntryPoint
));
457 // For IPF Image, the real entry point should be print.
459 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
,
460 "Loading driver at 0x%10p EntryPoint=0x%10p ",
461 (VOID
*)(UINTN
)Image
->ImageContext
.ImageAddress
,
462 (VOID
*)(UINTN
)(*(UINT64
*)(UINTN
)Image
->ImageContext
.EntryPoint
)));
466 // Print Module Name by Pdb file path
468 if (Image
->ImageContext
.PdbPointer
!= NULL
) {
470 for (Index
= 0; Image
->ImageContext
.PdbPointer
[Index
] != 0; Index
++) {
471 if (Image
->ImageContext
.PdbPointer
[Index
] == '\\') {
472 StartIndex
= Index
+ 1;
476 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
478 for (Index
= 0; Index
< sizeof (EfiFileName
); Index
++) {
479 EfiFileName
[Index
] = Image
->ImageContext
.PdbPointer
[Index
+ StartIndex
];
480 if (EfiFileName
[Index
] == 0) {
481 EfiFileName
[Index
] = '.';
483 if (EfiFileName
[Index
] == '.') {
484 EfiFileName
[Index
+ 1] = 'e';
485 EfiFileName
[Index
+ 2] = 'f';
486 EfiFileName
[Index
+ 3] = 'i';
487 EfiFileName
[Index
+ 4] = 0;
491 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "%a", EfiFileName
)); // &Image->ImageContext.PdbPointer[StartIndex]));
493 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "\n"));
505 if (DstBufAlocated
) {
506 CoreFreePages (Image
->ImageContext
.ImageAddress
, Image
->NumberOfPages
);
509 if (Image
->ImageContext
.FixupData
!= NULL
) {
510 CoreFreePool (Image
->ImageContext
.FixupData
);
517 LOADED_IMAGE_PRIVATE_DATA
*
518 CoreLoadedImageInfo (
519 IN EFI_HANDLE ImageHandle
525 Get the image's private data from its handle.
529 ImageHandle - The image handle
533 Return the image private data associated with ImageHandle.
538 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
539 LOADED_IMAGE_PRIVATE_DATA
*Image
;
541 Status
= CoreHandleProtocol (
543 &gEfiLoadedImageProtocolGuid
,
544 (VOID
**)&LoadedImage
546 if (!EFI_ERROR (Status
)) {
547 Image
= LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage
);
549 DEBUG ((EFI_D_LOAD
, "CoreLoadedImageInfo: Not an ImageHandle %x\n", ImageHandle
));
558 CoreLoadImageCommon (
559 IN BOOLEAN BootPolicy
,
560 IN EFI_HANDLE ParentImageHandle
,
561 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
562 IN VOID
*SourceBuffer OPTIONAL
,
564 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
565 IN OUT UINTN
*NumberOfPages OPTIONAL
,
566 OUT EFI_HANDLE
*ImageHandle
,
567 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
574 Loads an EFI image into memory and returns a handle to the image.
578 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
579 and that the boot manager is attempting to load FilePath as a boot selection.
580 ParentImageHandle - The caller's image handle.
581 FilePath - The specific file path from which the image is loaded.
582 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
583 the image to be loaded.
584 SourceSize - The size in bytes of SourceBuffer.
585 DstBuffer - The buffer to store the image
586 NumberOfPages - If not NULL, a pointer to the image's page number, if this number
587 is not enough, return EFI_BUFFER_TOO_SMALL and this parameter contain
589 ImageHandle - Pointer to the returned image handle that is created when the image
590 is successfully loaded.
591 EntryPoint - A pointer to the entry point
592 Attribute - The bit mask of attributes to set for the load PE image
596 EFI_SUCCESS - The image was loaded into memory.
597 EFI_NOT_FOUND - The FilePath was not found.
598 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
599 EFI_BUFFER_TOO_SMALL - The buffer is too small
600 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
601 parsed to locate the proper protocol for loading the file.
602 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
605 LOADED_IMAGE_PRIVATE_DATA
*Image
;
606 LOADED_IMAGE_PRIVATE_DATA
*ParentImage
;
607 IMAGE_FILE_HANDLE FHand
;
609 EFI_STATUS SecurityStatus
;
610 EFI_HANDLE DeviceHandle
;
611 UINT32 AuthenticationStatus
;
612 EFI_DEVICE_PATH_PROTOCOL
*OriginalFilePath
;
613 EFI_DEVICE_PATH_PROTOCOL
*HandleFilePath
;
616 SecurityStatus
= EFI_SUCCESS
;
618 ASSERT (gEfiCurrentTpl
< TPL_NOTIFY
);
622 // The caller must pass in a valid ParentImageHandle
624 if (ImageHandle
== NULL
|| ParentImageHandle
== NULL
) {
625 return EFI_INVALID_PARAMETER
;
628 ParentImage
= CoreLoadedImageInfo (ParentImageHandle
);
629 if (ParentImage
== NULL
) {
630 DEBUG((EFI_D_LOAD
|EFI_D_ERROR
, "LoadImageEx: Parent handle not an image handle\n"));
631 return EFI_INVALID_PARAMETER
;
635 // Get simple read access to the source file
637 OriginalFilePath
= FilePath
;
638 Status
= CoreOpenImageFile (
645 &AuthenticationStatus
647 if (Status
== EFI_ALREADY_STARTED
) {
650 } else if (EFI_ERROR (Status
)) {
655 // Verify the Authentication Status through the Security Architectural Protocol
657 if ((gSecurity
!= NULL
) && (OriginalFilePath
!= NULL
)) {
658 SecurityStatus
= gSecurity
->FileAuthenticationState (
660 AuthenticationStatus
,
663 if (EFI_ERROR (SecurityStatus
) && SecurityStatus
!= EFI_SECURITY_VIOLATION
) {
664 Status
= SecurityStatus
;
672 // Allocate a new image structure
674 Image
= CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA
));
676 return EFI_OUT_OF_RESOURCES
;
680 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
682 Status
= CoreHandleProtocol (DeviceHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&HandleFilePath
);
683 if (!EFI_ERROR (Status
)) {
684 FilePathSize
= CoreDevicePathSize (HandleFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
685 FilePath
= (EFI_DEVICE_PATH_PROTOCOL
*) ( ((UINT8
*)FilePath
) + FilePathSize
);
686 Image
->DeviceHandleDevicePath
= CoreDuplicateDevicePath (HandleFilePath
);
690 // Initialize the fields for an internal driver
692 Image
->Signature
= LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
;
693 Image
->Info
.SystemTable
= gDxeCoreST
;
694 Image
->Info
.DeviceHandle
= DeviceHandle
;
695 Image
->Info
.Revision
= EFI_LOADED_IMAGE_INFORMATION_REVISION
;
696 Image
->Info
.FilePath
= CoreDuplicateDevicePath (FilePath
);
697 Image
->Info
.ParentHandle
= ParentImageHandle
;
700 if (NumberOfPages
!= NULL
) {
701 Image
->NumberOfPages
= *NumberOfPages
;
703 Image
->NumberOfPages
= 0 ;
707 // Install the protocol interfaces for this image
708 // don't fire notifications yet
710 Status
= CoreInstallProtocolInterfaceNotify (
712 &gEfiLoadedImageProtocolGuid
,
713 EFI_NATIVE_INTERFACE
,
717 if (EFI_ERROR (Status
)) {
722 // Load the image. If EntryPoint is Null, it will not be set.
724 Status
= CoreLoadPeImage (&FHand
, Image
, DstBuffer
, EntryPoint
, Attribute
);
725 if (EFI_ERROR (Status
)) {
726 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_OUT_OF_RESOURCES
)) {
727 if (NumberOfPages
!= NULL
) {
728 *NumberOfPages
= Image
->NumberOfPages
;
735 // Register the image in the Debug Image Info Table if the attribute is set
737 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
) {
738 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL
, &Image
->Info
, Image
->Handle
);
742 //Reinstall loaded image protocol to fire any notifications
744 Status
= CoreReinstallProtocolInterface (
746 &gEfiLoadedImageProtocolGuid
,
750 if (EFI_ERROR (Status
)) {
756 // Success. Return the image handle
758 *ImageHandle
= Image
->Handle
;
762 // All done accessing the source file
763 // If we allocated the Source buffer, free it
765 if (FHand
.FreeBuffer
) {
766 CoreFreePool (FHand
.Source
);
770 // There was an error. If there's an Image structure, free it
772 if (EFI_ERROR (Status
)) {
774 CoreUnloadAndCloseImage (Image
, (BOOLEAN
)(DstBuffer
== 0));
777 } else if (EFI_ERROR (SecurityStatus
)) {
778 Status
= SecurityStatus
;
789 IN BOOLEAN BootPolicy
,
790 IN EFI_HANDLE ParentImageHandle
,
791 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
792 IN VOID
*SourceBuffer OPTIONAL
,
794 OUT EFI_HANDLE
*ImageHandle
800 Loads an EFI image into memory and returns a handle to the image.
804 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
805 and that the boot manager is attempting to load FilePath as a boot selection.
806 ParentImageHandle - The caller's image handle.
807 FilePath - The specific file path from which the image is loaded.
808 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
809 the image to be loaded.
810 SourceSize - The size in bytes of SourceBuffer.
811 ImageHandle - Pointer to the returned image handle that is created when the image
812 is successfully loaded.
816 EFI_SUCCESS - The image was loaded into memory.
817 EFI_NOT_FOUND - The FilePath was not found.
818 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
819 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
820 parsed to locate the proper protocol for loading the file.
821 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
826 PERF_START (NULL
, "LoadImage", NULL
, 0);
828 Status
= CoreLoadImageCommon (
834 (EFI_PHYSICAL_ADDRESS
)NULL
,
838 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
| EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
841 PERF_END (NULL
, "LoadImage", NULL
, 0);
850 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
851 IN EFI_HANDLE ParentImageHandle
,
852 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
853 IN VOID
*SourceBuffer OPTIONAL
,
855 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
856 OUT UINTN
*NumberOfPages OPTIONAL
,
857 OUT EFI_HANDLE
*ImageHandle
,
858 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
865 Loads an EFI image into memory and returns a handle to the image with extended parameters.
869 This - Calling context
870 ParentImageHandle - The caller's image handle.
871 FilePath - The specific file path from which the image is loaded.
872 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
873 the image to be loaded.
874 SourceSize - The size in bytes of SourceBuffer.
875 DstBuffer - The buffer to store the image.
876 NumberOfPages - For input, specifies the space size of the image by caller if not NULL.
877 For output, specifies the actual space size needed.
878 ImageHandle - Image handle for output.
879 EntryPoint - Image entry point for output.
880 Attribute - The bit mask of attributes to set for the load PE image.
884 EFI_SUCCESS - The image was loaded into memory.
885 EFI_NOT_FOUND - The FilePath was not found.
886 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
887 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
888 parsed to locate the proper protocol for loading the file.
889 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
892 return CoreLoadImageCommon (
912 IN EFI_HANDLE ImageHandle
,
913 OUT UINTN
*ExitDataSize
,
914 OUT CHAR16
**ExitData OPTIONAL
920 Transfer control to a loaded image's entry point.
924 ImageHandle - Handle of image to be started.
926 ExitDataSize - Pointer of the size to ExitData
928 ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated
929 Unicode string, optionally followed by additional binary data. The string
930 is a description that the caller may use to further indicate the reason for
935 EFI_INVALID_PARAMETER - Invalid parameter
937 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
939 EFI_SUCCESS - Successfully transfer control to the image's entry point.
944 LOADED_IMAGE_PRIVATE_DATA
*Image
;
945 LOADED_IMAGE_PRIVATE_DATA
*LastImage
;
946 UINT64 HandleDatabaseKey
;
949 Image
= CoreLoadedImageInfo (ImageHandle
);
950 if (Image
== NULL_HANDLE
|| Image
->Started
) {
951 return EFI_INVALID_PARAMETER
;
955 // Don't profile Objects or invalid start requests
957 PERF_START (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
961 // Push the current start image context, and
962 // link the current image to the head. This is the
963 // only image that can call Exit()
965 HandleDatabaseKey
= CoreGetHandleDatabaseKey ();
966 LastImage
= mCurrentImage
;
967 mCurrentImage
= Image
;
968 Image
->Tpl
= gEfiCurrentTpl
;
971 // Set long jump for Exit() support
972 // JumpContext must be aligned on a CPU specific boundary.
973 // Overallocate the buffer and force the required alignment
975 Image
->JumpBuffer
= CoreAllocateBootServicesPool (sizeof (BASE_LIBRARY_JUMP_BUFFER
) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
976 if (Image
->JumpBuffer
== NULL
) {
977 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
978 return EFI_OUT_OF_RESOURCES
;
980 Image
->JumpContext
= ALIGN_POINTER (Image
->JumpBuffer
, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
982 SetJumpFlag
= SetJump (Image
->JumpContext
);
984 // The initial call to SetJump() must always return 0.
985 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
989 // Call the image's entry point
991 Image
->Started
= TRUE
;
992 Image
->Status
= Image
->EntryPoint (ImageHandle
, Image
->Info
.SystemTable
);
995 // Add some debug information if the image returned with error.
996 // This make the user aware and check if the driver image have already released
997 // all the resource in this situation.
1000 if (EFI_ERROR (Image
->Status
)) {
1001 DEBUG ((EFI_D_ERROR
, "Error: Image at %10p start failed: %r\n", Image
->Info
.ImageBase
, Image
->Status
));
1006 // If the image returns, exit it through Exit()
1008 CoreExit (ImageHandle
, Image
->Status
, 0, NULL
);
1012 // Image has completed. Verify the tpl is the same
1014 ASSERT (Image
->Tpl
== gEfiCurrentTpl
);
1015 CoreRestoreTpl (Image
->Tpl
);
1017 CoreFreePool (Image
->JumpBuffer
);
1020 // Pop the current start image context
1022 mCurrentImage
= LastImage
;
1025 // Go connect any handles that were created or modified while the image executed.
1027 CoreConnectHandlesByKey (HandleDatabaseKey
);
1030 // Handle the image's returned ExitData
1032 DEBUG_CODE_BEGIN ();
1033 if (Image
->ExitDataSize
!= 0 || Image
->ExitData
!= NULL
) {
1037 "StartImage: ExitDataSize %d, ExitData %x",
1038 Image
->ExitDataSize
,
1041 if (Image
->ExitData
!= NULL
) {
1042 DEBUG ((EFI_D_LOAD
, " (%hs)", Image
->ExitData
));
1044 DEBUG ((EFI_D_LOAD
, "\n"));
1049 // Return the exit data to the caller
1051 if (ExitData
!= NULL
&& ExitDataSize
!= NULL
) {
1052 *ExitDataSize
= Image
->ExitDataSize
;
1053 *ExitData
= Image
->ExitData
;
1056 // Caller doesn't want the exit data, free it
1058 CoreFreePool (Image
->ExitData
);
1059 Image
->ExitData
= NULL
;
1063 // Save the Status because Image will get destroyed if it is unloaded.
1065 Status
= Image
->Status
;
1068 // If the image returned an error, or if the image is an application
1071 if (EFI_ERROR (Image
->Status
) || Image
->Type
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1072 CoreUnloadAndCloseImage (Image
, TRUE
);
1078 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
1084 CoreUnloadAndCloseImage (
1085 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
1090 Routine Description:
1092 Unloads EFI image from memory.
1097 FreePage - Free allocated pages
1107 EFI_HANDLE
*HandleBuffer
;
1109 EFI_GUID
**ProtocolGuidArray
;
1111 UINTN ProtocolIndex
;
1112 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfo
;
1113 UINTN OpenInfoCount
;
1114 UINTN OpenInfoIndex
;
1116 if (Image
->Ebc
!= NULL
) {
1118 // If EBC protocol exists we must perform cleanups for this image.
1120 Image
->Ebc
->UnloadImage (Image
->Ebc
, Image
->Handle
);
1124 // Unload image, free Image->ImageContext->ModHandle
1126 PeCoffLoaderUnloadImage (&Image
->ImageContext
);
1129 // Free our references to the image handle
1131 if (Image
->Handle
!= NULL_HANDLE
) {
1133 Status
= CoreLocateHandleBuffer (
1140 if (!EFI_ERROR (Status
)) {
1141 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
1142 Status
= CoreProtocolsPerHandle (
1143 HandleBuffer
[HandleIndex
],
1147 if (!EFI_ERROR (Status
)) {
1148 for (ProtocolIndex
= 0; ProtocolIndex
< ArrayCount
; ProtocolIndex
++) {
1149 Status
= CoreOpenProtocolInformation (
1150 HandleBuffer
[HandleIndex
],
1151 ProtocolGuidArray
[ProtocolIndex
],
1155 if (!EFI_ERROR (Status
)) {
1156 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
1157 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== Image
->Handle
) {
1158 Status
= CoreCloseProtocol (
1159 HandleBuffer
[HandleIndex
],
1160 ProtocolGuidArray
[ProtocolIndex
],
1162 OpenInfo
[OpenInfoIndex
].ControllerHandle
1166 if (OpenInfo
!= NULL
) {
1167 CoreFreePool(OpenInfo
);
1171 if (ProtocolGuidArray
!= NULL
) {
1172 CoreFreePool(ProtocolGuidArray
);
1176 if (HandleBuffer
!= NULL
) {
1177 CoreFreePool (HandleBuffer
);
1181 CoreRemoveDebugImageInfoEntry (Image
->Handle
);
1183 Status
= CoreUninstallProtocolInterface (
1185 &gEfiLoadedImageProtocolGuid
,
1190 if (Image
->RuntimeData
!= NULL
) {
1191 if (Image
->RuntimeData
->Link
.ForwardLink
!= NULL
) {
1193 // Remove the Image from the Runtime Image list as we are about to Free it!
1195 RemoveEntryList (&Image
->RuntimeData
->Link
);
1197 CoreFreePool (Image
->RuntimeData
);
1201 // Free the Image from memory
1203 if ((Image
->ImageBasePage
!= 0) && FreePage
) {
1204 CoreFreePages (Image
->ImageBasePage
, Image
->NumberOfPages
);
1208 // Done with the Image structure
1210 if (Image
->Info
.FilePath
!= NULL
) {
1211 CoreFreePool (Image
->Info
.FilePath
);
1214 if (Image
->DeviceHandleDevicePath
!= NULL
) {
1215 CoreFreePool (Image
->DeviceHandleDevicePath
);
1218 if (Image
->FixupData
!= NULL
) {
1219 CoreFreePool (Image
->FixupData
);
1222 CoreFreePool (Image
);
1230 IN EFI_HANDLE ImageHandle
,
1231 IN EFI_STATUS Status
,
1232 IN UINTN ExitDataSize
,
1233 IN CHAR16
*ExitData OPTIONAL
1237 Routine Description:
1239 Terminates the currently loaded EFI image and returns control to boot services.
1243 ImageHandle - Handle that identifies the image. This parameter is passed to the image
1245 Status - The image's exit code.
1246 ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is
1248 ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string,
1249 optionally followed by additional binary data. The string is a
1250 description that the caller may use to further indicate the reason for
1255 EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image.
1257 EFI_SUCCESS - Successfully terminates the currently loaded EFI image.
1259 EFI_ACCESS_DENIED - Should never reach there.
1261 EFI_OUT_OF_RESOURCES - Could not allocate pool
1265 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1269 // Prevent possible reentrance to this function
1270 // for the same ImageHandle
1272 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1274 Image
= CoreLoadedImageInfo (ImageHandle
);
1275 if (Image
== NULL_HANDLE
) {
1276 Status
= EFI_INVALID_PARAMETER
;
1280 if (!Image
->Started
) {
1282 // The image has not been started so just free its resources
1284 CoreUnloadAndCloseImage (Image
, TRUE
);
1285 Status
= EFI_SUCCESS
;
1290 // Image has been started, verify this image can exit
1292 if (Image
!= mCurrentImage
) {
1293 DEBUG ((EFI_D_LOAD
|EFI_D_ERROR
, "Exit: Image is not exitable image\n"));
1294 Status
= EFI_INVALID_PARAMETER
;
1301 Image
->Status
= Status
;
1304 // If there's ExitData info, move it
1306 if (ExitData
!= NULL
) {
1307 Image
->ExitDataSize
= ExitDataSize
;
1308 Image
->ExitData
= CoreAllocateBootServicesPool (Image
->ExitDataSize
);
1309 if (Image
->ExitData
== NULL
) {
1310 Status
= EFI_OUT_OF_RESOURCES
;
1313 CopyMem (Image
->ExitData
, ExitData
, Image
->ExitDataSize
);
1316 CoreRestoreTpl (OldTpl
);
1318 // return to StartImage
1320 LongJump (Image
->JumpContext
, (UINTN
)-1);
1323 // If we return from LongJump, then it is an error
1326 Status
= EFI_ACCESS_DENIED
;
1328 CoreRestoreTpl (OldTpl
);
1337 IN EFI_HANDLE ImageHandle
1341 Routine Description:
1347 ImageHandle - Handle that identifies the image to be unloaded.
1351 EFI_SUCCESS - The image has been unloaded.
1352 EFI_UNSUPPORTED - The image has been sarted, and does not support unload.
1353 EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle.
1358 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1362 // Prevent possible reentrance to this function
1363 // for the same ImageHandle
1365 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1367 Image
= CoreLoadedImageInfo (ImageHandle
);
1368 if (Image
== NULL
) {
1370 // The image handle is not valid
1372 Status
= EFI_INVALID_PARAMETER
;
1376 if (Image
->Started
) {
1378 // The image has been started, request it to unload.
1380 Status
= EFI_UNSUPPORTED
;
1381 if (Image
->Info
.Unload
!= NULL
) {
1382 Status
= Image
->Info
.Unload (ImageHandle
);
1387 // This Image hasn't been started, thus it can be unloaded
1389 Status
= EFI_SUCCESS
;
1393 if (!EFI_ERROR (Status
)) {
1395 // if the Image was not started or Unloaded O.K. then clean up
1397 CoreUnloadAndCloseImage (Image
, TRUE
);
1401 CoreRestoreTpl (OldTpl
);
1409 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
1410 IN EFI_HANDLE ImageHandle
1414 Routine Description:
1416 Unload the specified image.
1420 This - Indicates the calling context.
1422 ImageHandle - The specified image handle.
1426 EFI_INVALID_PARAMETER - Image handle is NULL.
1428 EFI_UNSUPPORTED - Attempt to unload an unsupported image.
1430 EFI_SUCCESS - Image successfully unloaded.
1434 return CoreUnloadImage (ImageHandle
);