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