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