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