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