]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/Image/Image.c
1) Remove buffer overflow when the number of Driver Binding Protocols increases in...
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Image / Image.c
1 /*++
2
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
8
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.
11
12 Module Name:
13
14 Image.c
15
16 Abstract:
17
18 Core image handling services
19
20 --*/
21
22 #include <DxeMain.h>
23 //
24 // Module Globals
25 //
26
27 LOADED_IMAGE_PRIVATE_DATA *mCurrentImage = NULL;
28
29 LOAD_PE32_IMAGE_PRIVATE_DATA mLoadPe32PrivateData = {
30 LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE,
31 NULL,
32 {
33 CoreLoadImageEx,
34 CoreUnloadImageEx
35 }
36 };
37
38
39 //
40 // This code is needed to build the Image handle for the DXE Core
41 //
42 LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage = {
43 LOADED_IMAGE_PRIVATE_DATA_SIGNATURE, // Signature
44 NULL, // Image handle
45 EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, // Image type
46 TRUE, // If entrypoint has been called
47 NULL, // EntryPoint
48 {
49 EFI_LOADED_IMAGE_INFORMATION_REVISION, // Revision
50 NULL, // Parent handle
51 NULL, // System handle
52
53 NULL, // Device handle
54 NULL, // File path
55 NULL, // Reserved
56
57 0, // LoadOptionsSize
58 NULL, // LoadOptions
59
60 NULL, // ImageBase
61 0, // ImageSize
62 EfiBootServicesCode, // ImageCodeType
63 EfiBootServicesData // ImageDataType
64 },
65 (EFI_PHYSICAL_ADDRESS)0, // ImageBasePage
66 0, // NumberOfPages
67 NULL, // FixupData
68 0, // Tpl
69 EFI_SUCCESS, // Status
70 0, // ExitDataSize
71 NULL, // ExitData
72 NULL, // JumpBuffer
73 NULL, // JumpContext
74 0, // Machine
75 NULL, // Ebc
76 NULL, // RuntimeData
77 NULL, // DeviceHandleDevicePath
78 };
79
80
81 EFI_STATUS
82 CoreInitializeImageServices (
83 IN VOID *HobStart
84 )
85 /*++
86
87 Routine Description:
88
89 Add the Image Services to EFI Boot Services Table and install the protocol
90 interfaces for this image.
91
92 Arguments:
93
94 HobStart - The HOB to initialize
95
96 Returns:
97
98 Status code.
99
100 --*/
101 {
102 EFI_STATUS Status;
103 LOADED_IMAGE_PRIVATE_DATA *Image;
104 EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress;
105 UINT64 DxeCoreImageLength;
106 VOID *DxeCoreEntryPoint;
107 EFI_PEI_HOB_POINTERS DxeCoreHob;
108 //
109 // Searching for image hob
110 //
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)) {
114 //
115 // Find Dxe Core HOB
116 //
117 break;
118 }
119 DxeCoreHob.Raw = GET_NEXT_HOB (DxeCoreHob);
120 }
121 ASSERT (DxeCoreHob.Raw != NULL);
122
123 DxeCoreImageBaseAddress = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress;
124 DxeCoreImageLength = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength;
125 DxeCoreEntryPoint = (VOID *) (UINTN) DxeCoreHob.MemoryAllocationModule->EntryPoint;
126 gDxeCoreFileName = &DxeCoreHob.MemoryAllocationModule->ModuleName;
127 //
128 // Initialize the fields for an internal driver
129 //
130 Image = &mCorePrivateImage;
131
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;
139
140 //
141 // Install the protocol interfaces for this image
142 //
143 Status = CoreInstallProtocolInterface (
144 &Image->Handle,
145 &gEfiLoadedImageProtocolGuid,
146 EFI_NATIVE_INTERFACE,
147 &Image->Info
148 );
149 ASSERT_EFI_ERROR (Status);
150
151 mCurrentImage = Image;
152
153 //
154 // Fill in DXE globals
155 //
156 gDxeCoreImageHandle = Image->Handle;
157 gDxeCoreLoadedImage = &Image->Info;
158
159 //
160 // Export DXE Core PE Loader functionality
161 //
162 return CoreInstallProtocolInterface (
163 &mLoadPe32PrivateData.Handle,
164 &gEfiLoadPeImageProtocolGuid,
165 EFI_NATIVE_INTERFACE,
166 &mLoadPe32PrivateData.Pe32Image
167 );
168 }
169
170 EFI_STATUS
171 CoreLoadPeImage (
172 IN VOID *Pe32Handle,
173 IN LOADED_IMAGE_PRIVATE_DATA *Image,
174 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
175 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
176 IN UINT32 Attribute
177 )
178 /*++
179
180 Routine Description:
181
182 Loads, relocates, and invokes a PE/COFF image
183
184 Arguments:
185
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
191
192 Returns:
193
194 EFI_SUCCESS - The file was loaded, relocated, and invoked
195
196 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
197
198 EFI_INVALID_PARAMETER - Invalid parameter
199
200 EFI_BUFFER_TOO_SMALL - Buffer for image is too small
201
202 --*/
203 {
204 EFI_STATUS Status;
205 BOOLEAN DstBufAlocated;
206 UINTN Size;
207
208 ZeroMem (&Image->ImageContext, sizeof (Image->ImageContext));
209
210 Image->ImageContext.Handle = Pe32Handle;
211 Image->ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)CoreReadImageFile;
212
213 //
214 // Get information about the image being loaded
215 //
216 Status = gEfiPeiPeCoffLoader->GetImageInfo (gEfiPeiPeCoffLoader, &Image->ImageContext);
217 if (EFI_ERROR (Status)) {
218 return Status;
219 }
220
221 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine)) {
222 //
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.
225 //
226 return EFI_UNSUPPORTED;
227 }
228
229
230 //
231 // Allocate memory of the correct memory type aligned on the required image boundry
232 //
233 DstBufAlocated = FALSE;
234 if (DstBuffer == 0) {
235 //
236 // Allocate Destination Buffer as caller did not pass it in
237 //
238
239 if (Image->ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
240 Size = (UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment;
241 } else {
242 Size = (UINTN)Image->ImageContext.ImageSize;
243 }
244
245 Image->NumberOfPages = EFI_SIZE_TO_PAGES (Size);
246
247 //
248 // If the image relocations have not been stripped, then load at any address.
249 // Otherwise load at the address at which it was linked.
250 //
251 // Memory below 1MB should be treated reserved for CSM and there should be
252 // no modules whose preferred load addresses are below 1MB.
253 //
254 Status = EFI_OUT_OF_RESOURCES;
255 if (Image->ImageContext.ImageAddress >= 0x100000 || Image->ImageContext.RelocationsStripped) {
256 Status = CoreAllocatePages (
257 AllocateAddress,
258 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),
259 Image->NumberOfPages,
260 &Image->ImageContext.ImageAddress
261 );
262 }
263 if (EFI_ERROR (Status) && !Image->ImageContext.RelocationsStripped) {
264 Status = CoreAllocatePages (
265 AllocateAnyPages,
266 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),
267 Image->NumberOfPages,
268 &Image->ImageContext.ImageAddress
269 );
270 }
271 if (EFI_ERROR (Status)) {
272 return Status;
273 }
274 DstBufAlocated = TRUE;
275 } else {
276 //
277 // Caller provided the destination buffer
278 //
279
280 if (Image->ImageContext.RelocationsStripped && (Image->ImageContext.ImageAddress != DstBuffer)) {
281 //
282 // If the image relocations were stripped, and the caller provided a
283 // destination buffer address that does not match the address that the
284 // image is linked at, then the image cannot be loaded.
285 //
286 return EFI_INVALID_PARAMETER;
287 }
288
289 if (Image->NumberOfPages != 0 &&
290 Image->NumberOfPages <
291 (EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment))) {
292 Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);
293 return EFI_BUFFER_TOO_SMALL;
294 }
295
296 Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);
297 Image->ImageContext.ImageAddress = DstBuffer;
298 }
299
300 Image->ImageBasePage = Image->ImageContext.ImageAddress;
301 Image->ImageContext.ImageAddress =
302 (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &
303 ~((UINTN)Image->ImageContext.SectionAlignment - 1);
304
305 //
306 // Load the image from the file into the allocated memory
307 //
308 Status = gEfiPeiPeCoffLoader->LoadImage (gEfiPeiPeCoffLoader, &Image->ImageContext);
309 if (EFI_ERROR (Status)) {
310 goto Done;
311 }
312
313 //
314 // If this is a Runtime Driver, then allocate memory for the FixupData that
315 // is used to relocate the image when SetVirtualAddressMap() is called. The
316 // relocation is done by the Runtime AP.
317 //
318 if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) {
319 if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
320 Image->ImageContext.FixupData = CoreAllocateRuntimePool ((UINTN)(Image->ImageContext.FixupDataSize));
321 if (Image->ImageContext.FixupData == NULL) {
322 Status = EFI_OUT_OF_RESOURCES;
323 goto Done;
324 }
325 }
326 }
327
328 //
329 // Relocate the image in memory
330 //
331 Status = gEfiPeiPeCoffLoader->RelocateImage (gEfiPeiPeCoffLoader, &Image->ImageContext);
332 if (EFI_ERROR (Status)) {
333 goto Done;
334 }
335
336 //
337 // Flush the Instruction Cache
338 //
339 InvalidateInstructionCacheRange ((VOID *)(UINTN)Image->ImageContext.ImageAddress, (UINTN)Image->ImageContext.ImageSize);
340
341 //
342 // Copy the machine type from the context to the image private data. This
343 // is needed during image unload to know if we should call an EBC protocol
344 // to unload the image.
345 //
346 Image->Machine = Image->ImageContext.Machine;
347
348 //
349 // Get the image entry point. If it's an EBC image, then call into the
350 // interpreter to create a thunk for the entry point and use the returned
351 // value for the entry point.
352 //
353 Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)Image->ImageContext.EntryPoint;
354 if (Image->ImageContext.Machine == EFI_IMAGE_MACHINE_EBC) {
355 //
356 // Locate the EBC interpreter protocol
357 //
358 Status = CoreLocateProtocol (&gEfiEbcProtocolGuid, NULL, (VOID **)&Image->Ebc);
359 if (EFI_ERROR(Status)) {
360 goto Done;
361 }
362
363 //
364 // Register a callback for flushing the instruction cache so that created
365 // thunks can be flushed.
366 //
367 Status = Image->Ebc->RegisterICacheFlush (Image->Ebc, (EBC_ICACHE_FLUSH)InvalidateInstructionCacheRange);
368 if (EFI_ERROR(Status)) {
369 goto Done;
370 }
371
372 //
373 // Create a thunk for the image's entry point. This will be the new
374 // entry point for the image.
375 //
376 Status = Image->Ebc->CreateThunk (
377 Image->Ebc,
378 Image->Handle,
379 (VOID *)(UINTN)Image->ImageContext.EntryPoint,
380 (VOID **)&Image->EntryPoint
381 );
382 if (EFI_ERROR(Status)) {
383 goto Done;
384 }
385 }
386
387 //
388 // Fill in the image information for the Loaded Image Protocol
389 //
390 Image->Type = Image->ImageContext.ImageType;
391 Image->Info.ImageBase = (VOID *)(UINTN)Image->ImageContext.ImageAddress;
392 Image->Info.ImageSize = Image->ImageContext.ImageSize;
393 Image->Info.ImageCodeType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType);
394 Image->Info.ImageDataType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageDataMemoryType);
395 if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) {
396 if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
397 //
398 // Make a list off all the RT images so we can let the RT AP know about them.
399 //
400 Image->RuntimeData = CoreAllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY));
401 if (Image->RuntimeData == NULL) {
402 goto Done;
403 }
404 Image->RuntimeData->ImageBase = Image->Info.ImageBase;
405 Image->RuntimeData->ImageSize = (UINT64) (Image->Info.ImageSize);
406 Image->RuntimeData->RelocationData = Image->ImageContext.FixupData;
407 Image->RuntimeData->Handle = Image->Handle;
408 InsertTailList (&gRuntime->ImageHead, &Image->RuntimeData->Link);
409 }
410 }
411
412 //
413 // Fill in the entry point of the image if it is available
414 //
415 if (EntryPoint != NULL) {
416 *EntryPoint = Image->ImageContext.EntryPoint;
417 }
418
419 //
420 // Print the load address and the PDB file name if it is available
421 //
422
423 DEBUG_CODE_BEGIN ();
424
425 UINTN Index;
426 UINTN StartIndex;
427 CHAR8 EfiFileName[256];
428
429 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading driver at 0x%10p EntryPoint=0x%10p ", (VOID *)(UINTN)Image->ImageContext.ImageAddress, (VOID *)(UINTN)Image->ImageContext.EntryPoint));
430 if (Image->ImageContext.PdbPointer != NULL) {
431 StartIndex = 0;
432 for (Index = 0; Image->ImageContext.PdbPointer[Index] != 0; Index++) {
433 if (Image->ImageContext.PdbPointer[Index] == '\\') {
434 StartIndex = Index + 1;
435 }
436 }
437 //
438 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
439 //
440 for (Index = 0; Index < sizeof (EfiFileName); Index++) {
441 EfiFileName[Index] = Image->ImageContext.PdbPointer[Index + StartIndex];
442 if (EfiFileName[Index] == 0) {
443 EfiFileName[Index] = '.';
444 }
445 if (EfiFileName[Index] == '.') {
446 EfiFileName[Index + 1] = 'e';
447 EfiFileName[Index + 2] = 'f';
448 EfiFileName[Index + 3] = 'i';
449 EfiFileName[Index + 4] = 0;
450 break;
451 }
452 }
453 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex]));
454 }
455 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));
456
457 DEBUG_CODE_END ();
458
459 return EFI_SUCCESS;
460
461 Done:
462
463 //
464 // Free memory.
465 //
466
467 if (DstBufAlocated) {
468 CoreFreePages (Image->ImageContext.ImageAddress, Image->NumberOfPages);
469 }
470
471 if (Image->ImageContext.FixupData != NULL) {
472 CoreFreePool (Image->ImageContext.FixupData);
473 }
474
475 return Status;
476 }
477
478
479 LOADED_IMAGE_PRIVATE_DATA *
480 CoreLoadedImageInfo (
481 IN EFI_HANDLE ImageHandle
482 )
483 /*++
484
485 Routine Description:
486
487 Get the image's private data from its handle.
488
489 Arguments:
490
491 ImageHandle - The image handle
492
493 Returns:
494
495 Return the image private data associated with ImageHandle.
496
497 --*/
498 {
499 EFI_STATUS Status;
500 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
501 LOADED_IMAGE_PRIVATE_DATA *Image;
502
503 Status = CoreHandleProtocol (
504 ImageHandle,
505 &gEfiLoadedImageProtocolGuid,
506 (VOID **)&LoadedImage
507 );
508 if (!EFI_ERROR (Status)) {
509 Image = LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage);
510 } else {
511 DEBUG ((EFI_D_LOAD, "CoreLoadedImageInfo: Not an ImageHandle %x\n", ImageHandle));
512 Image = NULL;
513 }
514
515 return Image;
516 }
517
518 STATIC
519 EFI_STATUS
520 CoreLoadImageCommon (
521 IN BOOLEAN BootPolicy,
522 IN EFI_HANDLE ParentImageHandle,
523 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
524 IN VOID *SourceBuffer OPTIONAL,
525 IN UINTN SourceSize,
526 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
527 IN OUT UINTN *NumberOfPages OPTIONAL,
528 OUT EFI_HANDLE *ImageHandle,
529 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
530 IN UINT32 Attribute
531 )
532 /*++
533
534 Routine Description:
535
536 Loads an EFI image into memory and returns a handle to the image.
537
538 Arguments:
539
540 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
541 and that the boot manager is attempting to load FilePath as a boot selection.
542 ParentImageHandle - The caller's image handle.
543 FilePath - The specific file path from which the image is loaded.
544 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
545 the image to be loaded.
546 SourceSize - The size in bytes of SourceBuffer.
547 DstBuffer - The buffer to store the image
548 NumberOfPages - If not NULL, a pointer to the image's page number, if this number
549 is not enough, return EFI_BUFFER_TOO_SMALL and this parameter contain
550 the required number.
551 ImageHandle - Pointer to the returned image handle that is created when the image
552 is successfully loaded.
553 EntryPoint - A pointer to the entry point
554 Attribute - The bit mask of attributes to set for the load PE image
555
556 Returns:
557
558 EFI_SUCCESS - The image was loaded into memory.
559 EFI_NOT_FOUND - The FilePath was not found.
560 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
561 EFI_BUFFER_TOO_SMALL - The buffer is too small
562 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
563 parsed to locate the proper protocol for loading the file.
564 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
565 --*/
566 {
567 LOADED_IMAGE_PRIVATE_DATA *Image;
568 LOADED_IMAGE_PRIVATE_DATA *ParentImage;
569 IMAGE_FILE_HANDLE FHand;
570 EFI_STATUS Status;
571 EFI_STATUS SecurityStatus;
572 EFI_HANDLE DeviceHandle;
573 UINT32 AuthenticationStatus;
574 EFI_DEVICE_PATH_PROTOCOL *OriginalFilePath;
575 EFI_DEVICE_PATH_PROTOCOL *HandleFilePath;
576 UINTN FilePathSize;
577
578 SecurityStatus = EFI_SUCCESS;
579
580 ASSERT (gEfiCurrentTpl < TPL_NOTIFY);
581 ParentImage = NULL;
582
583 //
584 // The caller must pass in a valid ParentImageHandle
585 //
586 if (ImageHandle == NULL || ParentImageHandle == NULL) {
587 return EFI_INVALID_PARAMETER;
588 }
589
590 ParentImage = CoreLoadedImageInfo (ParentImageHandle);
591 if (ParentImage == NULL) {
592 DEBUG((EFI_D_LOAD|EFI_D_ERROR, "LoadImageEx: Parent handle not an image handle\n"));
593 return EFI_INVALID_PARAMETER;
594 }
595
596 //
597 // Get simple read access to the source file
598 //
599 OriginalFilePath = FilePath;
600 Status = CoreOpenImageFile (
601 BootPolicy,
602 SourceBuffer,
603 SourceSize,
604 FilePath,
605 &DeviceHandle,
606 &FHand,
607 &AuthenticationStatus
608 );
609 if (Status == EFI_ALREADY_STARTED) {
610 Image = NULL;
611 goto Done;
612 } else if (EFI_ERROR (Status)) {
613 return Status;
614 }
615
616 //
617 // Verify the Authentication Status through the Security Architectural Protocol
618 //
619 if ((gSecurity != NULL) && (OriginalFilePath != NULL)) {
620 SecurityStatus = gSecurity->FileAuthenticationState (
621 gSecurity,
622 AuthenticationStatus,
623 OriginalFilePath
624 );
625 if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {
626 Status = SecurityStatus;
627 Image = NULL;
628 goto Done;
629 }
630 }
631
632
633 //
634 // Allocate a new image structure
635 //
636 Image = CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA));
637 if (Image == NULL) {
638 return EFI_OUT_OF_RESOURCES;
639 }
640
641 //
642 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
643 //
644 Status = CoreHandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath);
645 if (!EFI_ERROR (Status)) {
646 FilePathSize = CoreDevicePathSize (HandleFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
647 FilePath = (EFI_DEVICE_PATH_PROTOCOL *) ( ((UINT8 *)FilePath) + FilePathSize );
648 Image->DeviceHandleDevicePath = CoreDuplicateDevicePath (HandleFilePath);
649 }
650
651 //
652 // Initialize the fields for an internal driver
653 //
654 Image->Signature = LOADED_IMAGE_PRIVATE_DATA_SIGNATURE;
655 Image->Info.SystemTable = gDxeCoreST;
656 Image->Info.DeviceHandle = DeviceHandle;
657 Image->Info.Revision = EFI_LOADED_IMAGE_INFORMATION_REVISION;
658 Image->Info.FilePath = CoreDuplicateDevicePath (FilePath);
659 Image->Info.ParentHandle = ParentImageHandle;
660
661
662 if (NumberOfPages != NULL) {
663 Image->NumberOfPages = *NumberOfPages ;
664 } else {
665 Image->NumberOfPages = 0 ;
666 }
667
668 //
669 // Install the protocol interfaces for this image
670 // don't fire notifications yet
671 //
672 Status = CoreInstallProtocolInterfaceNotify (
673 &Image->Handle,
674 &gEfiLoadedImageProtocolGuid,
675 EFI_NATIVE_INTERFACE,
676 &Image->Info,
677 FALSE
678 );
679 if (EFI_ERROR (Status)) {
680 goto Done;
681 }
682
683 //
684 // Load the image. If EntryPoint is Null, it will not be set.
685 //
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;
691 }
692 }
693 goto Done;
694 }
695
696 //
697 // Register the image in the Debug Image Info Table if the attribute is set
698 //
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);
701 }
702
703 //
704 //Reinstall loaded image protocol to fire any notifications
705 //
706 Status = CoreReinstallProtocolInterface (
707 Image->Handle,
708 &gEfiLoadedImageProtocolGuid,
709 &Image->Info,
710 &Image->Info
711 );
712 if (EFI_ERROR (Status)) {
713 goto Done;
714 }
715
716
717 //
718 // Success. Return the image handle
719 //
720 *ImageHandle = Image->Handle;
721
722 Done:
723 //
724 // All done accessing the source file
725 // If we allocated the Source buffer, free it
726 //
727 if (FHand.FreeBuffer) {
728 CoreFreePool (FHand.Source);
729 }
730
731 //
732 // There was an error. If there's an Image structure, free it
733 //
734 if (EFI_ERROR (Status)) {
735 if (Image != NULL) {
736 CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer == 0));
737 *ImageHandle = NULL;
738 }
739 } else if (EFI_ERROR (SecurityStatus)) {
740 Status = SecurityStatus;
741 }
742
743 return Status;
744 }
745
746
747
748 EFI_STATUS
749 EFIAPI
750 CoreLoadImage (
751 IN BOOLEAN BootPolicy,
752 IN EFI_HANDLE ParentImageHandle,
753 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
754 IN VOID *SourceBuffer OPTIONAL,
755 IN UINTN SourceSize,
756 OUT EFI_HANDLE *ImageHandle
757 )
758 /*++
759
760 Routine Description:
761
762 Loads an EFI image into memory and returns a handle to the image.
763
764 Arguments:
765
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.
775
776 Returns:
777
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.
784 --*/
785 {
786 EFI_STATUS Status;
787
788 PERF_START (NULL, "LoadImage", NULL, 0);
789
790 Status = CoreLoadImageCommon (
791 BootPolicy,
792 ParentImageHandle,
793 FilePath,
794 SourceBuffer,
795 SourceSize,
796 (EFI_PHYSICAL_ADDRESS)NULL,
797 NULL,
798 ImageHandle,
799 NULL,
800 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION | EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
801 );
802
803 PERF_END (NULL, "LoadImage", NULL, 0);
804
805 return Status;
806 }
807
808
809 EFI_STATUS
810 EFIAPI
811 CoreLoadImageEx (
812 IN EFI_PE32_IMAGE_PROTOCOL *This,
813 IN EFI_HANDLE ParentImageHandle,
814 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
815 IN VOID *SourceBuffer OPTIONAL,
816 IN UINTN SourceSize,
817 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
818 OUT UINTN *NumberOfPages OPTIONAL,
819 OUT EFI_HANDLE *ImageHandle,
820 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
821 IN UINT32 Attribute
822 )
823 /*++
824
825 Routine Description:
826
827 Loads an EFI image into memory and returns a handle to the image with extended parameters.
828
829 Arguments:
830
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.
843
844 Returns:
845
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.
852 --*/
853 {
854 return CoreLoadImageCommon (
855 TRUE,
856 ParentImageHandle,
857 FilePath,
858 SourceBuffer,
859 SourceSize,
860 DstBuffer,
861 NumberOfPages,
862 ImageHandle,
863 EntryPoint,
864 Attribute
865 );
866 }
867
868
869
870
871 EFI_STATUS
872 EFIAPI
873 CoreStartImage (
874 IN EFI_HANDLE ImageHandle,
875 OUT UINTN *ExitDataSize,
876 OUT CHAR16 **ExitData OPTIONAL
877 )
878 /*++
879
880 Routine Description:
881
882 Transfer control to a loaded image's entry point.
883
884 Arguments:
885
886 ImageHandle - Handle of image to be started.
887
888 ExitDataSize - Pointer of the size to ExitData
889
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
893 the image's exit.
894
895 Returns:
896
897 EFI_INVALID_PARAMETER - Invalid parameter
898
899 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
900
901 EFI_SUCCESS - Successfully transfer control to the image's entry point.
902
903 --*/
904 {
905 EFI_STATUS Status;
906 LOADED_IMAGE_PRIVATE_DATA *Image;
907 LOADED_IMAGE_PRIVATE_DATA *LastImage;
908 UINT64 HandleDatabaseKey;
909 UINTN SetJumpFlag;
910
911 Image = CoreLoadedImageInfo (ImageHandle);
912 if (Image == NULL_HANDLE || Image->Started) {
913 return EFI_INVALID_PARAMETER;
914 }
915
916 //
917 // Don't profile Objects or invalid start requests
918 //
919 PERF_START (ImageHandle, START_IMAGE_TOK, NULL, 0);
920
921
922 //
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()
926 //
927 HandleDatabaseKey = CoreGetHandleDatabaseKey ();
928 LastImage = mCurrentImage;
929 mCurrentImage = Image;
930 Image->Tpl = gEfiCurrentTpl;
931
932 //
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
936 //
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;
941 }
942 Image->JumpContext = ALIGN_POINTER (Image->JumpBuffer, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);
943
944 SetJumpFlag = SetJump (Image->JumpContext);
945 //
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().
948 //
949 if (!SetJumpFlag) {
950 //
951 // Call the image's entry point
952 //
953 Image->Started = TRUE;
954 Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable);
955
956 //
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.
960 //
961 DEBUG_CODE_BEGIN ();
962 if (EFI_ERROR (Image->Status)) {
963 DEBUG ((EFI_D_ERROR, "Error: Image at %10p start failed: %r\n", Image->Info.ImageBase, Image->Status));
964 }
965 DEBUG_CODE_END ();
966
967 //
968 // If the image returns, exit it through Exit()
969 //
970 CoreExit (ImageHandle, Image->Status, 0, NULL);
971 }
972
973 //
974 // Image has completed. Verify the tpl is the same
975 //
976 ASSERT (Image->Tpl == gEfiCurrentTpl);
977 CoreRestoreTpl (Image->Tpl);
978
979 CoreFreePool (Image->JumpBuffer);
980
981 //
982 // Pop the current start image context
983 //
984 mCurrentImage = LastImage;
985
986 //
987 // Go connect any handles that were created or modified while the image executed.
988 //
989 CoreConnectHandlesByKey (HandleDatabaseKey);
990
991 //
992 // Handle the image's returned ExitData
993 //
994 DEBUG_CODE_BEGIN ();
995 if (Image->ExitDataSize != 0 || Image->ExitData != NULL) {
996
997 DEBUG (
998 (EFI_D_LOAD,
999 "StartImage: ExitDataSize %d, ExitData %x",
1000 Image->ExitDataSize,
1001 Image->ExitData)
1002 );
1003 if (Image->ExitData != NULL) {
1004 DEBUG ((EFI_D_LOAD, " (%hs)", Image->ExitData));
1005 }
1006 DEBUG ((EFI_D_LOAD, "\n"));
1007 }
1008 DEBUG_CODE_END ();
1009
1010 //
1011 // Return the exit data to the caller
1012 //
1013 if (ExitData != NULL && ExitDataSize != NULL) {
1014 *ExitDataSize = Image->ExitDataSize;
1015 *ExitData = Image->ExitData;
1016 } else {
1017 //
1018 // Caller doesn't want the exit data, free it
1019 //
1020 CoreFreePool (Image->ExitData);
1021 Image->ExitData = NULL;
1022 }
1023
1024 //
1025 // Save the Status because Image will get destroyed if it is unloaded.
1026 //
1027 Status = Image->Status;
1028
1029 //
1030 // If the image returned an error, or if the image is an application
1031 // unload it
1032 //
1033 if (EFI_ERROR (Image->Status) || Image->Type == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
1034 CoreUnloadAndCloseImage (Image, TRUE);
1035 }
1036
1037 //
1038 // Done
1039 //
1040 PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);
1041 return Status;
1042 }
1043
1044
1045 VOID
1046 CoreUnloadAndCloseImage (
1047 IN LOADED_IMAGE_PRIVATE_DATA *Image,
1048 IN BOOLEAN FreePage
1049 )
1050 /*++
1051
1052 Routine Description:
1053
1054 Unloads EFI image from memory.
1055
1056 Arguments:
1057
1058 Image - EFI image
1059 FreePage - Free allocated pages
1060
1061 Returns:
1062
1063 None
1064
1065 --*/
1066 {
1067 EFI_STATUS Status;
1068 UINTN HandleCount;
1069 EFI_HANDLE *HandleBuffer;
1070 UINTN HandleIndex;
1071 EFI_GUID **ProtocolGuidArray;
1072 UINTN ArrayCount;
1073 UINTN ProtocolIndex;
1074 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;
1075 UINTN OpenInfoCount;
1076 UINTN OpenInfoIndex;
1077
1078 if (Image->Ebc != NULL) {
1079 //
1080 // If EBC protocol exists we must perform cleanups for this image.
1081 //
1082 Image->Ebc->UnloadImage (Image->Ebc, Image->Handle);
1083 }
1084
1085 //
1086 // Unload image, free Image->ImageContext->ModHandle
1087 //
1088 gEfiPeiPeCoffLoader->UnloadImage (gEfiPeiPeCoffLoader, &Image->ImageContext);
1089
1090 //
1091 // Free our references to the image handle
1092 //
1093 if (Image->Handle != NULL_HANDLE) {
1094
1095 Status = CoreLocateHandleBuffer (
1096 AllHandles,
1097 NULL,
1098 NULL,
1099 &HandleCount,
1100 &HandleBuffer
1101 );
1102 if (!EFI_ERROR (Status)) {
1103 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
1104 Status = CoreProtocolsPerHandle (
1105 HandleBuffer[HandleIndex],
1106 &ProtocolGuidArray,
1107 &ArrayCount
1108 );
1109 if (!EFI_ERROR (Status)) {
1110 for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
1111 Status = CoreOpenProtocolInformation (
1112 HandleBuffer[HandleIndex],
1113 ProtocolGuidArray[ProtocolIndex],
1114 &OpenInfo,
1115 &OpenInfoCount
1116 );
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],
1123 Image->Handle,
1124 OpenInfo[OpenInfoIndex].ControllerHandle
1125 );
1126 }
1127 }
1128 if (OpenInfo != NULL) {
1129 CoreFreePool(OpenInfo);
1130 }
1131 }
1132 }
1133 if (ProtocolGuidArray != NULL) {
1134 CoreFreePool(ProtocolGuidArray);
1135 }
1136 }
1137 }
1138 if (HandleBuffer != NULL) {
1139 CoreFreePool (HandleBuffer);
1140 }
1141 }
1142
1143 CoreRemoveDebugImageInfoEntry (Image->Handle);
1144
1145 Status = CoreUninstallProtocolInterface (
1146 Image->Handle,
1147 &gEfiLoadedImageProtocolGuid,
1148 &Image->Info
1149 );
1150 }
1151
1152 if (Image->RuntimeData != NULL) {
1153 if (Image->RuntimeData->Link.ForwardLink != NULL) {
1154 //
1155 // Remove the Image from the Runtime Image list as we are about to Free it!
1156 //
1157 RemoveEntryList (&Image->RuntimeData->Link);
1158 }
1159 CoreFreePool (Image->RuntimeData);
1160 }
1161
1162 //
1163 // Free the Image from memory
1164 //
1165 if ((Image->ImageBasePage != 0) && FreePage) {
1166 CoreFreePages (Image->ImageBasePage, Image->NumberOfPages);
1167 }
1168
1169 //
1170 // Done with the Image structure
1171 //
1172 if (Image->Info.FilePath != NULL) {
1173 CoreFreePool (Image->Info.FilePath);
1174 }
1175
1176 if (Image->DeviceHandleDevicePath != NULL) {
1177 CoreFreePool (Image->DeviceHandleDevicePath);
1178 }
1179
1180 if (Image->FixupData != NULL) {
1181 CoreFreePool (Image->FixupData);
1182 }
1183
1184 CoreFreePool (Image);
1185 }
1186
1187
1188
1189 EFI_STATUS
1190 EFIAPI
1191 CoreExit (
1192 IN EFI_HANDLE ImageHandle,
1193 IN EFI_STATUS Status,
1194 IN UINTN ExitDataSize,
1195 IN CHAR16 *ExitData OPTIONAL
1196 )
1197 /*++
1198
1199 Routine Description:
1200
1201 Terminates the currently loaded EFI image and returns control to boot services.
1202
1203 Arguments:
1204
1205 ImageHandle - Handle that identifies the image. This parameter is passed to the image
1206 on entry.
1207 Status - The image's exit code.
1208 ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is
1209 EFI_SUCCESS.
1210 ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string,
1211 optionally followed by additional binary data. The string is a
1212 description that the caller may use to further indicate the reason for
1213 the image's exit.
1214
1215 Returns:
1216
1217 EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image.
1218
1219 EFI_SUCCESS - Successfully terminates the currently loaded EFI image.
1220
1221 EFI_ACCESS_DENIED - Should never reach there.
1222
1223 EFI_OUT_OF_RESOURCES - Could not allocate pool
1224
1225 --*/
1226 {
1227 LOADED_IMAGE_PRIVATE_DATA *Image;
1228 EFI_TPL OldTpl;
1229
1230 //
1231 // Prevent possible reentrance to this function
1232 // for the same ImageHandle
1233 //
1234 OldTpl = CoreRaiseTpl (TPL_NOTIFY);
1235
1236 Image = CoreLoadedImageInfo (ImageHandle);
1237 if (Image == NULL_HANDLE) {
1238 Status = EFI_INVALID_PARAMETER;
1239 goto Done;
1240 }
1241
1242 if (!Image->Started) {
1243 //
1244 // The image has not been started so just free its resources
1245 //
1246 CoreUnloadAndCloseImage (Image, TRUE);
1247 Status = EFI_SUCCESS;
1248 goto Done;
1249 }
1250
1251 //
1252 // Image has been started, verify this image can exit
1253 //
1254 if (Image != mCurrentImage) {
1255 DEBUG ((EFI_D_LOAD|EFI_D_ERROR, "Exit: Image is not exitable image\n"));
1256 Status = EFI_INVALID_PARAMETER;
1257 goto Done;
1258 }
1259
1260 //
1261 // Set status
1262 //
1263 Image->Status = Status;
1264
1265 //
1266 // If there's ExitData info, move it
1267 //
1268 if (ExitData != NULL) {
1269 Image->ExitDataSize = ExitDataSize;
1270 Image->ExitData = CoreAllocateBootServicesPool (Image->ExitDataSize);
1271 if (Image->ExitData == NULL) {
1272 Status = EFI_OUT_OF_RESOURCES;
1273 goto Done;
1274 }
1275 CopyMem (Image->ExitData, ExitData, Image->ExitDataSize);
1276 }
1277
1278 CoreRestoreTpl (OldTpl);
1279 //
1280 // return to StartImage
1281 //
1282 LongJump (Image->JumpContext, (UINTN)-1);
1283
1284 //
1285 // If we return from LongJump, then it is an error
1286 //
1287 ASSERT (FALSE);
1288 Status = EFI_ACCESS_DENIED;
1289 Done:
1290 CoreRestoreTpl (OldTpl);
1291 return Status;
1292 }
1293
1294
1295
1296 EFI_STATUS
1297 EFIAPI
1298 CoreUnloadImage (
1299 IN EFI_HANDLE ImageHandle
1300 )
1301 /*++
1302
1303 Routine Description:
1304
1305 Unloads an image.
1306
1307 Arguments:
1308
1309 ImageHandle - Handle that identifies the image to be unloaded.
1310
1311 Returns:
1312
1313 EFI_SUCCESS - The image has been unloaded.
1314 EFI_UNSUPPORTED - The image has been sarted, and does not support unload.
1315 EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle.
1316
1317 --*/
1318 {
1319 EFI_STATUS Status;
1320 LOADED_IMAGE_PRIVATE_DATA *Image;
1321 EFI_TPL OldTpl;
1322
1323 //
1324 // Prevent possible reentrance to this function
1325 // for the same ImageHandle
1326 //
1327 OldTpl = CoreRaiseTpl (TPL_NOTIFY);
1328
1329 Image = CoreLoadedImageInfo (ImageHandle);
1330 if (Image == NULL ) {
1331 //
1332 // The image handle is not valid
1333 //
1334 Status = EFI_INVALID_PARAMETER;
1335 goto Done;
1336 }
1337
1338 if (Image->Started) {
1339 //
1340 // The image has been started, request it to unload.
1341 //
1342 Status = EFI_UNSUPPORTED;
1343 if (Image->Info.Unload != NULL) {
1344 Status = Image->Info.Unload (ImageHandle);
1345 }
1346
1347 } else {
1348 //
1349 // This Image hasn't been started, thus it can be unloaded
1350 //
1351 Status = EFI_SUCCESS;
1352 }
1353
1354
1355 if (!EFI_ERROR (Status)) {
1356 //
1357 // if the Image was not started or Unloaded O.K. then clean up
1358 //
1359 CoreUnloadAndCloseImage (Image, TRUE);
1360 }
1361
1362 Done:
1363 CoreRestoreTpl (OldTpl);
1364 return Status;
1365 }
1366
1367
1368 EFI_STATUS
1369 EFIAPI
1370 CoreUnloadImageEx (
1371 IN EFI_PE32_IMAGE_PROTOCOL *This,
1372 IN EFI_HANDLE ImageHandle
1373 )
1374 /*++
1375
1376 Routine Description:
1377
1378 Unload the specified image.
1379
1380 Arguments:
1381
1382 This - Indicates the calling context.
1383
1384 ImageHandle - The specified image handle.
1385
1386 Returns:
1387
1388 EFI_INVALID_PARAMETER - Image handle is NULL.
1389
1390 EFI_UNSUPPORTED - Attempt to unload an unsupported image.
1391
1392 EFI_SUCCESS - Image successfully unloaded.
1393
1394 --*/
1395 {
1396 return CoreUnloadImage (ImageHandle);
1397 }