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