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