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