]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Core/Dxe/Image/Image.c
I fixed following bugs in EDKII.
[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 SecurityStatus = EFI_SUCCESS;
599
600 ASSERT (gEfiCurrentTpl < EFI_TPL_NOTIFY);
601 ParentImage = NULL;
602
603 //
604 // The caller must pass in a valid ParentImageHandle
605 //
606 if (ImageHandle == NULL || ParentImageHandle == NULL) {
607 return EFI_INVALID_PARAMETER;
608 }
609
610 ParentImage = CoreLoadedImageInfo (ParentImageHandle);
611 if (ParentImage == NULL) {
612 DEBUG((EFI_D_LOAD|EFI_D_ERROR, "LoadImageEx: Parent handle not an image handle\n"));
613 return EFI_INVALID_PARAMETER;
614 }
615
616 //
617 // Get simple read access to the source file
618 //
619 OriginalFilePath = FilePath;
620 Status = CoreOpenImageFile (
621 BootPolicy,
622 SourceBuffer,
623 SourceSize,
624 FilePath,
625 &DeviceHandle,
626 &FHand,
627 &AuthenticationStatus
628 );
629 if (Status == EFI_ALREADY_STARTED) {
630 Image = NULL;
631 goto Done;
632 } else if (EFI_ERROR (Status)) {
633 return Status;
634 }
635
636 //
637 // Verify the Authentication Status through the Security Architectural Protocol
638 //
639 if ((gSecurity != NULL) && (OriginalFilePath != NULL)) {
640 SecurityStatus = gSecurity->FileAuthenticationState (
641 gSecurity,
642 AuthenticationStatus,
643 OriginalFilePath
644 );
645 if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {
646 Status = SecurityStatus;
647 Image = NULL;
648 goto Done;
649 }
650 }
651
652
653 //
654 // Allocate a new image structure
655 //
656 Image = CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA));
657 if (Image == NULL) {
658 return EFI_OUT_OF_RESOURCES;
659 }
660
661 //
662 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
663 //
664 Status = CoreHandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath);
665 if (!EFI_ERROR (Status)) {
666 FilePathSize = CoreDevicePathSize (HandleFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
667 FilePath = (EFI_DEVICE_PATH_PROTOCOL *) ( ((UINT8 *)FilePath) + FilePathSize );
668 }
669
670 //
671 // Initialize the fields for an internal driver
672 //
673 Image->Signature = LOADED_IMAGE_PRIVATE_DATA_SIGNATURE;
674 Image->Info.SystemTable = gST;
675 Image->Info.DeviceHandle = DeviceHandle;
676 Image->Info.Revision = EFI_LOADED_IMAGE_INFORMATION_REVISION;
677 Image->Info.FilePath = CoreDuplicateDevicePath (FilePath);
678 Image->Info.ParentHandle = ParentImageHandle;
679
680 if (NumberOfPages != NULL) {
681 Image->NumberOfPages = *NumberOfPages ;
682 } else {
683 Image->NumberOfPages = 0 ;
684 }
685
686 //
687 // Install the protocol interfaces for this image
688 // don't fire notifications yet
689 //
690 Status = CoreInstallProtocolInterfaceNotify (
691 &Image->Handle,
692 &gEfiLoadedImageProtocolGuid,
693 EFI_NATIVE_INTERFACE,
694 &Image->Info,
695 FALSE
696 );
697 if (EFI_ERROR (Status)) {
698 goto Done;
699 }
700
701 //
702 // Load the image. If EntryPoint is Null, it will not be set.
703 //
704 Status = CoreLoadPeImage (&FHand, Image, DstBuffer, EntryPoint, Attribute);
705 if (EFI_ERROR (Status)) {
706 if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_OUT_OF_RESOURCES)) {
707 if (NumberOfPages != NULL) {
708 *NumberOfPages = Image->NumberOfPages;
709 }
710 }
711 goto Done;
712 }
713
714 //
715 // Register the image in the Debug Image Info Table if the attribute is set
716 //
717 if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION) {
718 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, &Image->Info, Image->Handle);
719 }
720
721 //
722 //Reinstall loaded image protocol to fire any notifications
723 //
724 Status = CoreReinstallProtocolInterface (
725 Image->Handle,
726 &gEfiLoadedImageProtocolGuid,
727 &Image->Info,
728 &Image->Info
729 );
730 if (EFI_ERROR (Status)) {
731 goto Done;
732 }
733
734
735 //
736 // Success. Return the image handle
737 //
738 *ImageHandle = Image->Handle;
739
740 Done:
741 //
742 // All done accessing the source file
743 // If we allocated the Source buffer, free it
744 //
745 if (FHand.FreeBuffer) {
746 CoreFreePool (FHand.Source);
747 }
748
749 //
750 // There was an error. If there's an Image structure, free it
751 //
752 if (EFI_ERROR (Status)) {
753 if (Image != NULL) {
754 CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer == 0));
755 *ImageHandle = NULL;
756 }
757 } else if (EFI_ERROR (SecurityStatus)) {
758 Status = SecurityStatus;
759 }
760
761 return Status;
762 }
763
764
765
766 EFI_STATUS
767 EFIAPI
768 CoreLoadImage (
769 IN BOOLEAN BootPolicy,
770 IN EFI_HANDLE ParentImageHandle,
771 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
772 IN VOID *SourceBuffer OPTIONAL,
773 IN UINTN SourceSize,
774 OUT EFI_HANDLE *ImageHandle
775 )
776 /*++
777
778 Routine Description:
779
780 Loads an EFI image into memory and returns a handle to the image.
781
782 Arguments:
783
784 BootPolicy - If TRUE, indicates that the request originates from the boot manager,
785 and that the boot manager is attempting to load FilePath as a boot selection.
786 ParentImageHandle - The caller's image handle.
787 FilePath - The specific file path from which the image is loaded.
788 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
789 the image to be loaded.
790 SourceSize - The size in bytes of SourceBuffer.
791 ImageHandle - Pointer to the returned image handle that is created when the image
792 is successfully loaded.
793
794 Returns:
795
796 EFI_SUCCESS - The image was loaded into memory.
797 EFI_NOT_FOUND - The FilePath was not found.
798 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
799 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
800 parsed to locate the proper protocol for loading the file.
801 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
802 --*/
803 {
804 EFI_STATUS Status;
805
806 PERF_START (NULL, "LoadImage", NULL, 0);
807
808 Status = CoreLoadImageCommon (
809 BootPolicy,
810 ParentImageHandle,
811 FilePath,
812 SourceBuffer,
813 SourceSize,
814 (EFI_PHYSICAL_ADDRESS)NULL,
815 NULL,
816 ImageHandle,
817 NULL,
818 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION | EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
819 );
820
821 PERF_END (NULL, "LoadImage", NULL, 0);
822
823 return Status;
824 }
825
826
827 EFI_STATUS
828 EFIAPI
829 CoreLoadImageEx (
830 IN EFI_PE32_IMAGE_PROTOCOL *This,
831 IN EFI_HANDLE ParentImageHandle,
832 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
833 IN VOID *SourceBuffer OPTIONAL,
834 IN UINTN SourceSize,
835 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
836 OUT UINTN *NumberOfPages OPTIONAL,
837 OUT EFI_HANDLE *ImageHandle,
838 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
839 IN UINT32 Attribute
840 )
841 /*++
842
843 Routine Description:
844
845 Loads an EFI image into memory and returns a handle to the image with extended parameters.
846
847 Arguments:
848
849 This - Calling context
850 ParentImageHandle - The caller's image handle.
851 FilePath - The specific file path from which the image is loaded.
852 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
853 the image to be loaded.
854 SourceSize - The size in bytes of SourceBuffer.
855 DstBuffer - The buffer to store the image.
856 NumberOfPages - For input, specifies the space size of the image by caller if not NULL.
857 For output, specifies the actual space size needed.
858 ImageHandle - Image handle for output.
859 EntryPoint - Image entry point for output.
860 Attribute - The bit mask of attributes to set for the load PE image.
861
862 Returns:
863
864 EFI_SUCCESS - The image was loaded into memory.
865 EFI_NOT_FOUND - The FilePath was not found.
866 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
867 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
868 parsed to locate the proper protocol for loading the file.
869 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
870 --*/
871 {
872 return CoreLoadImageCommon (
873 TRUE,
874 ParentImageHandle,
875 FilePath,
876 SourceBuffer,
877 SourceSize,
878 DstBuffer,
879 NumberOfPages,
880 ImageHandle,
881 EntryPoint,
882 Attribute
883 );
884 }
885
886
887
888
889 EFI_STATUS
890 EFIAPI
891 CoreStartImage (
892 IN EFI_HANDLE ImageHandle,
893 OUT UINTN *ExitDataSize,
894 OUT CHAR16 **ExitData OPTIONAL
895 )
896 /*++
897
898 Routine Description:
899
900 Transfer control to a loaded image's entry point.
901
902 Arguments:
903
904 ImageHandle - Handle of image to be started.
905
906 ExitDataSize - Pointer of the size to ExitData
907
908 ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated
909 Unicode string, optionally followed by additional binary data. The string
910 is a description that the caller may use to further indicate the reason for
911 the image's exit.
912
913 Returns:
914
915 EFI_INVALID_PARAMETER - Invalid parameter
916
917 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
918
919 EFI_SUCCESS - Successfully transfer control to the image's entry point.
920
921 --*/
922 {
923 EFI_STATUS Status;
924 LOADED_IMAGE_PRIVATE_DATA *Image;
925 LOADED_IMAGE_PRIVATE_DATA *LastImage;
926 UINT64 HandleDatabaseKey;
927 UINTN SetJumpFlag;
928
929 Image = CoreLoadedImageInfo (ImageHandle);
930 if (Image == NULL_HANDLE || Image->Started) {
931 return EFI_INVALID_PARAMETER;
932 }
933
934 //
935 // Don't profile Objects or invalid start requests
936 //
937 PERF_START (ImageHandle, START_IMAGE_TOK, NULL, 0);
938
939
940 //
941 // Push the current start image context, and
942 // link the current image to the head. This is the
943 // only image that can call Exit()
944 //
945 HandleDatabaseKey = CoreGetHandleDatabaseKey ();
946 LastImage = mCurrentImage;
947 mCurrentImage = Image;
948 Image->Tpl = gEfiCurrentTpl;
949
950 //
951 // Set long jump for Exit() support
952 //
953 Image->JumpContext = CoreAllocateBootServicesPool (sizeof (*Image->JumpContext));
954 if (Image->JumpContext == NULL) {
955 PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);
956 return EFI_OUT_OF_RESOURCES;
957 }
958
959 SetJumpFlag = SetJump (Image->JumpContext);
960 //
961 // The initial call to SetJump() must always return 0.
962 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
963 //
964 if (!SetJumpFlag) {
965 //
966 // Call the image's entry point
967 //
968 Image->Started = TRUE;
969 Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable);
970
971 //
972 // Add some debug information if the image returned with error.
973 // This make the user aware and check if the driver image have already released
974 // all the resource in this situation.
975 //
976 DEBUG_CODE_BEGIN ();
977 if (EFI_ERROR (Image->Status)) {
978 DEBUG ((EFI_D_ERROR, "Error: Image at %08X start failed: %x\n", Image->Info.ImageBase, Image->Status));
979 }
980 DEBUG_CODE_END ();
981
982 //
983 // If the image returns, exit it through Exit()
984 //
985 CoreExit (ImageHandle, Image->Status, 0, NULL);
986 }
987
988 //
989 // Image has completed. Verify the tpl is the same
990 //
991 ASSERT (Image->Tpl == gEfiCurrentTpl);
992 CoreRestoreTpl (Image->Tpl);
993
994 CoreFreePool (Image->JumpContext);
995
996 //
997 // Pop the current start image context
998 //
999 mCurrentImage = LastImage;
1000
1001 //
1002 // Go connect any handles that were created or modified while the image executed.
1003 //
1004 CoreConnectHandlesByKey (HandleDatabaseKey);
1005
1006 //
1007 // Handle the image's returned ExitData
1008 //
1009 DEBUG_CODE_BEGIN ();
1010 if (Image->ExitDataSize != 0 || Image->ExitData != NULL) {
1011
1012 DEBUG (
1013 (EFI_D_LOAD,
1014 "StartImage: ExitDataSize %d, ExitData %x",
1015 Image->ExitDataSize,
1016 Image->ExitData)
1017 );
1018 if (Image->ExitData != NULL) {
1019 DEBUG ((EFI_D_LOAD, " (%hs)", Image->ExitData));
1020 }
1021 DEBUG ((EFI_D_LOAD, "\n"));
1022 }
1023 DEBUG_CODE_END ();
1024
1025 //
1026 // Return the exit data to the caller
1027 //
1028 if (ExitData != NULL && ExitDataSize != NULL) {
1029 *ExitDataSize = Image->ExitDataSize;
1030 *ExitData = Image->ExitData;
1031 } else {
1032 //
1033 // Caller doesn't want the exit data, free it
1034 //
1035 CoreFreePool (Image->ExitData);
1036 Image->ExitData = NULL;
1037 }
1038
1039 //
1040 // Save the Status because Image will get destroyed if it is unloaded.
1041 //
1042 Status = Image->Status;
1043
1044 //
1045 // If the image returned an error, or if the image is an application
1046 // unload it
1047 //
1048 if (EFI_ERROR (Image->Status) || Image->Type == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
1049 CoreUnloadAndCloseImage (Image, TRUE);
1050 }
1051
1052 //
1053 // Done
1054 //
1055 PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);
1056 return Status;
1057 }
1058
1059
1060 VOID
1061 CoreUnloadAndCloseImage (
1062 IN LOADED_IMAGE_PRIVATE_DATA *Image,
1063 IN BOOLEAN FreePage
1064 )
1065 /*++
1066
1067 Routine Description:
1068
1069 Unloads EFI image from memory.
1070
1071 Arguments:
1072
1073 Image - EFI image
1074 FreePage - Free allocated pages
1075
1076 Returns:
1077
1078 None
1079
1080 --*/
1081 {
1082 EFI_STATUS Status;
1083 UINTN HandleCount;
1084 EFI_HANDLE *HandleBuffer;
1085 UINTN HandleIndex;
1086 EFI_GUID **ProtocolGuidArray;
1087 UINTN ArrayCount;
1088 UINTN ProtocolIndex;
1089 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;
1090 UINTN OpenInfoCount;
1091 UINTN OpenInfoIndex;
1092
1093 if (Image->Ebc != NULL) {
1094 //
1095 // If EBC protocol exists we must perform cleanups for this image.
1096 //
1097 Image->Ebc->UnloadImage (Image->Ebc, Image->Handle);
1098 }
1099
1100 //
1101 // Unload image, free Image->ImageContext->ModHandle
1102 //
1103 gEfiPeiPeCoffLoader->UnloadImage (gEfiPeiPeCoffLoader, &Image->ImageContext);
1104
1105 //
1106 // Free our references to the image handle
1107 //
1108 if (Image->Handle != NULL_HANDLE) {
1109
1110 Status = CoreLocateHandleBuffer (
1111 AllHandles,
1112 NULL,
1113 NULL,
1114 &HandleCount,
1115 &HandleBuffer
1116 );
1117 if (!EFI_ERROR (Status)) {
1118 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
1119 Status = CoreProtocolsPerHandle (
1120 HandleBuffer[HandleIndex],
1121 &ProtocolGuidArray,
1122 &ArrayCount
1123 );
1124 if (!EFI_ERROR (Status)) {
1125 for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
1126 Status = CoreOpenProtocolInformation (
1127 HandleBuffer[HandleIndex],
1128 ProtocolGuidArray[ProtocolIndex],
1129 &OpenInfo,
1130 &OpenInfoCount
1131 );
1132 if (!EFI_ERROR (Status)) {
1133 for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
1134 if (OpenInfo[OpenInfoIndex].AgentHandle == Image->Handle) {
1135 Status = CoreCloseProtocol (
1136 HandleBuffer[HandleIndex],
1137 ProtocolGuidArray[ProtocolIndex],
1138 Image->Handle,
1139 OpenInfo[OpenInfoIndex].ControllerHandle
1140 );
1141 }
1142 }
1143 if (OpenInfo != NULL) {
1144 CoreFreePool(OpenInfo);
1145 }
1146 }
1147 }
1148 if (ProtocolGuidArray != NULL) {
1149 CoreFreePool(ProtocolGuidArray);
1150 }
1151 }
1152 }
1153 if (HandleBuffer != NULL) {
1154 CoreFreePool (HandleBuffer);
1155 }
1156 }
1157
1158 CoreRemoveDebugImageInfoEntry (Image->Handle);
1159
1160 Status = CoreUninstallProtocolInterface (
1161 Image->Handle,
1162 &gEfiLoadedImageProtocolGuid,
1163 &Image->Info
1164 );
1165 }
1166
1167 if (Image->RuntimeFixupValid) {
1168 //
1169 // Remove the Image from the Runtime Image list as we are about to Free it!
1170 //
1171 RemoveEntryList (&Image->Link);
1172 }
1173
1174 //
1175 // Free the Image from memory
1176 //
1177 if ((Image->ImageBasePage != 0) && FreePage) {
1178 CoreFreePages (Image->ImageBasePage, Image->NumberOfPages);
1179 }
1180
1181 //
1182 // Done with the Image structure
1183 //
1184 if (Image->Info.FilePath != NULL) {
1185 CoreFreePool (Image->Info.FilePath);
1186 }
1187
1188 if (Image->FixupData != NULL) {
1189 CoreFreePool (Image->FixupData);
1190 }
1191
1192 CoreFreePool (Image);
1193 }
1194
1195
1196
1197 EFI_STATUS
1198 EFIAPI
1199 CoreExit (
1200 IN EFI_HANDLE ImageHandle,
1201 IN EFI_STATUS Status,
1202 IN UINTN ExitDataSize,
1203 IN CHAR16 *ExitData OPTIONAL
1204 )
1205 /*++
1206
1207 Routine Description:
1208
1209 Terminates the currently loaded EFI image and returns control to boot services.
1210
1211 Arguments:
1212
1213 ImageHandle - Handle that identifies the image. This parameter is passed to the image
1214 on entry.
1215 Status - The image's exit code.
1216 ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is
1217 EFI_SUCCESS.
1218 ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string,
1219 optionally followed by additional binary data. The string is a
1220 description that the caller may use to further indicate the reason for
1221 the image's exit.
1222
1223 Returns:
1224
1225 EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image.
1226
1227 EFI_SUCCESS - Successfully terminates the currently loaded EFI image.
1228
1229 EFI_ACCESS_DENIED - Should never reach there.
1230
1231 EFI_OUT_OF_RESOURCES - Could not allocate pool
1232
1233 --*/
1234 {
1235 LOADED_IMAGE_PRIVATE_DATA *Image;
1236
1237 Image = CoreLoadedImageInfo (ImageHandle);
1238 if (Image == NULL_HANDLE) {
1239 return EFI_INVALID_PARAMETER;
1240 }
1241
1242 if (!Image->Started) {
1243 //
1244 // The image has not been started so just free its resources
1245 //
1246 CoreUnloadAndCloseImage (Image, TRUE);
1247 return EFI_SUCCESS;
1248 }
1249
1250 //
1251 // Image has been started, verify this image can exit
1252 //
1253 if (Image != mCurrentImage) {
1254 DEBUG ((EFI_D_LOAD|EFI_D_ERROR, "Exit: Image is not exitable image\n"));
1255 return EFI_INVALID_PARAMETER;
1256 }
1257
1258 //
1259 // Set status
1260 //
1261 Image->Status = Status;
1262
1263 //
1264 // If there's ExitData info, move it
1265 //
1266 if (ExitData != NULL) {
1267 Image->ExitDataSize = ExitDataSize;
1268 Image->ExitData = CoreAllocateBootServicesPool (Image->ExitDataSize);
1269 if (Image->ExitData == NULL) {
1270 return EFI_OUT_OF_RESOURCES;
1271 }
1272 CopyMem (Image->ExitData, ExitData, Image->ExitDataSize);
1273 }
1274
1275 //
1276 // return to StartImage
1277 //
1278 LongJump (Image->JumpContext, (UINTN)-1);
1279
1280 //
1281 // If we return from LongJump, then it is an error
1282 //
1283 ASSERT (FALSE);
1284 return EFI_ACCESS_DENIED;
1285 }
1286
1287
1288
1289 EFI_STATUS
1290 EFIAPI
1291 CoreUnloadImage (
1292 IN EFI_HANDLE ImageHandle
1293 )
1294 /*++
1295
1296 Routine Description:
1297
1298 Unloads an image.
1299
1300 Arguments:
1301
1302 ImageHandle - Handle that identifies the image to be unloaded.
1303
1304 Returns:
1305
1306 EFI_SUCCESS - The image has been unloaded.
1307 EFI_UNSUPPORTED - The image has been sarted, and does not support unload.
1308 EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle.
1309
1310 --*/
1311 {
1312 EFI_STATUS Status;
1313 LOADED_IMAGE_PRIVATE_DATA *Image;
1314
1315 Image = CoreLoadedImageInfo (ImageHandle);
1316 if (Image == NULL ) {
1317 //
1318 // The image handle is not valid
1319 //
1320 return EFI_INVALID_PARAMETER;
1321 }
1322
1323 if (Image->Started) {
1324 //
1325 // The image has been started, request it to unload.
1326 //
1327 Status = EFI_UNSUPPORTED;
1328 if (Image->Info.Unload != NULL) {
1329 Status = Image->Info.Unload (ImageHandle);
1330 }
1331
1332 } else {
1333 //
1334 // This Image hasn't been started, thus it can be unloaded
1335 //
1336 Status = EFI_SUCCESS;
1337 }
1338
1339
1340 if (!EFI_ERROR (Status)) {
1341 //
1342 // if the Image was not started or Unloaded O.K. then clean up
1343 //
1344 CoreUnloadAndCloseImage (Image, TRUE);
1345 }
1346
1347 return Status;
1348 }
1349
1350
1351 EFI_STATUS
1352 EFIAPI
1353 CoreUnloadImageEx (
1354 IN EFI_PE32_IMAGE_PROTOCOL *This,
1355 IN EFI_HANDLE ImageHandle
1356 )
1357 /*++
1358
1359 Routine Description:
1360
1361 Unload the specified image.
1362
1363 Arguments:
1364
1365 This - Indicates the calling context.
1366
1367 ImageHandle - The specified image handle.
1368
1369 Returns:
1370
1371 EFI_INVALID_PARAMETER - Image handle is NULL.
1372
1373 EFI_UNSUPPORTED - Attempt to unload an unsupported image.
1374
1375 EFI_SUCCESS - Image successfully unloaded.
1376
1377 --*/
1378 {
1379 return CoreUnloadImage (ImageHandle);
1380 }