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