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