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