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 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
));
451 if (Image
->ImageContext
.PdbPointer
!= NULL
) {
453 for (Index
= 0; Image
->ImageContext
.PdbPointer
[Index
] != 0; Index
++) {
454 if (Image
->ImageContext
.PdbPointer
[Index
] == '\\') {
455 StartIndex
= Index
+ 1;
459 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
461 for (Index
= 0; Index
< sizeof (EfiFileName
); Index
++) {
462 EfiFileName
[Index
] = Image
->ImageContext
.PdbPointer
[Index
+ StartIndex
];
463 if (EfiFileName
[Index
] == 0) {
464 EfiFileName
[Index
] = '.';
466 if (EfiFileName
[Index
] == '.') {
467 EfiFileName
[Index
+ 1] = 'e';
468 EfiFileName
[Index
+ 2] = 'f';
469 EfiFileName
[Index
+ 3] = 'i';
470 EfiFileName
[Index
+ 4] = 0;
474 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "%a", EfiFileName
)); // &Image->ImageContext.PdbPointer[StartIndex]));
476 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "\n"));
488 if (DstBufAlocated
) {
489 CoreFreePages (Image
->ImageContext
.ImageAddress
, Image
->NumberOfPages
);
492 if (Image
->ImageContext
.FixupData
!= NULL
) {
493 CoreFreePool (Image
->ImageContext
.FixupData
);
500 LOADED_IMAGE_PRIVATE_DATA
*
501 CoreLoadedImageInfo (
502 IN EFI_HANDLE ImageHandle
508 Get the image's private data from its handle.
512 ImageHandle - The image handle
516 Return the image private data associated with ImageHandle.
521 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
522 LOADED_IMAGE_PRIVATE_DATA
*Image
;
524 Status
= CoreHandleProtocol (
526 &gEfiLoadedImageProtocolGuid
,
527 (VOID
**)&LoadedImage
529 if (!EFI_ERROR (Status
)) {
530 Image
= LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage
);
532 DEBUG ((EFI_D_LOAD
, "CoreLoadedImageInfo: Not an ImageHandle %x\n", ImageHandle
));
541 CoreLoadImageCommon (
542 IN BOOLEAN BootPolicy
,
543 IN EFI_HANDLE ParentImageHandle
,
544 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
545 IN VOID
*SourceBuffer OPTIONAL
,
547 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
548 IN OUT UINTN
*NumberOfPages OPTIONAL
,
549 OUT EFI_HANDLE
*ImageHandle
,
550 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
557 Loads an EFI image into memory and returns a handle to the image.
561 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
562 and that the boot manager is attempting to load FilePath as a boot selection.
563 ParentImageHandle - The caller's image handle.
564 FilePath - The specific file path from which the image is loaded.
565 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
566 the image to be loaded.
567 SourceSize - The size in bytes of SourceBuffer.
568 DstBuffer - The buffer to store the image
569 NumberOfPages - If not NULL, a pointer to the image's page number, if this number
570 is not enough, return EFI_BUFFER_TOO_SMALL and this parameter contain
572 ImageHandle - Pointer to the returned image handle that is created when the image
573 is successfully loaded.
574 EntryPoint - A pointer to the entry point
575 Attribute - The bit mask of attributes to set for the load PE image
579 EFI_SUCCESS - The image was loaded into memory.
580 EFI_NOT_FOUND - The FilePath was not found.
581 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
582 EFI_BUFFER_TOO_SMALL - The buffer is too small
583 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
584 parsed to locate the proper protocol for loading the file.
585 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
588 LOADED_IMAGE_PRIVATE_DATA
*Image
;
589 LOADED_IMAGE_PRIVATE_DATA
*ParentImage
;
590 IMAGE_FILE_HANDLE FHand
;
592 EFI_STATUS SecurityStatus
;
593 EFI_HANDLE DeviceHandle
;
594 UINT32 AuthenticationStatus
;
595 EFI_DEVICE_PATH_PROTOCOL
*OriginalFilePath
;
596 EFI_DEVICE_PATH_PROTOCOL
*HandleFilePath
;
599 SecurityStatus
= EFI_SUCCESS
;
601 ASSERT (gEfiCurrentTpl
< TPL_NOTIFY
);
605 // The caller must pass in a valid ParentImageHandle
607 if (ImageHandle
== NULL
|| ParentImageHandle
== NULL
) {
608 return EFI_INVALID_PARAMETER
;
611 ParentImage
= CoreLoadedImageInfo (ParentImageHandle
);
612 if (ParentImage
== NULL
) {
613 DEBUG((EFI_D_LOAD
|EFI_D_ERROR
, "LoadImageEx: Parent handle not an image handle\n"));
614 return EFI_INVALID_PARAMETER
;
618 // Get simple read access to the source file
620 OriginalFilePath
= FilePath
;
621 Status
= CoreOpenImageFile (
628 &AuthenticationStatus
630 if (Status
== EFI_ALREADY_STARTED
) {
633 } else if (EFI_ERROR (Status
)) {
638 // Verify the Authentication Status through the Security Architectural Protocol
640 if ((gSecurity
!= NULL
) && (OriginalFilePath
!= NULL
)) {
641 SecurityStatus
= gSecurity
->FileAuthenticationState (
643 AuthenticationStatus
,
646 if (EFI_ERROR (SecurityStatus
) && SecurityStatus
!= EFI_SECURITY_VIOLATION
) {
647 Status
= SecurityStatus
;
655 // Allocate a new image structure
657 Image
= CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA
));
659 return EFI_OUT_OF_RESOURCES
;
663 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
665 Status
= CoreHandleProtocol (DeviceHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&HandleFilePath
);
666 if (!EFI_ERROR (Status
)) {
667 FilePathSize
= CoreDevicePathSize (HandleFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
668 FilePath
= (EFI_DEVICE_PATH_PROTOCOL
*) ( ((UINT8
*)FilePath
) + FilePathSize
);
669 Image
->DeviceHandleDevicePath
= CoreDuplicateDevicePath (HandleFilePath
);
673 // Initialize the fields for an internal driver
675 Image
->Signature
= LOADED_IMAGE_PRIVATE_DATA_SIGNATURE
;
676 Image
->Info
.SystemTable
= gDxeCoreST
;
677 Image
->Info
.DeviceHandle
= DeviceHandle
;
678 Image
->Info
.Revision
= EFI_LOADED_IMAGE_INFORMATION_REVISION
;
679 Image
->Info
.FilePath
= CoreDuplicateDevicePath (FilePath
);
680 Image
->Info
.ParentHandle
= ParentImageHandle
;
683 if (NumberOfPages
!= NULL
) {
684 Image
->NumberOfPages
= *NumberOfPages
;
686 Image
->NumberOfPages
= 0 ;
690 // Install the protocol interfaces for this image
691 // don't fire notifications yet
693 Status
= CoreInstallProtocolInterfaceNotify (
695 &gEfiLoadedImageProtocolGuid
,
696 EFI_NATIVE_INTERFACE
,
700 if (EFI_ERROR (Status
)) {
705 // Load the image. If EntryPoint is Null, it will not be set.
707 Status
= CoreLoadPeImage (&FHand
, Image
, DstBuffer
, EntryPoint
, Attribute
);
708 if (EFI_ERROR (Status
)) {
709 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_OUT_OF_RESOURCES
)) {
710 if (NumberOfPages
!= NULL
) {
711 *NumberOfPages
= Image
->NumberOfPages
;
718 // Register the image in the Debug Image Info Table if the attribute is set
720 if (Attribute
& EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
) {
721 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL
, &Image
->Info
, Image
->Handle
);
725 //Reinstall loaded image protocol to fire any notifications
727 Status
= CoreReinstallProtocolInterface (
729 &gEfiLoadedImageProtocolGuid
,
733 if (EFI_ERROR (Status
)) {
739 // Success. Return the image handle
741 *ImageHandle
= Image
->Handle
;
745 // All done accessing the source file
746 // If we allocated the Source buffer, free it
748 if (FHand
.FreeBuffer
) {
749 CoreFreePool (FHand
.Source
);
753 // There was an error. If there's an Image structure, free it
755 if (EFI_ERROR (Status
)) {
757 CoreUnloadAndCloseImage (Image
, (BOOLEAN
)(DstBuffer
== 0));
760 } else if (EFI_ERROR (SecurityStatus
)) {
761 Status
= SecurityStatus
;
772 IN BOOLEAN BootPolicy
,
773 IN EFI_HANDLE ParentImageHandle
,
774 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
775 IN VOID
*SourceBuffer OPTIONAL
,
777 OUT EFI_HANDLE
*ImageHandle
783 Loads an EFI image into memory and returns a handle to the image.
787 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
788 and that the boot manager is attempting to load FilePath as a boot selection.
789 ParentImageHandle - The caller's image handle.
790 FilePath - The specific file path from which the image is loaded.
791 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
792 the image to be loaded.
793 SourceSize - The size in bytes of SourceBuffer.
794 ImageHandle - Pointer to the returned image handle that is created when the image
795 is successfully loaded.
799 EFI_SUCCESS - The image was loaded into memory.
800 EFI_NOT_FOUND - The FilePath was not found.
801 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
802 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
803 parsed to locate the proper protocol for loading the file.
804 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
809 PERF_START (NULL
, "LoadImage", NULL
, 0);
811 Status
= CoreLoadImageCommon (
817 (EFI_PHYSICAL_ADDRESS
)NULL
,
821 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION
| EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
824 PERF_END (NULL
, "LoadImage", NULL
, 0);
833 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
834 IN EFI_HANDLE ParentImageHandle
,
835 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
836 IN VOID
*SourceBuffer OPTIONAL
,
838 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL
,
839 OUT UINTN
*NumberOfPages OPTIONAL
,
840 OUT EFI_HANDLE
*ImageHandle
,
841 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint OPTIONAL
,
848 Loads an EFI image into memory and returns a handle to the image with extended parameters.
852 This - Calling context
853 ParentImageHandle - The caller's image handle.
854 FilePath - The specific file path from which the image is loaded.
855 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
856 the image to be loaded.
857 SourceSize - The size in bytes of SourceBuffer.
858 DstBuffer - The buffer to store the image.
859 NumberOfPages - For input, specifies the space size of the image by caller if not NULL.
860 For output, specifies the actual space size needed.
861 ImageHandle - Image handle for output.
862 EntryPoint - Image entry point for output.
863 Attribute - The bit mask of attributes to set for the load PE image.
867 EFI_SUCCESS - The image was loaded into memory.
868 EFI_NOT_FOUND - The FilePath was not found.
869 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
870 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
871 parsed to locate the proper protocol for loading the file.
872 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
875 return CoreLoadImageCommon (
895 IN EFI_HANDLE ImageHandle
,
896 OUT UINTN
*ExitDataSize
,
897 OUT CHAR16
**ExitData OPTIONAL
903 Transfer control to a loaded image's entry point.
907 ImageHandle - Handle of image to be started.
909 ExitDataSize - Pointer of the size to ExitData
911 ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated
912 Unicode string, optionally followed by additional binary data. The string
913 is a description that the caller may use to further indicate the reason for
918 EFI_INVALID_PARAMETER - Invalid parameter
920 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
922 EFI_SUCCESS - Successfully transfer control to the image's entry point.
927 LOADED_IMAGE_PRIVATE_DATA
*Image
;
928 LOADED_IMAGE_PRIVATE_DATA
*LastImage
;
929 UINT64 HandleDatabaseKey
;
932 Image
= CoreLoadedImageInfo (ImageHandle
);
933 if (Image
== NULL_HANDLE
|| Image
->Started
) {
934 return EFI_INVALID_PARAMETER
;
938 // Don't profile Objects or invalid start requests
940 PERF_START (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
944 // Push the current start image context, and
945 // link the current image to the head. This is the
946 // only image that can call Exit()
948 HandleDatabaseKey
= CoreGetHandleDatabaseKey ();
949 LastImage
= mCurrentImage
;
950 mCurrentImage
= Image
;
951 Image
->Tpl
= gEfiCurrentTpl
;
954 // Set long jump for Exit() support
955 // JumpContext must be aligned on a CPU specific boundary.
956 // Overallocate the buffer and force the required alignment
958 Image
->JumpBuffer
= CoreAllocateBootServicesPool (sizeof (BASE_LIBRARY_JUMP_BUFFER
) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
959 if (Image
->JumpBuffer
== NULL
) {
960 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
961 return EFI_OUT_OF_RESOURCES
;
963 Image
->JumpContext
= ALIGN_POINTER (Image
->JumpBuffer
, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
965 SetJumpFlag
= SetJump (Image
->JumpContext
);
967 // The initial call to SetJump() must always return 0.
968 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
972 // Call the image's entry point
974 Image
->Started
= TRUE
;
975 Image
->Status
= Image
->EntryPoint (ImageHandle
, Image
->Info
.SystemTable
);
978 // Add some debug information if the image returned with error.
979 // This make the user aware and check if the driver image have already released
980 // all the resource in this situation.
983 if (EFI_ERROR (Image
->Status
)) {
984 DEBUG ((EFI_D_ERROR
, "Error: Image at %10p start failed: %r\n", Image
->Info
.ImageBase
, Image
->Status
));
989 // If the image returns, exit it through Exit()
991 CoreExit (ImageHandle
, Image
->Status
, 0, NULL
);
995 // Image has completed. Verify the tpl is the same
997 ASSERT (Image
->Tpl
== gEfiCurrentTpl
);
998 CoreRestoreTpl (Image
->Tpl
);
1000 CoreFreePool (Image
->JumpBuffer
);
1003 // Pop the current start image context
1005 mCurrentImage
= LastImage
;
1008 // Go connect any handles that were created or modified while the image executed.
1010 CoreConnectHandlesByKey (HandleDatabaseKey
);
1013 // Handle the image's returned ExitData
1015 DEBUG_CODE_BEGIN ();
1016 if (Image
->ExitDataSize
!= 0 || Image
->ExitData
!= NULL
) {
1020 "StartImage: ExitDataSize %d, ExitData %x",
1021 Image
->ExitDataSize
,
1024 if (Image
->ExitData
!= NULL
) {
1025 DEBUG ((EFI_D_LOAD
, " (%hs)", Image
->ExitData
));
1027 DEBUG ((EFI_D_LOAD
, "\n"));
1032 // Return the exit data to the caller
1034 if (ExitData
!= NULL
&& ExitDataSize
!= NULL
) {
1035 *ExitDataSize
= Image
->ExitDataSize
;
1036 *ExitData
= Image
->ExitData
;
1039 // Caller doesn't want the exit data, free it
1041 CoreFreePool (Image
->ExitData
);
1042 Image
->ExitData
= NULL
;
1046 // Save the Status because Image will get destroyed if it is unloaded.
1048 Status
= Image
->Status
;
1051 // If the image returned an error, or if the image is an application
1054 if (EFI_ERROR (Image
->Status
) || Image
->Type
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1055 CoreUnloadAndCloseImage (Image
, TRUE
);
1061 PERF_END (ImageHandle
, START_IMAGE_TOK
, NULL
, 0);
1067 CoreUnloadAndCloseImage (
1068 IN LOADED_IMAGE_PRIVATE_DATA
*Image
,
1073 Routine Description:
1075 Unloads EFI image from memory.
1080 FreePage - Free allocated pages
1090 EFI_HANDLE
*HandleBuffer
;
1092 EFI_GUID
**ProtocolGuidArray
;
1094 UINTN ProtocolIndex
;
1095 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfo
;
1096 UINTN OpenInfoCount
;
1097 UINTN OpenInfoIndex
;
1099 if (Image
->Ebc
!= NULL
) {
1101 // If EBC protocol exists we must perform cleanups for this image.
1103 Image
->Ebc
->UnloadImage (Image
->Ebc
, Image
->Handle
);
1107 // Unload image, free Image->ImageContext->ModHandle
1109 PeCoffLoaderUnloadImage (&Image
->ImageContext
);
1112 // Free our references to the image handle
1114 if (Image
->Handle
!= NULL_HANDLE
) {
1116 Status
= CoreLocateHandleBuffer (
1123 if (!EFI_ERROR (Status
)) {
1124 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
1125 Status
= CoreProtocolsPerHandle (
1126 HandleBuffer
[HandleIndex
],
1130 if (!EFI_ERROR (Status
)) {
1131 for (ProtocolIndex
= 0; ProtocolIndex
< ArrayCount
; ProtocolIndex
++) {
1132 Status
= CoreOpenProtocolInformation (
1133 HandleBuffer
[HandleIndex
],
1134 ProtocolGuidArray
[ProtocolIndex
],
1138 if (!EFI_ERROR (Status
)) {
1139 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
1140 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== Image
->Handle
) {
1141 Status
= CoreCloseProtocol (
1142 HandleBuffer
[HandleIndex
],
1143 ProtocolGuidArray
[ProtocolIndex
],
1145 OpenInfo
[OpenInfoIndex
].ControllerHandle
1149 if (OpenInfo
!= NULL
) {
1150 CoreFreePool(OpenInfo
);
1154 if (ProtocolGuidArray
!= NULL
) {
1155 CoreFreePool(ProtocolGuidArray
);
1159 if (HandleBuffer
!= NULL
) {
1160 CoreFreePool (HandleBuffer
);
1164 CoreRemoveDebugImageInfoEntry (Image
->Handle
);
1166 Status
= CoreUninstallProtocolInterface (
1168 &gEfiLoadedImageProtocolGuid
,
1173 if (Image
->RuntimeData
!= NULL
) {
1174 if (Image
->RuntimeData
->Link
.ForwardLink
!= NULL
) {
1176 // Remove the Image from the Runtime Image list as we are about to Free it!
1178 RemoveEntryList (&Image
->RuntimeData
->Link
);
1180 CoreFreePool (Image
->RuntimeData
);
1184 // Free the Image from memory
1186 if ((Image
->ImageBasePage
!= 0) && FreePage
) {
1187 CoreFreePages (Image
->ImageBasePage
, Image
->NumberOfPages
);
1191 // Done with the Image structure
1193 if (Image
->Info
.FilePath
!= NULL
) {
1194 CoreFreePool (Image
->Info
.FilePath
);
1197 if (Image
->DeviceHandleDevicePath
!= NULL
) {
1198 CoreFreePool (Image
->DeviceHandleDevicePath
);
1201 if (Image
->FixupData
!= NULL
) {
1202 CoreFreePool (Image
->FixupData
);
1205 CoreFreePool (Image
);
1213 IN EFI_HANDLE ImageHandle
,
1214 IN EFI_STATUS Status
,
1215 IN UINTN ExitDataSize
,
1216 IN CHAR16
*ExitData OPTIONAL
1220 Routine Description:
1222 Terminates the currently loaded EFI image and returns control to boot services.
1226 ImageHandle - Handle that identifies the image. This parameter is passed to the image
1228 Status - The image's exit code.
1229 ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is
1231 ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string,
1232 optionally followed by additional binary data. The string is a
1233 description that the caller may use to further indicate the reason for
1238 EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image.
1240 EFI_SUCCESS - Successfully terminates the currently loaded EFI image.
1242 EFI_ACCESS_DENIED - Should never reach there.
1244 EFI_OUT_OF_RESOURCES - Could not allocate pool
1248 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1252 // Prevent possible reentrance to this function
1253 // for the same ImageHandle
1255 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1257 Image
= CoreLoadedImageInfo (ImageHandle
);
1258 if (Image
== NULL_HANDLE
) {
1259 Status
= EFI_INVALID_PARAMETER
;
1263 if (!Image
->Started
) {
1265 // The image has not been started so just free its resources
1267 CoreUnloadAndCloseImage (Image
, TRUE
);
1268 Status
= EFI_SUCCESS
;
1273 // Image has been started, verify this image can exit
1275 if (Image
!= mCurrentImage
) {
1276 DEBUG ((EFI_D_LOAD
|EFI_D_ERROR
, "Exit: Image is not exitable image\n"));
1277 Status
= EFI_INVALID_PARAMETER
;
1284 Image
->Status
= Status
;
1287 // If there's ExitData info, move it
1289 if (ExitData
!= NULL
) {
1290 Image
->ExitDataSize
= ExitDataSize
;
1291 Image
->ExitData
= CoreAllocateBootServicesPool (Image
->ExitDataSize
);
1292 if (Image
->ExitData
== NULL
) {
1293 Status
= EFI_OUT_OF_RESOURCES
;
1296 CopyMem (Image
->ExitData
, ExitData
, Image
->ExitDataSize
);
1299 CoreRestoreTpl (OldTpl
);
1301 // return to StartImage
1303 LongJump (Image
->JumpContext
, (UINTN
)-1);
1306 // If we return from LongJump, then it is an error
1309 Status
= EFI_ACCESS_DENIED
;
1311 CoreRestoreTpl (OldTpl
);
1320 IN EFI_HANDLE ImageHandle
1324 Routine Description:
1330 ImageHandle - Handle that identifies the image to be unloaded.
1334 EFI_SUCCESS - The image has been unloaded.
1335 EFI_UNSUPPORTED - The image has been sarted, and does not support unload.
1336 EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle.
1341 LOADED_IMAGE_PRIVATE_DATA
*Image
;
1345 // Prevent possible reentrance to this function
1346 // for the same ImageHandle
1348 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
1350 Image
= CoreLoadedImageInfo (ImageHandle
);
1351 if (Image
== NULL
) {
1353 // The image handle is not valid
1355 Status
= EFI_INVALID_PARAMETER
;
1359 if (Image
->Started
) {
1361 // The image has been started, request it to unload.
1363 Status
= EFI_UNSUPPORTED
;
1364 if (Image
->Info
.Unload
!= NULL
) {
1365 Status
= Image
->Info
.Unload (ImageHandle
);
1370 // This Image hasn't been started, thus it can be unloaded
1372 Status
= EFI_SUCCESS
;
1376 if (!EFI_ERROR (Status
)) {
1378 // if the Image was not started or Unloaded O.K. then clean up
1380 CoreUnloadAndCloseImage (Image
, TRUE
);
1384 CoreRestoreTpl (OldTpl
);
1392 IN EFI_PE32_IMAGE_PROTOCOL
*This
,
1393 IN EFI_HANDLE ImageHandle
1397 Routine Description:
1399 Unload the specified image.
1403 This - Indicates the calling context.
1405 ImageHandle - The specified image handle.
1409 EFI_INVALID_PARAMETER - Image handle is NULL.
1411 EFI_UNSUPPORTED - Attempt to unload an unsupported image.
1413 EFI_SUCCESS - Image successfully unloaded.
1417 return CoreUnloadImage (ImageHandle
);