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