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