]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Core/Dxe/Image/Image.c
Removed cross references from PciCf8Lib and PciExpressLib class to PciLib class.
[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 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine)) {
272 //
273 // The PE/COFF loader can support loading image types that can be executed.
274 // If we loaded an image type that we can not execute return EFI_UNSUPORTED.
275 //
276 return EFI_UNSUPPORTED;
277 }
278
279
280 //
281 // Allocate memory of the correct memory type aligned on the required image boundry
282 //
283
284 if (DstBuffer == 0) {
285 //
286 // Allocate Destination Buffer as caller did not pass it in
287 //
288
289 if (Image->ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
290 Size = (UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment;
291 } else {
292 Size = (UINTN)Image->ImageContext.ImageSize;
293 }
294
295 Image->NumberOfPages = EFI_SIZE_TO_PAGES (Size);
296
297 //
298 // If the image relocations have not been stripped, then load at any address.
299 // Otherwise load at the address at which it was linked.
300 //
301 Status = CoreAllocatePages (
302 (Image->ImageContext.RelocationsStripped) ? AllocateAddress : AllocateAnyPages,
303 Image->ImageContext.ImageCodeMemoryType,
304 Image->NumberOfPages,
305 &Image->ImageContext.ImageAddress
306 );
307 if (EFI_ERROR (Status)) {
308 return Status;
309 }
310
311 Image->ImageBasePage = Image->ImageContext.ImageAddress;
312
313 } else {
314 //
315 // Caller provided the destination buffer
316 //
317
318 if (Image->ImageContext.RelocationsStripped && (Image->ImageContext.ImageAddress != DstBuffer)) {
319 //
320 // If the image relocations were stripped, and the caller provided a
321 // destination buffer address that does not match the address that the
322 // image is linked at, then the image cannot be loaded.
323 //
324 return EFI_INVALID_PARAMETER;
325 }
326
327 if (Image->NumberOfPages != 0 &&
328 Image->NumberOfPages <
329 (EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment))) {
330 Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);
331 return EFI_BUFFER_TOO_SMALL;
332 }
333
334 Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);
335 Image->ImageContext.ImageAddress = DstBuffer;
336 Image->ImageBasePage = Image->ImageContext.ImageAddress;
337 }
338
339 Image->ImageContext.ImageAddress =
340 (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &
341 ~((UINTN)Image->ImageContext.SectionAlignment - 1);
342
343 //
344 // Load the image from the file into the allocated memory
345 //
346 Status = gEfiPeiPeCoffLoader->LoadImage (gEfiPeiPeCoffLoader, &Image->ImageContext);
347 if (EFI_ERROR (Status)) {
348 return Status;
349 }
350
351 //
352 // If this is a Runtime Driver, then allocate memory for the FixupData that
353 // is used to relocate the image when SetVirtualAddressMap() is called. The
354 // relocation is done by the Runtime AP.
355 //
356 if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) {
357 if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
358 Image->ImageContext.FixupData = CoreAllocateRuntimePool ((UINTN)(Image->ImageContext.FixupDataSize));
359 if (Image->ImageContext.FixupData == NULL) {
360 Status = EFI_OUT_OF_RESOURCES;
361 goto Done;
362 }
363
364 //
365 // Make a list off all the RT images so we can let the RT AP know about them
366 //
367 Image->RuntimeFixupValid = TRUE;
368 Image->RuntimeFixup = Image->ImageContext.FixupData;
369 InsertTailList (&mRuntimeImageList, &Image->Link);
370 }
371 }
372
373 //
374 // Relocate the image in memory
375 //
376 Status = gEfiPeiPeCoffLoader->RelocateImage (gEfiPeiPeCoffLoader, &Image->ImageContext);
377 if (EFI_ERROR (Status)) {
378 return Status;
379 }
380
381 //
382 // Flush the Instruction Cache
383 //
384 InvalidateInstructionCacheRange ((VOID *)(UINTN)Image->ImageContext.ImageAddress, (UINTN)Image->ImageContext.ImageSize);
385
386 //
387 // Copy the machine type from the context to the image private data. This
388 // is needed during image unload to know if we should call an EBC protocol
389 // to unload the image.
390 //
391 Image->Machine = Image->ImageContext.Machine;
392
393 //
394 // Get the image entry point. If it's an EBC image, then call into the
395 // interpreter to create a thunk for the entry point and use the returned
396 // value for the entry point.
397 //
398 Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)Image->ImageContext.EntryPoint;
399 if (Image->ImageContext.Machine == EFI_IMAGE_MACHINE_EBC) {
400 //
401 // Locate the EBC interpreter protocol
402 //
403 Status = CoreLocateProtocol (&gEfiEbcProtocolGuid, NULL, (VOID **)&Image->Ebc);
404 if (EFI_ERROR(Status)) {
405 goto Done;
406 }
407
408 //
409 // Register a callback for flushing the instruction cache so that created
410 // thunks can be flushed.
411 //
412 Status = Image->Ebc->RegisterICacheFlush (Image->Ebc, (EBC_ICACHE_FLUSH)InvalidateInstructionCacheRange);
413 if (EFI_ERROR(Status)) {
414 goto Done;
415 }
416
417 //
418 // Create a thunk for the image's entry point. This will be the new
419 // entry point for the image.
420 //
421 Status = Image->Ebc->CreateThunk (
422 Image->Ebc,
423 Image->Handle,
424 (VOID *)(UINTN)Image->ImageContext.EntryPoint,
425 (VOID **)&Image->EntryPoint
426 );
427 if (EFI_ERROR(Status)) {
428 goto Done;
429 }
430 }
431
432 //
433 // Fill in the image information for the Loaded Image Protocol
434 //
435 Image->Type = Image->ImageContext.ImageType;
436 Image->Info.ImageBase = (VOID *)(UINTN)Image->ImageContext.ImageAddress;
437 Image->Info.ImageSize = Image->ImageContext.ImageSize;
438 Image->Info.ImageCodeType = Image->ImageContext.ImageCodeMemoryType;
439 Image->Info.ImageDataType = Image->ImageContext.ImageDataMemoryType;
440
441 //
442 // Fill in the entry point of the image if it is available
443 //
444 if (EntryPoint != NULL) {
445 *EntryPoint = Image->ImageContext.EntryPoint;
446 }
447
448 //
449 // Print the load address and the PDB file name if it is available
450 //
451
452 DEBUG_CODE_BEGIN ();
453
454 UINTN Index;
455 UINTN StartIndex;
456 CHAR8 EfiFileName[256];
457
458 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading driver at 0x%08x EntryPoint=0x%08x ", (UINTN)Image->ImageContext.ImageAddress, (UINTN)Image->ImageContext.EntryPoint));
459 if (Image->ImageContext.PdbPointer != NULL) {
460 StartIndex = 0;
461 for (Index = 0; Image->ImageContext.PdbPointer[Index] != 0; Index++) {
462 if (Image->ImageContext.PdbPointer[Index] == '\\') {
463 StartIndex = Index + 1;
464 }
465 }
466 //
467 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
468 //
469 for (Index = 0; Index < sizeof (EfiFileName); Index++) {
470 EfiFileName[Index] = Image->ImageContext.PdbPointer[Index + StartIndex];
471 if (EfiFileName[Index] == 0) {
472 EfiFileName[Index] = '.';
473 }
474 if (EfiFileName[Index] == '.') {
475 EfiFileName[Index + 1] = 'e';
476 EfiFileName[Index + 2] = 'f';
477 EfiFileName[Index + 3] = 'i';
478 EfiFileName[Index + 4] = 0;
479 break;
480 }
481 }
482 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex]));
483 }
484 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));
485
486 DEBUG_CODE_END ();
487
488 return EFI_SUCCESS;
489
490 Done:
491 //
492 // Free memory
493 //
494 CoreFreePages (Image->ImageContext.ImageAddress, Image->NumberOfPages);
495 return Status;
496 }
497
498
499 LOADED_IMAGE_PRIVATE_DATA *
500 CoreLoadedImageInfo (
501 IN EFI_HANDLE ImageHandle
502 )
503 /*++
504
505 Routine Description:
506
507 Get the image's private data from its handle.
508
509 Arguments:
510
511 ImageHandle - The image handle
512
513 Returns:
514
515 Return the image private data associated with ImageHandle.
516
517 --*/
518 {
519 EFI_STATUS Status;
520 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
521 LOADED_IMAGE_PRIVATE_DATA *Image;
522
523 Status = CoreHandleProtocol (
524 ImageHandle,
525 &gEfiLoadedImageProtocolGuid,
526 (VOID **)&LoadedImage
527 );
528 if (!EFI_ERROR (Status)) {
529 Image = LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage);
530 } else {
531 DEBUG ((EFI_D_LOAD, "CoreLoadedImageInfo: Not an ImageHandle %x\n", ImageHandle));
532 Image = NULL;
533 }
534
535 return Image;
536 }
537
538
539 EFI_STATUS
540 CoreLoadImageCommon (
541 IN BOOLEAN BootPolicy,
542 IN EFI_HANDLE ParentImageHandle,
543 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
544 IN VOID *SourceBuffer OPTIONAL,
545 IN UINTN SourceSize,
546 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
547 IN OUT UINTN *NumberOfPages OPTIONAL,
548 OUT EFI_HANDLE *ImageHandle,
549 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
550 IN UINT32 Attribute
551 )
552 /*++
553
554 Routine Description:
555
556 Loads an EFI image into memory and returns a handle to the image.
557
558 Arguments:
559
560 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
561 and that the boot manager is attempting to load FilePath as a boot selection.
562 ParentImageHandle - The caller's image handle.
563 FilePath - The specific file path from which the image is loaded.
564 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
565 the image to be loaded.
566 SourceSize - The size in bytes of SourceBuffer.
567 DstBuffer - The buffer to store the image
568 NumberOfPages - If not NULL, a pointer to the image's page number, if this number
569 is not enough, return EFI_BUFFER_TOO_SMALL and this parameter contain
570 the required number.
571 ImageHandle - Pointer to the returned image handle that is created when the image
572 is successfully loaded.
573 EntryPoint - A pointer to the entry point
574 Attribute - The bit mask of attributes to set for the load PE image
575
576 Returns:
577
578 EFI_SUCCESS - The image was loaded into memory.
579 EFI_NOT_FOUND - The FilePath was not found.
580 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
581 EFI_BUFFER_TOO_SMALL - The buffer is too small
582 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
583 parsed to locate the proper protocol for loading the file.
584 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
585 --*/
586 {
587 LOADED_IMAGE_PRIVATE_DATA *Image;
588 LOADED_IMAGE_PRIVATE_DATA *ParentImage;
589 IMAGE_FILE_HANDLE FHand;
590 EFI_STATUS Status;
591 EFI_STATUS SecurityStatus;
592 EFI_HANDLE DeviceHandle;
593 UINT32 AuthenticationStatus;
594 EFI_DEVICE_PATH_PROTOCOL *OriginalFilePath;
595 EFI_DEVICE_PATH_PROTOCOL *HandleFilePath;
596 UINTN FilePathSize;
597
598
599 ASSERT (gEfiCurrentTpl < EFI_TPL_NOTIFY);
600 ParentImage = NULL;
601
602 //
603 // The caller must pass in a valid ParentImageHandle
604 //
605 if (ImageHandle == NULL || ParentImageHandle == NULL) {
606 return EFI_INVALID_PARAMETER;
607 }
608
609 ParentImage = CoreLoadedImageInfo (ParentImageHandle);
610 if (ParentImage == NULL) {
611 DEBUG((EFI_D_LOAD|EFI_D_ERROR, "LoadImageEx: Parent handle not an image handle\n"));
612 return EFI_INVALID_PARAMETER;
613 }
614
615 //
616 // Get simple read access to the source file
617 //
618 OriginalFilePath = FilePath;
619 Status = CoreOpenImageFile (
620 BootPolicy,
621 SourceBuffer,
622 SourceSize,
623 FilePath,
624 &DeviceHandle,
625 &FHand,
626 &AuthenticationStatus
627 );
628 if (Status == EFI_ALREADY_STARTED) {
629 Image = NULL;
630 goto Done;
631 } else if (EFI_ERROR (Status)) {
632 return Status;
633 }
634
635 //
636 // Verify the Authentication Status through the Security Architectural Protocol
637 //
638 if ((gSecurity != NULL) && (OriginalFilePath != NULL)) {
639 SecurityStatus = gSecurity->FileAuthenticationState (
640 gSecurity,
641 AuthenticationStatus,
642 OriginalFilePath
643 );
644 if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {
645 Status = SecurityStatus;
646 Image = NULL;
647 goto Done;
648 }
649 }
650
651
652 //
653 // Allocate a new image structure
654 //
655 Image = CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA));
656 if (Image == NULL) {
657 return EFI_OUT_OF_RESOURCES;
658 }
659
660 //
661 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
662 //
663 Status = CoreHandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath);
664 if (!EFI_ERROR (Status)) {
665 FilePathSize = CoreDevicePathSize (HandleFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
666 FilePath = (EFI_DEVICE_PATH_PROTOCOL *) ( ((UINT8 *)FilePath) + FilePathSize );
667 }
668
669 //
670 // Initialize the fields for an internal driver
671 //
672 Image->Signature = LOADED_IMAGE_PRIVATE_DATA_SIGNATURE;
673 Image->Info.SystemTable = gST;
674 Image->Info.DeviceHandle = DeviceHandle;
675 Image->Info.Revision = EFI_LOADED_IMAGE_INFORMATION_REVISION;
676 Image->Info.FilePath = CoreDuplicateDevicePath (FilePath);
677 Image->Info.ParentHandle = ParentImageHandle;
678
679 if (NumberOfPages != NULL) {
680 Image->NumberOfPages = *NumberOfPages ;
681 } else {
682 Image->NumberOfPages = 0 ;
683 }
684
685 //
686 // Install the protocol interfaces for this image
687 // don't fire notifications yet
688 //
689 Status = CoreInstallProtocolInterfaceNotify (
690 &Image->Handle,
691 &gEfiLoadedImageProtocolGuid,
692 EFI_NATIVE_INTERFACE,
693 &Image->Info,
694 FALSE
695 );
696 if (EFI_ERROR (Status)) {
697 goto Done;
698 }
699
700 //
701 // Load the image. If EntryPoint is Null, it will not be set.
702 //
703 Status = CoreLoadPeImage (&FHand, Image, DstBuffer, EntryPoint, Attribute);
704 if (EFI_ERROR (Status)) {
705 if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_OUT_OF_RESOURCES)) {
706 if (NumberOfPages != NULL) {
707 *NumberOfPages = Image->NumberOfPages;
708 }
709 }
710 goto Done;
711 }
712
713 //
714 // Register the image in the Debug Image Info Table if the attribute is set
715 //
716 if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION) {
717 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, &Image->Info, Image->Handle);
718 }
719
720 //
721 //Reinstall loaded image protocol to fire any notifications
722 //
723 Status = CoreReinstallProtocolInterface (
724 Image->Handle,
725 &gEfiLoadedImageProtocolGuid,
726 &Image->Info,
727 &Image->Info
728 );
729 if (EFI_ERROR (Status)) {
730 goto Done;
731 }
732
733
734 //
735 // Success. Return the image handle
736 //
737 *ImageHandle = Image->Handle;
738
739 Done:
740 //
741 // All done accessing the source file
742 // If we allocated the Source buffer, free it
743 //
744 if (FHand.FreeBuffer) {
745 CoreFreePool (FHand.Source);
746 }
747
748 //
749 // There was an error. If there's an Image structure, free it
750 //
751 if (EFI_ERROR (Status)) {
752 if (Image != NULL) {
753 CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer == 0));
754 *ImageHandle = NULL;
755 }
756 }
757
758 return Status;
759 }
760
761
762
763 EFI_STATUS
764 EFIAPI
765 CoreLoadImage (
766 IN BOOLEAN BootPolicy,
767 IN EFI_HANDLE ParentImageHandle,
768 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
769 IN VOID *SourceBuffer OPTIONAL,
770 IN UINTN SourceSize,
771 OUT EFI_HANDLE *ImageHandle
772 )
773 /*++
774
775 Routine Description:
776
777 Loads an EFI image into memory and returns a handle to the image.
778
779 Arguments:
780
781 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
782 and that the boot manager is attempting to load FilePath as a boot selection.
783 ParentImageHandle - The caller's image handle.
784 FilePath - The specific file path from which the image is loaded.
785 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
786 the image to be loaded.
787 SourceSize - The size in bytes of SourceBuffer.
788 ImageHandle - Pointer to the returned image handle that is created when the image
789 is successfully loaded.
790
791 Returns:
792
793 EFI_SUCCESS - The image was loaded into memory.
794 EFI_NOT_FOUND - The FilePath was not found.
795 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
796 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
797 parsed to locate the proper protocol for loading the file.
798 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
799 --*/
800 {
801 EFI_STATUS Status;
802
803 PERF_START (NULL, "LoadImage", NULL, 0);
804
805 Status = CoreLoadImageCommon (
806 BootPolicy,
807 ParentImageHandle,
808 FilePath,
809 SourceBuffer,
810 SourceSize,
811 (EFI_PHYSICAL_ADDRESS)NULL,
812 NULL,
813 ImageHandle,
814 NULL,
815 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION | EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
816 );
817
818 PERF_END (NULL, "LoadImage", NULL, 0);
819
820 return Status;
821 }
822
823
824 EFI_STATUS
825 EFIAPI
826 CoreLoadImageEx (
827 IN EFI_PE32_IMAGE_PROTOCOL *This,
828 IN EFI_HANDLE ParentImageHandle,
829 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
830 IN VOID *SourceBuffer OPTIONAL,
831 IN UINTN SourceSize,
832 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
833 OUT UINTN *NumberOfPages OPTIONAL,
834 OUT EFI_HANDLE *ImageHandle,
835 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
836 IN UINT32 Attribute
837 )
838 /*++
839
840 Routine Description:
841
842 Loads an EFI image into memory and returns a handle to the image with extended parameters.
843
844 Arguments:
845
846 This - Calling context
847 ParentImageHandle - The caller's image handle.
848 FilePath - The specific file path from which the image is loaded.
849 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
850 the image to be loaded.
851 SourceSize - The size in bytes of SourceBuffer.
852 DstBuffer - The buffer to store the image.
853 NumberOfPages - For input, specifies the space size of the image by caller if not NULL.
854 For output, specifies the actual space size needed.
855 ImageHandle - Image handle for output.
856 EntryPoint - Image entry point for output.
857 Attribute - The bit mask of attributes to set for the load PE image.
858
859 Returns:
860
861 EFI_SUCCESS - The image was loaded into memory.
862 EFI_NOT_FOUND - The FilePath was not found.
863 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
864 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
865 parsed to locate the proper protocol for loading the file.
866 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
867 --*/
868 {
869 return CoreLoadImageCommon (
870 TRUE,
871 ParentImageHandle,
872 FilePath,
873 SourceBuffer,
874 SourceSize,
875 DstBuffer,
876 NumberOfPages,
877 ImageHandle,
878 EntryPoint,
879 Attribute
880 );
881 }
882
883
884
885
886 EFI_STATUS
887 EFIAPI
888 CoreStartImage (
889 IN EFI_HANDLE ImageHandle,
890 OUT UINTN *ExitDataSize,
891 OUT CHAR16 **ExitData OPTIONAL
892 )
893 /*++
894
895 Routine Description:
896
897 Transfer control to a loaded image's entry point.
898
899 Arguments:
900
901 ImageHandle - Handle of image to be started.
902
903 ExitDataSize - Pointer of the size to ExitData
904
905 ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated
906 Unicode string, optionally followed by additional binary data. The string
907 is a description that the caller may use to further indicate the reason for
908 the image¡¯s exit.
909
910 Returns:
911
912 EFI_INVALID_PARAMETER - Invalid parameter
913
914 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
915
916 EFI_SUCCESS - Successfully transfer control to the image's entry point.
917
918 --*/
919 {
920 EFI_STATUS Status;
921 LOADED_IMAGE_PRIVATE_DATA *Image;
922 LOADED_IMAGE_PRIVATE_DATA *LastImage;
923 UINT64 HandleDatabaseKey;
924 UINTN SetJumpFlag;
925
926 Image = CoreLoadedImageInfo (ImageHandle);
927 if (Image == NULL_HANDLE || Image->Started) {
928 return EFI_INVALID_PARAMETER;
929 }
930
931 //
932 // Don't profile Objects or invalid start requests
933 //
934 PERF_START (ImageHandle, START_IMAGE_TOK, NULL, 0);
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_BEGIN ();
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 DEBUG_CODE_END ();
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_BEGIN ();
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 DEBUG_CODE_END ();
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 }