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