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