]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/Image/Image.c
MdeModulePkg/DxeCore: invoke the emulator protocol for foreign images
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Image / Image.c
1 /** @file
2 Core image handling services to load and unload PeImage.
3
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "DxeMain.h"
10 #include "Image.h"
11
12 //
13 // Module Globals
14 //
15 LOADED_IMAGE_PRIVATE_DATA *mCurrentImage = NULL;
16
17 LOAD_PE32_IMAGE_PRIVATE_DATA mLoadPe32PrivateData = {
18 LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE,
19 NULL,
20 {
21 CoreLoadImageEx,
22 CoreUnloadImageEx
23 }
24 };
25
26 typedef struct {
27 LIST_ENTRY Link;
28 EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL *Emulator;
29 UINT16 MachineType;
30 } EMULATOR_ENTRY;
31
32 STATIC LIST_ENTRY mAvailableEmulators;
33 STATIC EFI_EVENT mPeCoffEmuProtocolRegistrationEvent;
34 STATIC VOID *mPeCoffEmuProtocolNotifyRegistration;
35
36 //
37 // This code is needed to build the Image handle for the DXE Core
38 //
39 LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage = {
40 LOADED_IMAGE_PRIVATE_DATA_SIGNATURE, // Signature
41 NULL, // Image handle
42 EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, // Image type
43 TRUE, // If entrypoint has been called
44 NULL, // EntryPoint
45 {
46 EFI_LOADED_IMAGE_INFORMATION_REVISION, // Revision
47 NULL, // Parent handle
48 NULL, // System handle
49
50 NULL, // Device handle
51 NULL, // File path
52 NULL, // Reserved
53
54 0, // LoadOptionsSize
55 NULL, // LoadOptions
56
57 NULL, // ImageBase
58 0, // ImageSize
59 EfiBootServicesCode, // ImageCodeType
60 EfiBootServicesData // ImageDataType
61 },
62 (EFI_PHYSICAL_ADDRESS)0, // ImageBasePage
63 0, // NumberOfPages
64 NULL, // FixupData
65 0, // Tpl
66 EFI_SUCCESS, // Status
67 0, // ExitDataSize
68 NULL, // ExitData
69 NULL, // JumpBuffer
70 NULL, // JumpContext
71 0, // Machine
72 NULL, // Ebc
73 NULL, // PeCoffEmu
74 NULL, // RuntimeData
75 NULL // LoadedImageDevicePath
76 };
77 //
78 // The field is define for Loading modules at fixed address feature to tracker the PEI code
79 // memory range usage. It is a bit mapped array in which every bit indicates the correspoding memory page
80 // available or not.
81 //
82 GLOBAL_REMOVE_IF_UNREFERENCED UINT64 *mDxeCodeMemoryRangeUsageBitMap=NULL;
83
84 typedef struct {
85 UINT16 MachineType;
86 CHAR16 *MachineTypeName;
87 } MACHINE_TYPE_INFO;
88
89 //
90 // EBC machine is not listed in this table, because EBC is in the default supported scopes of other machine type.
91 //
92 GLOBAL_REMOVE_IF_UNREFERENCED MACHINE_TYPE_INFO mMachineTypeInfo[] = {
93 {EFI_IMAGE_MACHINE_IA32, L"IA32"},
94 {EFI_IMAGE_MACHINE_IA64, L"IA64"},
95 {EFI_IMAGE_MACHINE_X64, L"X64"},
96 {EFI_IMAGE_MACHINE_ARMTHUMB_MIXED, L"ARM"},
97 {EFI_IMAGE_MACHINE_AARCH64, L"AARCH64"}
98 };
99
100 UINT16 mDxeCoreImageMachineType = 0;
101
102 /**
103 Return machine type name.
104
105 @param MachineType The machine type
106
107 @return machine type name
108 **/
109 CHAR16 *
110 GetMachineTypeName (
111 UINT16 MachineType
112 )
113 {
114 UINTN Index;
115
116 for (Index = 0; Index < sizeof(mMachineTypeInfo)/sizeof(mMachineTypeInfo[0]); Index++) {
117 if (mMachineTypeInfo[Index].MachineType == MachineType) {
118 return mMachineTypeInfo[Index].MachineTypeName;
119 }
120 }
121
122 return L"<Unknown>";
123 }
124
125 /**
126 Notification event handler registered by CoreInitializeImageServices () to
127 keep track of which PE/COFF image emulators are available.
128
129 @param Event The Event that is being processed, not used.
130 @param Context Event Context, not used.
131
132 **/
133 STATIC
134 VOID
135 EFIAPI
136 PeCoffEmuProtocolNotify (
137 IN EFI_EVENT Event,
138 IN VOID *Context
139 )
140 {
141 EFI_STATUS Status;
142 UINTN BufferSize;
143 EFI_HANDLE EmuHandle;
144 EMULATOR_ENTRY *Entry;
145
146 EmuHandle = NULL;
147
148 while (TRUE) {
149 BufferSize = sizeof (EmuHandle);
150 Status = CoreLocateHandle (
151 ByRegisterNotify,
152 NULL,
153 mPeCoffEmuProtocolNotifyRegistration,
154 &BufferSize,
155 &EmuHandle
156 );
157 if (EFI_ERROR (Status)) {
158 //
159 // If no more notification events exit
160 //
161 return;
162 }
163
164 Entry = AllocateZeroPool (sizeof (*Entry));
165 ASSERT (Entry != NULL);
166
167 Status = CoreHandleProtocol (
168 EmuHandle,
169 &gEdkiiPeCoffImageEmulatorProtocolGuid,
170 (VOID **)&Entry->Emulator
171 );
172 ASSERT_EFI_ERROR (Status);
173
174 Entry->MachineType = Entry->Emulator->MachineType;
175
176 InsertTailList (&mAvailableEmulators, &Entry->Link);
177 }
178 }
179
180 /**
181 Add the Image Services to EFI Boot Services Table and install the protocol
182 interfaces for this image.
183
184 @param HobStart The HOB to initialize
185
186 @return Status code.
187
188 **/
189 EFI_STATUS
190 CoreInitializeImageServices (
191 IN VOID *HobStart
192 )
193 {
194 EFI_STATUS Status;
195 LOADED_IMAGE_PRIVATE_DATA *Image;
196 EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress;
197 UINT64 DxeCoreImageLength;
198 VOID *DxeCoreEntryPoint;
199 EFI_PEI_HOB_POINTERS DxeCoreHob;
200
201 //
202 // Searching for image hob
203 //
204 DxeCoreHob.Raw = HobStart;
205 while ((DxeCoreHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, DxeCoreHob.Raw)) != NULL) {
206 if (CompareGuid (&DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) {
207 //
208 // Find Dxe Core HOB
209 //
210 break;
211 }
212 DxeCoreHob.Raw = GET_NEXT_HOB (DxeCoreHob);
213 }
214 ASSERT (DxeCoreHob.Raw != NULL);
215
216 DxeCoreImageBaseAddress = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress;
217 DxeCoreImageLength = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength;
218 DxeCoreEntryPoint = (VOID *) (UINTN) DxeCoreHob.MemoryAllocationModule->EntryPoint;
219 gDxeCoreFileName = &DxeCoreHob.MemoryAllocationModule->ModuleName;
220
221 //
222 // Initialize the fields for an internal driver
223 //
224 Image = &mCorePrivateImage;
225
226 Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)DxeCoreEntryPoint;
227 Image->ImageBasePage = DxeCoreImageBaseAddress;
228 Image->NumberOfPages = (UINTN)(EFI_SIZE_TO_PAGES((UINTN)(DxeCoreImageLength)));
229 Image->Tpl = gEfiCurrentTpl;
230 Image->Info.SystemTable = gDxeCoreST;
231 Image->Info.ImageBase = (VOID *)(UINTN)DxeCoreImageBaseAddress;
232 Image->Info.ImageSize = DxeCoreImageLength;
233
234 //
235 // Install the protocol interfaces for this image
236 //
237 Status = CoreInstallProtocolInterface (
238 &Image->Handle,
239 &gEfiLoadedImageProtocolGuid,
240 EFI_NATIVE_INTERFACE,
241 &Image->Info
242 );
243 ASSERT_EFI_ERROR (Status);
244
245 mCurrentImage = Image;
246
247 //
248 // Fill in DXE globals
249 //
250 mDxeCoreImageMachineType = PeCoffLoaderGetMachineType (Image->Info.ImageBase);
251 gDxeCoreImageHandle = Image->Handle;
252 gDxeCoreLoadedImage = &Image->Info;
253
254 //
255 // Create the PE/COFF emulator protocol registration event
256 //
257 Status = CoreCreateEvent (
258 EVT_NOTIFY_SIGNAL,
259 TPL_CALLBACK,
260 PeCoffEmuProtocolNotify,
261 NULL,
262 &mPeCoffEmuProtocolRegistrationEvent
263 );
264 ASSERT_EFI_ERROR(Status);
265
266 //
267 // Register for protocol notifications on this event
268 //
269 Status = CoreRegisterProtocolNotify (
270 &gEdkiiPeCoffImageEmulatorProtocolGuid,
271 mPeCoffEmuProtocolRegistrationEvent,
272 &mPeCoffEmuProtocolNotifyRegistration
273 );
274 ASSERT_EFI_ERROR(Status);
275
276 InitializeListHead (&mAvailableEmulators);
277
278 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
279 //
280 // Export DXE Core PE Loader functionality for backward compatibility.
281 //
282 Status = CoreInstallProtocolInterface (
283 &mLoadPe32PrivateData.Handle,
284 &gEfiLoadPeImageProtocolGuid,
285 EFI_NATIVE_INTERFACE,
286 &mLoadPe32PrivateData.Pe32Image
287 );
288 }
289
290 ProtectUefiImage (&Image->Info, Image->LoadedImageDevicePath);
291
292 return Status;
293 }
294
295 /**
296 Read image file (specified by UserHandle) into user specified buffer with specified offset
297 and length.
298
299 @param UserHandle Image file handle
300 @param Offset Offset to the source file
301 @param ReadSize For input, pointer of size to read; For output,
302 pointer of size actually read.
303 @param Buffer Buffer to write into
304
305 @retval EFI_SUCCESS Successfully read the specified part of file
306 into buffer.
307
308 **/
309 EFI_STATUS
310 EFIAPI
311 CoreReadImageFile (
312 IN VOID *UserHandle,
313 IN UINTN Offset,
314 IN OUT UINTN *ReadSize,
315 OUT VOID *Buffer
316 )
317 {
318 UINTN EndPosition;
319 IMAGE_FILE_HANDLE *FHand;
320
321 if (UserHandle == NULL || ReadSize == NULL || Buffer == NULL) {
322 return EFI_INVALID_PARAMETER;
323 }
324
325 if (MAX_ADDRESS - Offset < *ReadSize) {
326 return EFI_INVALID_PARAMETER;
327 }
328
329 FHand = (IMAGE_FILE_HANDLE *)UserHandle;
330 ASSERT (FHand->Signature == IMAGE_FILE_HANDLE_SIGNATURE);
331
332 //
333 // Move data from our local copy of the file
334 //
335 EndPosition = Offset + *ReadSize;
336 if (EndPosition > FHand->SourceSize) {
337 *ReadSize = (UINT32)(FHand->SourceSize - Offset);
338 }
339 if (Offset >= FHand->SourceSize) {
340 *ReadSize = 0;
341 }
342
343 CopyMem (Buffer, (CHAR8 *)FHand->Source + Offset, *ReadSize);
344 return EFI_SUCCESS;
345 }
346 /**
347 To check memory usage bit map array to figure out if the memory range the image will be loaded in is available or not. If
348 memory range is available, the function will mark the corresponding bits to 1 which indicates the memory range is used.
349 The function is only invoked when load modules at fixed address feature is enabled.
350
351 @param ImageBase The base address the image will be loaded at.
352 @param ImageSize The size of the image
353
354 @retval EFI_SUCCESS The memory range the image will be loaded in is available
355 @retval EFI_NOT_FOUND The memory range the image will be loaded in is not available
356 **/
357 EFI_STATUS
358 CheckAndMarkFixLoadingMemoryUsageBitMap (
359 IN EFI_PHYSICAL_ADDRESS ImageBase,
360 IN UINTN ImageSize
361 )
362 {
363 UINT32 DxeCodePageNumber;
364 UINT64 DxeCodeSize;
365 EFI_PHYSICAL_ADDRESS DxeCodeBase;
366 UINTN BaseOffsetPageNumber;
367 UINTN TopOffsetPageNumber;
368 UINTN Index;
369 //
370 // The DXE code range includes RuntimeCodePage range and Boot time code range.
371 //
372 DxeCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);
373 DxeCodePageNumber += PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);
374 DxeCodeSize = EFI_PAGES_TO_SIZE(DxeCodePageNumber);
375 DxeCodeBase = gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress - DxeCodeSize;
376
377 //
378 // If the memory usage bit map is not initialized, do it. Every bit in the array
379 // indicate the status of the corresponding memory page, available or not
380 //
381 if (mDxeCodeMemoryRangeUsageBitMap == NULL) {
382 mDxeCodeMemoryRangeUsageBitMap = AllocateZeroPool(((DxeCodePageNumber/64) + 1)*sizeof(UINT64));
383 }
384 //
385 // If the Dxe code memory range is not allocated or the bit map array allocation failed, return EFI_NOT_FOUND
386 //
387 if (!gLoadFixedAddressCodeMemoryReady || mDxeCodeMemoryRangeUsageBitMap == NULL) {
388 return EFI_NOT_FOUND;
389 }
390 //
391 // Test the memory range for loading the image in the DXE code range.
392 //
393 if (gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress < ImageBase + ImageSize ||
394 DxeCodeBase > ImageBase) {
395 return EFI_NOT_FOUND;
396 }
397 //
398 // Test if the memory is avalaible or not.
399 //
400 BaseOffsetPageNumber = EFI_SIZE_TO_PAGES((UINT32)(ImageBase - DxeCodeBase));
401 TopOffsetPageNumber = EFI_SIZE_TO_PAGES((UINT32)(ImageBase + ImageSize - DxeCodeBase));
402 for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {
403 if ((mDxeCodeMemoryRangeUsageBitMap[Index / 64] & LShiftU64(1, (Index % 64))) != 0) {
404 //
405 // This page is already used.
406 //
407 return EFI_NOT_FOUND;
408 }
409 }
410
411 //
412 // Being here means the memory range is available. So mark the bits for the memory range
413 //
414 for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {
415 mDxeCodeMemoryRangeUsageBitMap[Index / 64] |= LShiftU64(1, (Index % 64));
416 }
417 return EFI_SUCCESS;
418 }
419 /**
420
421 Get the fixed loading address from image header assigned by build tool. This function only be called
422 when Loading module at Fixed address feature enabled.
423
424 @param ImageContext Pointer to the image context structure that describes the PE/COFF
425 image that needs to be examined by this function.
426 @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools .
427 @retval EFI_NOT_FOUND The image has no assigned fixed loading address.
428
429 **/
430 EFI_STATUS
431 GetPeCoffImageFixLoadingAssignedAddress(
432 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
433 )
434 {
435 UINTN SectionHeaderOffset;
436 EFI_STATUS Status;
437 EFI_IMAGE_SECTION_HEADER SectionHeader;
438 EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
439 UINT16 Index;
440 UINTN Size;
441 UINT16 NumberOfSections;
442 IMAGE_FILE_HANDLE *Handle;
443 UINT64 ValueInSectionHeader;
444
445
446 Status = EFI_NOT_FOUND;
447
448 //
449 // Get PeHeader pointer
450 //
451 Handle = (IMAGE_FILE_HANDLE*)ImageContext->Handle;
452 ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )Handle->Source + ImageContext->PeCoffHeaderOffset);
453 SectionHeaderOffset = ImageContext->PeCoffHeaderOffset +
454 sizeof (UINT32) +
455 sizeof (EFI_IMAGE_FILE_HEADER) +
456 ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader;
457 NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;
458
459 //
460 // Get base address from the first section header that doesn't point to code section.
461 //
462 for (Index = 0; Index < NumberOfSections; Index++) {
463 //
464 // Read section header from file
465 //
466 Size = sizeof (EFI_IMAGE_SECTION_HEADER);
467 Status = ImageContext->ImageRead (
468 ImageContext->Handle,
469 SectionHeaderOffset,
470 &Size,
471 &SectionHeader
472 );
473 if (EFI_ERROR (Status)) {
474 return Status;
475 }
476 if (Size != sizeof (EFI_IMAGE_SECTION_HEADER)) {
477 return EFI_NOT_FOUND;
478 }
479
480 Status = EFI_NOT_FOUND;
481
482 if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {
483 //
484 // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header
485 // that doesn't point to code section in image header, as well as ImageBase field of image header. And there is an
486 // assumption that when the feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations
487 // & PointerToLineNumbers fields should NOT be Zero, or else, these 2 fields should be set to Zero
488 //
489 ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations);
490 if (ValueInSectionHeader != 0) {
491 //
492 // When the feature is configured as load module at fixed absolute address, the ImageAddress field of ImageContext
493 // hold the spcified address. If the feature is configured as load module at fixed offset, ImageAddress hold an offset
494 // relative to top address
495 //
496 if ((INT64)PcdGet64(PcdLoadModuleAtFixAddressEnable) < 0) {
497 ImageContext->ImageAddress = gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress + (INT64)(INTN)ImageContext->ImageAddress;
498 }
499 //
500 // Check if the memory range is available.
501 //
502 Status = CheckAndMarkFixLoadingMemoryUsageBitMap (ImageContext->ImageAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment));
503 }
504 break;
505 }
506 SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
507 }
508 DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address 0x%11p. Status = %r \n", (VOID *)(UINTN)(ImageContext->ImageAddress), Status));
509 return Status;
510 }
511
512 /**
513 Decides whether a PE/COFF image can execute on this system, either natively
514 or via emulation/interpretation. In the latter case, the PeCoffEmu member
515 of the LOADED_IMAGE_PRIVATE_DATA struct pointer is populated with a pointer
516 to the emulator protocol that supports this image.
517
518 @param[in, out] Image LOADED_IMAGE_PRIVATE_DATA struct pointer
519
520 @retval TRUE The image is supported
521 @retval FALSE The image is not supported
522
523 **/
524 STATIC
525 BOOLEAN
526 CoreIsImageTypeSupported (
527 IN OUT LOADED_IMAGE_PRIVATE_DATA *Image
528 )
529 {
530 LIST_ENTRY *Link;
531 EMULATOR_ENTRY *Entry;
532
533 for (Link = GetFirstNode (&mAvailableEmulators);
534 !IsNull (&mAvailableEmulators, Link);
535 Link = GetNextNode (&mAvailableEmulators, Link)) {
536
537 Entry = BASE_CR (Link, EMULATOR_ENTRY, Link);
538 if (Entry->MachineType != Image->ImageContext.Machine) {
539 continue;
540 }
541
542 if (Entry->Emulator->IsImageSupported (Entry->Emulator,
543 Image->ImageContext.ImageType,
544 Image->Info.FilePath)) {
545 Image->PeCoffEmu = Entry->Emulator;
546 return TRUE;
547 }
548 }
549
550 return EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine) ||
551 EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image->ImageContext.Machine);
552 }
553
554 /**
555 Loads, relocates, and invokes a PE/COFF image
556
557 @param BootPolicy If TRUE, indicates that the request originates
558 from the boot manager, and that the boot
559 manager is attempting to load FilePath as a
560 boot selection.
561 @param Pe32Handle The handle of PE32 image
562 @param Image PE image to be loaded
563 @param DstBuffer The buffer to store the image
564 @param EntryPoint A pointer to the entry point
565 @param Attribute The bit mask of attributes to set for the load
566 PE image
567
568 @retval EFI_SUCCESS The file was loaded, relocated, and invoked
569 @retval EFI_OUT_OF_RESOURCES There was not enough memory to load and
570 relocate the PE/COFF file
571 @retval EFI_INVALID_PARAMETER Invalid parameter
572 @retval EFI_BUFFER_TOO_SMALL Buffer for image is too small
573
574 **/
575 EFI_STATUS
576 CoreLoadPeImage (
577 IN BOOLEAN BootPolicy,
578 IN VOID *Pe32Handle,
579 IN LOADED_IMAGE_PRIVATE_DATA *Image,
580 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
581 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
582 IN UINT32 Attribute
583 )
584 {
585 EFI_STATUS Status;
586 BOOLEAN DstBufAlocated;
587 UINTN Size;
588
589 ZeroMem (&Image->ImageContext, sizeof (Image->ImageContext));
590
591 Image->ImageContext.Handle = Pe32Handle;
592 Image->ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)CoreReadImageFile;
593
594 //
595 // Get information about the image being loaded
596 //
597 Status = PeCoffLoaderGetImageInfo (&Image->ImageContext);
598 if (EFI_ERROR (Status)) {
599 return Status;
600 }
601
602 if (!CoreIsImageTypeSupported (Image)) {
603 //
604 // The PE/COFF loader can support loading image types that can be executed.
605 // If we loaded an image type that we can not execute return EFI_UNSUPPORTED.
606 //
607 DEBUG ((DEBUG_ERROR, "Image type %s can't be loaded on %s UEFI system.\n",
608 GetMachineTypeName (Image->ImageContext.Machine),
609 GetMachineTypeName (mDxeCoreImageMachineType)));
610 return EFI_UNSUPPORTED;
611 }
612
613 //
614 // Set EFI memory type based on ImageType
615 //
616 switch (Image->ImageContext.ImageType) {
617 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:
618 Image->ImageContext.ImageCodeMemoryType = EfiLoaderCode;
619 Image->ImageContext.ImageDataMemoryType = EfiLoaderData;
620 break;
621 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
622 Image->ImageContext.ImageCodeMemoryType = EfiBootServicesCode;
623 Image->ImageContext.ImageDataMemoryType = EfiBootServicesData;
624 break;
625 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
626 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER:
627 Image->ImageContext.ImageCodeMemoryType = EfiRuntimeServicesCode;
628 Image->ImageContext.ImageDataMemoryType = EfiRuntimeServicesData;
629 break;
630 default:
631 Image->ImageContext.ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM;
632 return EFI_UNSUPPORTED;
633 }
634
635 //
636 // Allocate memory of the correct memory type aligned on the required image boundary
637 //
638 DstBufAlocated = FALSE;
639 if (DstBuffer == 0) {
640 //
641 // Allocate Destination Buffer as caller did not pass it in
642 //
643
644 if (Image->ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
645 Size = (UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment;
646 } else {
647 Size = (UINTN)Image->ImageContext.ImageSize;
648 }
649
650 Image->NumberOfPages = EFI_SIZE_TO_PAGES (Size);
651
652 //
653 // If the image relocations have not been stripped, then load at any address.
654 // Otherwise load at the address at which it was linked.
655 //
656 // Memory below 1MB should be treated reserved for CSM and there should be
657 // no modules whose preferred load addresses are below 1MB.
658 //
659 Status = EFI_OUT_OF_RESOURCES;
660 //
661 // If Loading Module At Fixed Address feature is enabled, the module should be loaded to
662 // a specified address.
663 //
664 if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 ) {
665 Status = GetPeCoffImageFixLoadingAssignedAddress (&(Image->ImageContext));
666
667 if (EFI_ERROR (Status)) {
668 //
669 // If the code memory is not ready, invoke CoreAllocatePage with AllocateAnyPages to load the driver.
670 //
671 DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED ERROR: Loading module at fixed address failed since specified memory is not available.\n"));
672
673 Status = CoreAllocatePages (
674 AllocateAnyPages,
675 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),
676 Image->NumberOfPages,
677 &Image->ImageContext.ImageAddress
678 );
679 }
680 } else {
681 if (Image->ImageContext.ImageAddress >= 0x100000 || Image->ImageContext.RelocationsStripped) {
682 Status = CoreAllocatePages (
683 AllocateAddress,
684 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),
685 Image->NumberOfPages,
686 &Image->ImageContext.ImageAddress
687 );
688 }
689 if (EFI_ERROR (Status) && !Image->ImageContext.RelocationsStripped) {
690 Status = CoreAllocatePages (
691 AllocateAnyPages,
692 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),
693 Image->NumberOfPages,
694 &Image->ImageContext.ImageAddress
695 );
696 }
697 }
698 if (EFI_ERROR (Status)) {
699 return Status;
700 }
701 DstBufAlocated = TRUE;
702 } else {
703 //
704 // Caller provided the destination buffer
705 //
706
707 if (Image->ImageContext.RelocationsStripped && (Image->ImageContext.ImageAddress != DstBuffer)) {
708 //
709 // If the image relocations were stripped, and the caller provided a
710 // destination buffer address that does not match the address that the
711 // image is linked at, then the image cannot be loaded.
712 //
713 return EFI_INVALID_PARAMETER;
714 }
715
716 if (Image->NumberOfPages != 0 &&
717 Image->NumberOfPages <
718 (EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment))) {
719 Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);
720 return EFI_BUFFER_TOO_SMALL;
721 }
722
723 Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);
724 Image->ImageContext.ImageAddress = DstBuffer;
725 }
726
727 Image->ImageBasePage = Image->ImageContext.ImageAddress;
728 if (!Image->ImageContext.IsTeImage) {
729 Image->ImageContext.ImageAddress =
730 (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &
731 ~((UINTN)Image->ImageContext.SectionAlignment - 1);
732 }
733
734 //
735 // Load the image from the file into the allocated memory
736 //
737 Status = PeCoffLoaderLoadImage (&Image->ImageContext);
738 if (EFI_ERROR (Status)) {
739 goto Done;
740 }
741
742 //
743 // If this is a Runtime Driver, then allocate memory for the FixupData that
744 // is used to relocate the image when SetVirtualAddressMap() is called. The
745 // relocation is done by the Runtime AP.
746 //
747 if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) != 0) {
748 if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
749 Image->ImageContext.FixupData = AllocateRuntimePool ((UINTN)(Image->ImageContext.FixupDataSize));
750 if (Image->ImageContext.FixupData == NULL) {
751 Status = EFI_OUT_OF_RESOURCES;
752 goto Done;
753 }
754 }
755 }
756
757 //
758 // Relocate the image in memory
759 //
760 Status = PeCoffLoaderRelocateImage (&Image->ImageContext);
761 if (EFI_ERROR (Status)) {
762 goto Done;
763 }
764
765 //
766 // Flush the Instruction Cache
767 //
768 InvalidateInstructionCacheRange ((VOID *)(UINTN)Image->ImageContext.ImageAddress, (UINTN)Image->ImageContext.ImageSize);
769
770 //
771 // Copy the machine type from the context to the image private data. This
772 // is needed during image unload to know if we should call an EBC protocol
773 // to unload the image.
774 //
775 Image->Machine = Image->ImageContext.Machine;
776
777 //
778 // Get the image entry point. If it's an EBC image, then call into the
779 // interpreter to create a thunk for the entry point and use the returned
780 // value for the entry point.
781 //
782 Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)Image->ImageContext.EntryPoint;
783 if (Image->ImageContext.Machine == EFI_IMAGE_MACHINE_EBC) {
784 //
785 // Locate the EBC interpreter protocol
786 //
787 Status = CoreLocateProtocol (&gEfiEbcProtocolGuid, NULL, (VOID **)&Image->Ebc);
788 if (EFI_ERROR(Status) || Image->Ebc == NULL) {
789 DEBUG ((DEBUG_LOAD | DEBUG_ERROR, "CoreLoadPeImage: There is no EBC interpreter for an EBC image.\n"));
790 goto Done;
791 }
792
793 //
794 // Register a callback for flushing the instruction cache so that created
795 // thunks can be flushed.
796 //
797 Status = Image->Ebc->RegisterICacheFlush (Image->Ebc, (EBC_ICACHE_FLUSH)InvalidateInstructionCacheRange);
798 if (EFI_ERROR(Status)) {
799 goto Done;
800 }
801
802 //
803 // Create a thunk for the image's entry point. This will be the new
804 // entry point for the image.
805 //
806 Status = Image->Ebc->CreateThunk (
807 Image->Ebc,
808 Image->Handle,
809 (VOID *)(UINTN) Image->ImageContext.EntryPoint,
810 (VOID **) &Image->EntryPoint
811 );
812 if (EFI_ERROR(Status)) {
813 goto Done;
814 }
815 } else if (Image->PeCoffEmu != NULL) {
816 Status = Image->PeCoffEmu->RegisterImage (Image->PeCoffEmu,
817 Image->ImageBasePage,
818 EFI_PAGES_TO_SIZE (Image->NumberOfPages),
819 &Image->EntryPoint);
820 if (EFI_ERROR (Status)) {
821 DEBUG ((DEBUG_LOAD | DEBUG_ERROR,
822 "CoreLoadPeImage: Failed to register foreign image with emulator.\n"));
823 goto Done;
824 }
825 }
826
827 //
828 // Fill in the image information for the Loaded Image Protocol
829 //
830 Image->Type = Image->ImageContext.ImageType;
831 Image->Info.ImageBase = (VOID *)(UINTN)Image->ImageContext.ImageAddress;
832 Image->Info.ImageSize = Image->ImageContext.ImageSize;
833 Image->Info.ImageCodeType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType);
834 Image->Info.ImageDataType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageDataMemoryType);
835 if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) != 0) {
836 if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
837 //
838 // Make a list off all the RT images so we can let the RT AP know about them.
839 //
840 Image->RuntimeData = AllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY));
841 if (Image->RuntimeData == NULL) {
842 goto Done;
843 }
844 Image->RuntimeData->ImageBase = Image->Info.ImageBase;
845 Image->RuntimeData->ImageSize = (UINT64) (Image->Info.ImageSize);
846 Image->RuntimeData->RelocationData = Image->ImageContext.FixupData;
847 Image->RuntimeData->Handle = Image->Handle;
848 InsertTailList (&gRuntime->ImageHead, &Image->RuntimeData->Link);
849 InsertImageRecord (Image->RuntimeData);
850 }
851 }
852
853 //
854 // Fill in the entry point of the image if it is available
855 //
856 if (EntryPoint != NULL) {
857 *EntryPoint = Image->ImageContext.EntryPoint;
858 }
859
860 //
861 // Print the load address and the PDB file name if it is available
862 //
863
864 DEBUG_CODE_BEGIN ();
865
866 UINTN Index;
867 UINTN StartIndex;
868 CHAR8 EfiFileName[256];
869
870
871 DEBUG ((DEBUG_INFO | DEBUG_LOAD,
872 "Loading driver at 0x%11p EntryPoint=0x%11p ",
873 (VOID *)(UINTN) Image->ImageContext.ImageAddress,
874 FUNCTION_ENTRY_POINT (Image->ImageContext.EntryPoint)));
875
876
877 //
878 // Print Module Name by Pdb file path.
879 // Windows and Unix style file path are all trimmed correctly.
880 //
881 if (Image->ImageContext.PdbPointer != NULL) {
882 StartIndex = 0;
883 for (Index = 0; Image->ImageContext.PdbPointer[Index] != 0; Index++) {
884 if ((Image->ImageContext.PdbPointer[Index] == '\\') || (Image->ImageContext.PdbPointer[Index] == '/')) {
885 StartIndex = Index + 1;
886 }
887 }
888 //
889 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
890 // The PDB file name is limited in the range of 0~255.
891 // If the length is bigger than 255, trim the redudant characters to avoid overflow in array boundary.
892 //
893 for (Index = 0; Index < sizeof (EfiFileName) - 4; Index++) {
894 EfiFileName[Index] = Image->ImageContext.PdbPointer[Index + StartIndex];
895 if (EfiFileName[Index] == 0) {
896 EfiFileName[Index] = '.';
897 }
898 if (EfiFileName[Index] == '.') {
899 EfiFileName[Index + 1] = 'e';
900 EfiFileName[Index + 2] = 'f';
901 EfiFileName[Index + 3] = 'i';
902 EfiFileName[Index + 4] = 0;
903 break;
904 }
905 }
906
907 if (Index == sizeof (EfiFileName) - 4) {
908 EfiFileName[Index] = 0;
909 }
910 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex]));
911 }
912 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "\n"));
913
914 DEBUG_CODE_END ();
915
916 return EFI_SUCCESS;
917
918 Done:
919
920 //
921 // Free memory.
922 //
923
924 if (DstBufAlocated) {
925 CoreFreePages (Image->ImageContext.ImageAddress, Image->NumberOfPages);
926 Image->ImageContext.ImageAddress = 0;
927 Image->ImageBasePage = 0;
928 }
929
930 if (Image->ImageContext.FixupData != NULL) {
931 CoreFreePool (Image->ImageContext.FixupData);
932 }
933
934 return Status;
935 }
936
937
938
939 /**
940 Get the image's private data from its handle.
941
942 @param ImageHandle The image handle
943
944 @return Return the image private data associated with ImageHandle.
945
946 **/
947 LOADED_IMAGE_PRIVATE_DATA *
948 CoreLoadedImageInfo (
949 IN EFI_HANDLE ImageHandle
950 )
951 {
952 EFI_STATUS Status;
953 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
954 LOADED_IMAGE_PRIVATE_DATA *Image;
955
956 Status = CoreHandleProtocol (
957 ImageHandle,
958 &gEfiLoadedImageProtocolGuid,
959 (VOID **)&LoadedImage
960 );
961 if (!EFI_ERROR (Status)) {
962 Image = LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage);
963 } else {
964 DEBUG ((DEBUG_LOAD, "CoreLoadedImageInfo: Not an ImageHandle %p\n", ImageHandle));
965 Image = NULL;
966 }
967
968 return Image;
969 }
970
971
972 /**
973 Unloads EFI image from memory.
974
975 @param Image EFI image
976 @param FreePage Free allocated pages
977
978 **/
979 VOID
980 CoreUnloadAndCloseImage (
981 IN LOADED_IMAGE_PRIVATE_DATA *Image,
982 IN BOOLEAN FreePage
983 )
984 {
985 EFI_STATUS Status;
986 UINTN HandleCount;
987 EFI_HANDLE *HandleBuffer;
988 UINTN HandleIndex;
989 EFI_GUID **ProtocolGuidArray;
990 UINTN ArrayCount;
991 UINTN ProtocolIndex;
992 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;
993 UINTN OpenInfoCount;
994 UINTN OpenInfoIndex;
995
996 HandleBuffer = NULL;
997 ProtocolGuidArray = NULL;
998
999 if (Image->Started) {
1000 UnregisterMemoryProfileImage (Image);
1001 }
1002
1003 UnprotectUefiImage (&Image->Info, Image->LoadedImageDevicePath);
1004
1005 if (Image->Ebc != NULL) {
1006 //
1007 // If EBC protocol exists we must perform cleanups for this image.
1008 //
1009 Image->Ebc->UnloadImage (Image->Ebc, Image->Handle);
1010 }
1011
1012 if (Image->PeCoffEmu != NULL) {
1013 //
1014 // If the PE/COFF Emulator protocol exists we must unregister the image.
1015 //
1016 Image->PeCoffEmu->UnregisterImage (Image->PeCoffEmu, Image->ImageBasePage);
1017 }
1018
1019 //
1020 // Unload image, free Image->ImageContext->ModHandle
1021 //
1022 PeCoffLoaderUnloadImage (&Image->ImageContext);
1023
1024 //
1025 // Free our references to the image handle
1026 //
1027 if (Image->Handle != NULL) {
1028
1029 Status = CoreLocateHandleBuffer (
1030 AllHandles,
1031 NULL,
1032 NULL,
1033 &HandleCount,
1034 &HandleBuffer
1035 );
1036 if (!EFI_ERROR (Status)) {
1037 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
1038 Status = CoreProtocolsPerHandle (
1039 HandleBuffer[HandleIndex],
1040 &ProtocolGuidArray,
1041 &ArrayCount
1042 );
1043 if (!EFI_ERROR (Status)) {
1044 for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
1045 Status = CoreOpenProtocolInformation (
1046 HandleBuffer[HandleIndex],
1047 ProtocolGuidArray[ProtocolIndex],
1048 &OpenInfo,
1049 &OpenInfoCount
1050 );
1051 if (!EFI_ERROR (Status)) {
1052 for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
1053 if (OpenInfo[OpenInfoIndex].AgentHandle == Image->Handle) {
1054 Status = CoreCloseProtocol (
1055 HandleBuffer[HandleIndex],
1056 ProtocolGuidArray[ProtocolIndex],
1057 Image->Handle,
1058 OpenInfo[OpenInfoIndex].ControllerHandle
1059 );
1060 }
1061 }
1062 if (OpenInfo != NULL) {
1063 CoreFreePool(OpenInfo);
1064 }
1065 }
1066 }
1067 if (ProtocolGuidArray != NULL) {
1068 CoreFreePool(ProtocolGuidArray);
1069 }
1070 }
1071 }
1072 if (HandleBuffer != NULL) {
1073 CoreFreePool (HandleBuffer);
1074 }
1075 }
1076
1077 CoreRemoveDebugImageInfoEntry (Image->Handle);
1078
1079 Status = CoreUninstallProtocolInterface (
1080 Image->Handle,
1081 &gEfiLoadedImageDevicePathProtocolGuid,
1082 Image->LoadedImageDevicePath
1083 );
1084
1085 Status = CoreUninstallProtocolInterface (
1086 Image->Handle,
1087 &gEfiLoadedImageProtocolGuid,
1088 &Image->Info
1089 );
1090
1091 if (Image->ImageContext.HiiResourceData != 0) {
1092 Status = CoreUninstallProtocolInterface (
1093 Image->Handle,
1094 &gEfiHiiPackageListProtocolGuid,
1095 (VOID *) (UINTN) Image->ImageContext.HiiResourceData
1096 );
1097 }
1098
1099 }
1100
1101 if (Image->RuntimeData != NULL) {
1102 if (Image->RuntimeData->Link.ForwardLink != NULL) {
1103 //
1104 // Remove the Image from the Runtime Image list as we are about to Free it!
1105 //
1106 RemoveEntryList (&Image->RuntimeData->Link);
1107 RemoveImageRecord (Image->RuntimeData);
1108 }
1109 CoreFreePool (Image->RuntimeData);
1110 }
1111
1112 //
1113 // Free the Image from memory
1114 //
1115 if ((Image->ImageBasePage != 0) && FreePage) {
1116 CoreFreePages (Image->ImageBasePage, Image->NumberOfPages);
1117 }
1118
1119 //
1120 // Done with the Image structure
1121 //
1122 if (Image->Info.FilePath != NULL) {
1123 CoreFreePool (Image->Info.FilePath);
1124 }
1125
1126 if (Image->LoadedImageDevicePath != NULL) {
1127 CoreFreePool (Image->LoadedImageDevicePath);
1128 }
1129
1130 if (Image->FixupData != NULL) {
1131 CoreFreePool (Image->FixupData);
1132 }
1133
1134 CoreFreePool (Image);
1135 }
1136
1137
1138 /**
1139 Loads an EFI image into memory and returns a handle to the image.
1140
1141 @param BootPolicy If TRUE, indicates that the request originates
1142 from the boot manager, and that the boot
1143 manager is attempting to load FilePath as a
1144 boot selection.
1145 @param ParentImageHandle The caller's image handle.
1146 @param FilePath The specific file path from which the image is
1147 loaded.
1148 @param SourceBuffer If not NULL, a pointer to the memory location
1149 containing a copy of the image to be loaded.
1150 @param SourceSize The size in bytes of SourceBuffer.
1151 @param DstBuffer The buffer to store the image
1152 @param NumberOfPages If not NULL, it inputs a pointer to the page
1153 number of DstBuffer and outputs a pointer to
1154 the page number of the image. If this number is
1155 not enough, return EFI_BUFFER_TOO_SMALL and
1156 this parameter contains the required number.
1157 @param ImageHandle Pointer to the returned image handle that is
1158 created when the image is successfully loaded.
1159 @param EntryPoint A pointer to the entry point
1160 @param Attribute The bit mask of attributes to set for the load
1161 PE image
1162
1163 @retval EFI_SUCCESS The image was loaded into memory.
1164 @retval EFI_NOT_FOUND The FilePath was not found.
1165 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1166 @retval EFI_BUFFER_TOO_SMALL The buffer is too small
1167 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1168 path cannot be parsed to locate the proper
1169 protocol for loading the file.
1170 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1171 resources.
1172 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1173 understood.
1174 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1175 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1176 image from being loaded. NULL is returned in *ImageHandle.
1177 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1178 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1179 platform policy specifies that the image should not be started.
1180
1181 **/
1182 EFI_STATUS
1183 CoreLoadImageCommon (
1184 IN BOOLEAN BootPolicy,
1185 IN EFI_HANDLE ParentImageHandle,
1186 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
1187 IN VOID *SourceBuffer OPTIONAL,
1188 IN UINTN SourceSize,
1189 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
1190 IN OUT UINTN *NumberOfPages OPTIONAL,
1191 OUT EFI_HANDLE *ImageHandle,
1192 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
1193 IN UINT32 Attribute
1194 )
1195 {
1196 LOADED_IMAGE_PRIVATE_DATA *Image;
1197 LOADED_IMAGE_PRIVATE_DATA *ParentImage;
1198 IMAGE_FILE_HANDLE FHand;
1199 EFI_STATUS Status;
1200 EFI_STATUS SecurityStatus;
1201 EFI_HANDLE DeviceHandle;
1202 UINT32 AuthenticationStatus;
1203 EFI_DEVICE_PATH_PROTOCOL *OriginalFilePath;
1204 EFI_DEVICE_PATH_PROTOCOL *HandleFilePath;
1205 EFI_DEVICE_PATH_PROTOCOL *InputFilePath;
1206 EFI_DEVICE_PATH_PROTOCOL *Node;
1207 UINTN FilePathSize;
1208 BOOLEAN ImageIsFromFv;
1209 BOOLEAN ImageIsFromLoadFile;
1210
1211 SecurityStatus = EFI_SUCCESS;
1212
1213 ASSERT (gEfiCurrentTpl < TPL_NOTIFY);
1214 ParentImage = NULL;
1215
1216 //
1217 // The caller must pass in a valid ParentImageHandle
1218 //
1219 if (ImageHandle == NULL || ParentImageHandle == NULL) {
1220 return EFI_INVALID_PARAMETER;
1221 }
1222
1223 ParentImage = CoreLoadedImageInfo (ParentImageHandle);
1224 if (ParentImage == NULL) {
1225 DEBUG((DEBUG_LOAD|DEBUG_ERROR, "LoadImageEx: Parent handle not an image handle\n"));
1226 return EFI_INVALID_PARAMETER;
1227 }
1228
1229 ZeroMem (&FHand, sizeof (IMAGE_FILE_HANDLE));
1230 FHand.Signature = IMAGE_FILE_HANDLE_SIGNATURE;
1231 OriginalFilePath = FilePath;
1232 InputFilePath = FilePath;
1233 HandleFilePath = FilePath;
1234 DeviceHandle = NULL;
1235 Status = EFI_SUCCESS;
1236 AuthenticationStatus = 0;
1237 ImageIsFromFv = FALSE;
1238 ImageIsFromLoadFile = FALSE;
1239
1240 //
1241 // If the caller passed a copy of the file, then just use it
1242 //
1243 if (SourceBuffer != NULL) {
1244 FHand.Source = SourceBuffer;
1245 FHand.SourceSize = SourceSize;
1246 Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &HandleFilePath, &DeviceHandle);
1247 if (EFI_ERROR (Status)) {
1248 DeviceHandle = NULL;
1249 }
1250 if (SourceSize > 0) {
1251 Status = EFI_SUCCESS;
1252 } else {
1253 Status = EFI_LOAD_ERROR;
1254 }
1255 } else {
1256 if (FilePath == NULL) {
1257 return EFI_INVALID_PARAMETER;
1258 }
1259
1260 //
1261 // Try to get the image device handle by checking the match protocol.
1262 //
1263 Node = NULL;
1264 Status = CoreLocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &HandleFilePath, &DeviceHandle);
1265 if (!EFI_ERROR (Status)) {
1266 ImageIsFromFv = TRUE;
1267 } else {
1268 HandleFilePath = FilePath;
1269 Status = CoreLocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &HandleFilePath, &DeviceHandle);
1270 if (EFI_ERROR (Status)) {
1271 if (!BootPolicy) {
1272 HandleFilePath = FilePath;
1273 Status = CoreLocateDevicePath (&gEfiLoadFile2ProtocolGuid, &HandleFilePath, &DeviceHandle);
1274 }
1275 if (EFI_ERROR (Status)) {
1276 HandleFilePath = FilePath;
1277 Status = CoreLocateDevicePath (&gEfiLoadFileProtocolGuid, &HandleFilePath, &DeviceHandle);
1278 if (!EFI_ERROR (Status)) {
1279 ImageIsFromLoadFile = TRUE;
1280 Node = HandleFilePath;
1281 }
1282 }
1283 }
1284 }
1285
1286 //
1287 // Get the source file buffer by its device path.
1288 //
1289 FHand.Source = GetFileBufferByFilePath (
1290 BootPolicy,
1291 FilePath,
1292 &FHand.SourceSize,
1293 &AuthenticationStatus
1294 );
1295 if (FHand.Source == NULL) {
1296 Status = EFI_NOT_FOUND;
1297 } else {
1298 FHand.FreeBuffer = TRUE;
1299 if (ImageIsFromLoadFile) {
1300 //
1301 // LoadFile () may cause the device path of the Handle be updated.
1302 //
1303 OriginalFilePath = AppendDevicePath (DevicePathFromHandle (DeviceHandle), Node);
1304 }
1305 }
1306 }
1307
1308 if (EFI_ERROR (Status)) {
1309 Image = NULL;
1310 goto Done;
1311 }
1312
1313 if (gSecurity2 != NULL) {
1314 //
1315 // Verify File Authentication through the Security2 Architectural Protocol
1316 //
1317 SecurityStatus = gSecurity2->FileAuthentication (
1318 gSecurity2,
1319 OriginalFilePath,
1320 FHand.Source,
1321 FHand.SourceSize,
1322 BootPolicy
1323 );
1324 if (!EFI_ERROR (SecurityStatus) && ImageIsFromFv) {
1325 //
1326 // When Security2 is installed, Security Architectural Protocol must be published.
1327 //
1328 ASSERT (gSecurity != NULL);
1329
1330 //
1331 // Verify the Authentication Status through the Security Architectural Protocol
1332 // Only on images that have been read using Firmware Volume protocol.
1333 //
1334 SecurityStatus = gSecurity->FileAuthenticationState (
1335 gSecurity,
1336 AuthenticationStatus,
1337 OriginalFilePath
1338 );
1339 }
1340 } else if ((gSecurity != NULL) && (OriginalFilePath != NULL)) {
1341 //
1342 // Verify the Authentication Status through the Security Architectural Protocol
1343 //
1344 SecurityStatus = gSecurity->FileAuthenticationState (
1345 gSecurity,
1346 AuthenticationStatus,
1347 OriginalFilePath
1348 );
1349 }
1350
1351 //
1352 // Check Security Status.
1353 //
1354 if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {
1355 if (SecurityStatus == EFI_ACCESS_DENIED) {
1356 //
1357 // Image was not loaded because the platform policy prohibits the image from being loaded.
1358 // It's the only place we could meet EFI_ACCESS_DENIED.
1359 //
1360 *ImageHandle = NULL;
1361 }
1362 Status = SecurityStatus;
1363 Image = NULL;
1364 goto Done;
1365 }
1366
1367 //
1368 // Allocate a new image structure
1369 //
1370 Image = AllocateZeroPool (sizeof(LOADED_IMAGE_PRIVATE_DATA));
1371 if (Image == NULL) {
1372 Status = EFI_OUT_OF_RESOURCES;
1373 goto Done;
1374 }
1375
1376 //
1377 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
1378 //
1379 FilePath = OriginalFilePath;
1380 if (DeviceHandle != NULL) {
1381 Status = CoreHandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath);
1382 if (!EFI_ERROR (Status)) {
1383 FilePathSize = GetDevicePathSize (HandleFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
1384 FilePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *)FilePath) + FilePathSize );
1385 }
1386 }
1387 //
1388 // Initialize the fields for an internal driver
1389 //
1390 Image->Signature = LOADED_IMAGE_PRIVATE_DATA_SIGNATURE;
1391 Image->Info.SystemTable = gDxeCoreST;
1392 Image->Info.DeviceHandle = DeviceHandle;
1393 Image->Info.Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
1394 Image->Info.FilePath = DuplicateDevicePath (FilePath);
1395 Image->Info.ParentHandle = ParentImageHandle;
1396
1397
1398 if (NumberOfPages != NULL) {
1399 Image->NumberOfPages = *NumberOfPages ;
1400 } else {
1401 Image->NumberOfPages = 0 ;
1402 }
1403
1404 //
1405 // Install the protocol interfaces for this image
1406 // don't fire notifications yet
1407 //
1408 Status = CoreInstallProtocolInterfaceNotify (
1409 &Image->Handle,
1410 &gEfiLoadedImageProtocolGuid,
1411 EFI_NATIVE_INTERFACE,
1412 &Image->Info,
1413 FALSE
1414 );
1415 if (EFI_ERROR (Status)) {
1416 goto Done;
1417 }
1418
1419 //
1420 // Load the image. If EntryPoint is Null, it will not be set.
1421 //
1422 Status = CoreLoadPeImage (BootPolicy, &FHand, Image, DstBuffer, EntryPoint, Attribute);
1423 if (EFI_ERROR (Status)) {
1424 if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_OUT_OF_RESOURCES)) {
1425 if (NumberOfPages != NULL) {
1426 *NumberOfPages = Image->NumberOfPages;
1427 }
1428 }
1429 goto Done;
1430 }
1431
1432 if (NumberOfPages != NULL) {
1433 *NumberOfPages = Image->NumberOfPages;
1434 }
1435
1436 //
1437 // Register the image in the Debug Image Info Table if the attribute is set
1438 //
1439 if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION) != 0) {
1440 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, &Image->Info, Image->Handle);
1441 }
1442
1443 //
1444 //Reinstall loaded image protocol to fire any notifications
1445 //
1446 Status = CoreReinstallProtocolInterface (
1447 Image->Handle,
1448 &gEfiLoadedImageProtocolGuid,
1449 &Image->Info,
1450 &Image->Info
1451 );
1452 if (EFI_ERROR (Status)) {
1453 goto Done;
1454 }
1455
1456 //
1457 // If DevicePath parameter to the LoadImage() is not NULL, then make a copy of DevicePath,
1458 // otherwise Loaded Image Device Path Protocol is installed with a NULL interface pointer.
1459 //
1460 if (OriginalFilePath != NULL) {
1461 Image->LoadedImageDevicePath = DuplicateDevicePath (OriginalFilePath);
1462 }
1463
1464 //
1465 // Install Loaded Image Device Path Protocol onto the image handle of a PE/COFE image
1466 //
1467 Status = CoreInstallProtocolInterface (
1468 &Image->Handle,
1469 &gEfiLoadedImageDevicePathProtocolGuid,
1470 EFI_NATIVE_INTERFACE,
1471 Image->LoadedImageDevicePath
1472 );
1473 if (EFI_ERROR (Status)) {
1474 goto Done;
1475 }
1476
1477 //
1478 // Install HII Package List Protocol onto the image handle
1479 //
1480 if (Image->ImageContext.HiiResourceData != 0) {
1481 Status = CoreInstallProtocolInterface (
1482 &Image->Handle,
1483 &gEfiHiiPackageListProtocolGuid,
1484 EFI_NATIVE_INTERFACE,
1485 (VOID *) (UINTN) Image->ImageContext.HiiResourceData
1486 );
1487 if (EFI_ERROR (Status)) {
1488 goto Done;
1489 }
1490 }
1491 ProtectUefiImage (&Image->Info, Image->LoadedImageDevicePath);
1492
1493 //
1494 // Success. Return the image handle
1495 //
1496 *ImageHandle = Image->Handle;
1497
1498 Done:
1499 //
1500 // All done accessing the source file
1501 // If we allocated the Source buffer, free it
1502 //
1503 if (FHand.FreeBuffer) {
1504 CoreFreePool (FHand.Source);
1505 }
1506 if (OriginalFilePath != InputFilePath) {
1507 CoreFreePool (OriginalFilePath);
1508 }
1509
1510 //
1511 // There was an error. If there's an Image structure, free it
1512 //
1513 if (EFI_ERROR (Status)) {
1514 if (Image != NULL) {
1515 CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer == 0));
1516 Image = NULL;
1517 }
1518 } else if (EFI_ERROR (SecurityStatus)) {
1519 Status = SecurityStatus;
1520 }
1521
1522 //
1523 // Track the return status from LoadImage.
1524 //
1525 if (Image != NULL) {
1526 Image->LoadImageStatus = Status;
1527 }
1528
1529 return Status;
1530 }
1531
1532
1533
1534
1535 /**
1536 Loads an EFI image into memory and returns a handle to the image.
1537
1538 @param BootPolicy If TRUE, indicates that the request originates
1539 from the boot manager, and that the boot
1540 manager is attempting to load FilePath as a
1541 boot selection.
1542 @param ParentImageHandle The caller's image handle.
1543 @param FilePath The specific file path from which the image is
1544 loaded.
1545 @param SourceBuffer If not NULL, a pointer to the memory location
1546 containing a copy of the image to be loaded.
1547 @param SourceSize The size in bytes of SourceBuffer.
1548 @param ImageHandle Pointer to the returned image handle that is
1549 created when the image is successfully loaded.
1550
1551 @retval EFI_SUCCESS The image was loaded into memory.
1552 @retval EFI_NOT_FOUND The FilePath was not found.
1553 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1554 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1555 path cannot be parsed to locate the proper
1556 protocol for loading the file.
1557 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1558 resources.
1559 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1560 understood.
1561 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1562 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1563 image from being loaded. NULL is returned in *ImageHandle.
1564 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1565 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1566 platform policy specifies that the image should not be started.
1567
1568 **/
1569 EFI_STATUS
1570 EFIAPI
1571 CoreLoadImage (
1572 IN BOOLEAN BootPolicy,
1573 IN EFI_HANDLE ParentImageHandle,
1574 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
1575 IN VOID *SourceBuffer OPTIONAL,
1576 IN UINTN SourceSize,
1577 OUT EFI_HANDLE *ImageHandle
1578 )
1579 {
1580 EFI_STATUS Status;
1581 EFI_HANDLE Handle;
1582
1583 PERF_LOAD_IMAGE_BEGIN (NULL);
1584
1585 Status = CoreLoadImageCommon (
1586 BootPolicy,
1587 ParentImageHandle,
1588 FilePath,
1589 SourceBuffer,
1590 SourceSize,
1591 (EFI_PHYSICAL_ADDRESS) (UINTN) NULL,
1592 NULL,
1593 ImageHandle,
1594 NULL,
1595 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION | EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
1596 );
1597
1598 Handle = NULL;
1599 if (!EFI_ERROR (Status)) {
1600 //
1601 // ImageHandle will be valid only Status is success.
1602 //
1603 Handle = *ImageHandle;
1604 }
1605
1606 PERF_LOAD_IMAGE_END (Handle);
1607
1608 return Status;
1609 }
1610
1611
1612
1613 /**
1614 Loads an EFI image into memory and returns a handle to the image with extended parameters.
1615
1616 @param This Calling context
1617 @param ParentImageHandle The caller's image handle.
1618 @param FilePath The specific file path from which the image is
1619 loaded.
1620 @param SourceBuffer If not NULL, a pointer to the memory location
1621 containing a copy of the image to be loaded.
1622 @param SourceSize The size in bytes of SourceBuffer.
1623 @param DstBuffer The buffer to store the image.
1624 @param NumberOfPages For input, specifies the space size of the
1625 image by caller if not NULL. For output,
1626 specifies the actual space size needed.
1627 @param ImageHandle Image handle for output.
1628 @param EntryPoint Image entry point for output.
1629 @param Attribute The bit mask of attributes to set for the load
1630 PE image.
1631
1632 @retval EFI_SUCCESS The image was loaded into memory.
1633 @retval EFI_NOT_FOUND The FilePath was not found.
1634 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1635 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1636 path cannot be parsed to locate the proper
1637 protocol for loading the file.
1638 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1639 resources.
1640 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1641 understood.
1642 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1643 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1644 image from being loaded. NULL is returned in *ImageHandle.
1645 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1646 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1647 platform policy specifies that the image should not be started.
1648
1649 **/
1650 EFI_STATUS
1651 EFIAPI
1652 CoreLoadImageEx (
1653 IN EFI_PE32_IMAGE_PROTOCOL *This,
1654 IN EFI_HANDLE ParentImageHandle,
1655 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
1656 IN VOID *SourceBuffer OPTIONAL,
1657 IN UINTN SourceSize,
1658 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
1659 OUT UINTN *NumberOfPages OPTIONAL,
1660 OUT EFI_HANDLE *ImageHandle,
1661 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
1662 IN UINT32 Attribute
1663 )
1664 {
1665 EFI_STATUS Status;
1666 EFI_HANDLE Handle;
1667
1668 PERF_LOAD_IMAGE_BEGIN (NULL);
1669
1670 Status = CoreLoadImageCommon (
1671 TRUE,
1672 ParentImageHandle,
1673 FilePath,
1674 SourceBuffer,
1675 SourceSize,
1676 DstBuffer,
1677 NumberOfPages,
1678 ImageHandle,
1679 EntryPoint,
1680 Attribute
1681 );
1682
1683 Handle = NULL;
1684 if (!EFI_ERROR (Status)) {
1685 //
1686 // ImageHandle will be valid only Status is success.
1687 //
1688 Handle = *ImageHandle;
1689 }
1690
1691 PERF_LOAD_IMAGE_END (Handle);
1692
1693 return Status;
1694 }
1695
1696
1697 /**
1698 Transfer control to a loaded image's entry point.
1699
1700 @param ImageHandle Handle of image to be started.
1701 @param ExitDataSize Pointer of the size to ExitData
1702 @param ExitData Pointer to a pointer to a data buffer that
1703 includes a Null-terminated string,
1704 optionally followed by additional binary data.
1705 The string is a description that the caller may
1706 use to further indicate the reason for the
1707 image's exit.
1708
1709 @retval EFI_INVALID_PARAMETER Invalid parameter
1710 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1711 @retval EFI_SECURITY_VIOLATION The current platform policy specifies that the image should not be started.
1712 @retval EFI_SUCCESS Successfully transfer control to the image's
1713 entry point.
1714
1715 **/
1716 EFI_STATUS
1717 EFIAPI
1718 CoreStartImage (
1719 IN EFI_HANDLE ImageHandle,
1720 OUT UINTN *ExitDataSize,
1721 OUT CHAR16 **ExitData OPTIONAL
1722 )
1723 {
1724 EFI_STATUS Status;
1725 LOADED_IMAGE_PRIVATE_DATA *Image;
1726 LOADED_IMAGE_PRIVATE_DATA *LastImage;
1727 UINT64 HandleDatabaseKey;
1728 UINTN SetJumpFlag;
1729 EFI_HANDLE Handle;
1730
1731 Handle = ImageHandle;
1732
1733 Image = CoreLoadedImageInfo (ImageHandle);
1734 if (Image == NULL || Image->Started) {
1735 return EFI_INVALID_PARAMETER;
1736 }
1737 if (EFI_ERROR (Image->LoadImageStatus)) {
1738 return Image->LoadImageStatus;
1739 }
1740
1741 //
1742 // The image to be started must have the machine type supported by DxeCore.
1743 //
1744 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->Machine) &&
1745 Image->PeCoffEmu == NULL) {
1746 //
1747 // Do not ASSERT here, because image might be loaded via EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED
1748 // But it can not be started.
1749 //
1750 DEBUG ((EFI_D_ERROR, "Image type %s can't be started ", GetMachineTypeName(Image->Machine)));
1751 DEBUG ((EFI_D_ERROR, "on %s UEFI system.\n", GetMachineTypeName(mDxeCoreImageMachineType)));
1752 return EFI_UNSUPPORTED;
1753 }
1754
1755 PERF_START_IMAGE_BEGIN (Handle);
1756
1757
1758 //
1759 // Push the current start image context, and
1760 // link the current image to the head. This is the
1761 // only image that can call Exit()
1762 //
1763 HandleDatabaseKey = CoreGetHandleDatabaseKey ();
1764 LastImage = mCurrentImage;
1765 mCurrentImage = Image;
1766 Image->Tpl = gEfiCurrentTpl;
1767
1768 //
1769 // Set long jump for Exit() support
1770 // JumpContext must be aligned on a CPU specific boundary.
1771 // Overallocate the buffer and force the required alignment
1772 //
1773 Image->JumpBuffer = AllocatePool (sizeof (BASE_LIBRARY_JUMP_BUFFER) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);
1774 if (Image->JumpBuffer == NULL) {
1775 //
1776 // Image may be unloaded after return with failure,
1777 // then ImageHandle may be invalid, so use NULL handle to record perf log.
1778 //
1779 PERF_START_IMAGE_END (NULL);
1780
1781 //
1782 // Pop the current start image context
1783 //
1784 mCurrentImage = LastImage;
1785
1786 return EFI_OUT_OF_RESOURCES;
1787 }
1788 Image->JumpContext = ALIGN_POINTER (Image->JumpBuffer, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);
1789
1790 SetJumpFlag = SetJump (Image->JumpContext);
1791 //
1792 // The initial call to SetJump() must always return 0.
1793 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
1794 //
1795 if (SetJumpFlag == 0) {
1796 RegisterMemoryProfileImage (Image, (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION ? EFI_FV_FILETYPE_APPLICATION : EFI_FV_FILETYPE_DRIVER));
1797 //
1798 // Call the image's entry point
1799 //
1800 Image->Started = TRUE;
1801 Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable);
1802
1803 //
1804 // Add some debug information if the image returned with error.
1805 // This make the user aware and check if the driver image have already released
1806 // all the resource in this situation.
1807 //
1808 DEBUG_CODE_BEGIN ();
1809 if (EFI_ERROR (Image->Status)) {
1810 DEBUG ((DEBUG_ERROR, "Error: Image at %11p start failed: %r\n", Image->Info.ImageBase, Image->Status));
1811 }
1812 DEBUG_CODE_END ();
1813
1814 //
1815 // If the image returns, exit it through Exit()
1816 //
1817 CoreExit (ImageHandle, Image->Status, 0, NULL);
1818 }
1819
1820 //
1821 // Image has completed. Verify the tpl is the same
1822 //
1823 ASSERT (Image->Tpl == gEfiCurrentTpl);
1824 CoreRestoreTpl (Image->Tpl);
1825
1826 CoreFreePool (Image->JumpBuffer);
1827
1828 //
1829 // Pop the current start image context
1830 //
1831 mCurrentImage = LastImage;
1832
1833 //
1834 // UEFI Specification - StartImage() - EFI 1.10 Extension
1835 // To maintain compatibility with UEFI drivers that are written to the EFI
1836 // 1.02 Specification, StartImage() must monitor the handle database before
1837 // and after each image is started. If any handles are created or modified
1838 // when an image is started, then EFI_BOOT_SERVICES.ConnectController() must
1839 // be called with the Recursive parameter set to TRUE for each of the newly
1840 // created or modified handles before StartImage() returns.
1841 //
1842 if (Image->Type != EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
1843 CoreConnectHandlesByKey (HandleDatabaseKey);
1844 }
1845
1846 //
1847 // Handle the image's returned ExitData
1848 //
1849 DEBUG_CODE_BEGIN ();
1850 if (Image->ExitDataSize != 0 || Image->ExitData != NULL) {
1851
1852 DEBUG ((DEBUG_LOAD, "StartImage: ExitDataSize %d, ExitData %p", (UINT32)Image->ExitDataSize, Image->ExitData));
1853 if (Image->ExitData != NULL) {
1854 DEBUG ((DEBUG_LOAD, " (%hs)", Image->ExitData));
1855 }
1856 DEBUG ((DEBUG_LOAD, "\n"));
1857 }
1858 DEBUG_CODE_END ();
1859
1860 //
1861 // Return the exit data to the caller
1862 //
1863 if (ExitData != NULL && ExitDataSize != NULL) {
1864 *ExitDataSize = Image->ExitDataSize;
1865 *ExitData = Image->ExitData;
1866 } else {
1867 //
1868 // Caller doesn't want the exit data, free it
1869 //
1870 CoreFreePool (Image->ExitData);
1871 Image->ExitData = NULL;
1872 }
1873
1874 //
1875 // Save the Status because Image will get destroyed if it is unloaded.
1876 //
1877 Status = Image->Status;
1878
1879 //
1880 // If the image returned an error, or if the image is an application
1881 // unload it
1882 //
1883 if (EFI_ERROR (Image->Status) || Image->Type == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
1884 CoreUnloadAndCloseImage (Image, TRUE);
1885 //
1886 // ImageHandle may be invalid after the image is unloaded, so use NULL handle to record perf log.
1887 //
1888 Handle = NULL;
1889 }
1890
1891 //
1892 // Done
1893 //
1894 PERF_START_IMAGE_END (Handle);
1895 return Status;
1896 }
1897
1898 /**
1899 Terminates the currently loaded EFI image and returns control to boot services.
1900
1901 @param ImageHandle Handle that identifies the image. This
1902 parameter is passed to the image on entry.
1903 @param Status The image's exit code.
1904 @param ExitDataSize The size, in bytes, of ExitData. Ignored if
1905 ExitStatus is EFI_SUCCESS.
1906 @param ExitData Pointer to a data buffer that includes a
1907 Null-terminated Unicode string, optionally
1908 followed by additional binary data. The string
1909 is a description that the caller may use to
1910 further indicate the reason for the image's
1911 exit.
1912
1913 @retval EFI_INVALID_PARAMETER Image handle is NULL or it is not current
1914 image.
1915 @retval EFI_SUCCESS Successfully terminates the currently loaded
1916 EFI image.
1917 @retval EFI_ACCESS_DENIED Should never reach there.
1918 @retval EFI_OUT_OF_RESOURCES Could not allocate pool
1919
1920 **/
1921 EFI_STATUS
1922 EFIAPI
1923 CoreExit (
1924 IN EFI_HANDLE ImageHandle,
1925 IN EFI_STATUS Status,
1926 IN UINTN ExitDataSize,
1927 IN CHAR16 *ExitData OPTIONAL
1928 )
1929 {
1930 LOADED_IMAGE_PRIVATE_DATA *Image;
1931 EFI_TPL OldTpl;
1932
1933 //
1934 // Prevent possible reentrance to this function
1935 // for the same ImageHandle
1936 //
1937 OldTpl = CoreRaiseTpl (TPL_NOTIFY);
1938
1939 Image = CoreLoadedImageInfo (ImageHandle);
1940 if (Image == NULL) {
1941 Status = EFI_INVALID_PARAMETER;
1942 goto Done;
1943 }
1944
1945 if (!Image->Started) {
1946 //
1947 // The image has not been started so just free its resources
1948 //
1949 CoreUnloadAndCloseImage (Image, TRUE);
1950 Status = EFI_SUCCESS;
1951 goto Done;
1952 }
1953
1954 //
1955 // Image has been started, verify this image can exit
1956 //
1957 if (Image != mCurrentImage) {
1958 DEBUG ((DEBUG_LOAD|DEBUG_ERROR, "Exit: Image is not exitable image\n"));
1959 Status = EFI_INVALID_PARAMETER;
1960 goto Done;
1961 }
1962
1963 //
1964 // Set status
1965 //
1966 Image->Status = Status;
1967
1968 //
1969 // If there's ExitData info, move it
1970 //
1971 if (ExitData != NULL) {
1972 Image->ExitDataSize = ExitDataSize;
1973 Image->ExitData = AllocatePool (Image->ExitDataSize);
1974 if (Image->ExitData == NULL) {
1975 Status = EFI_OUT_OF_RESOURCES;
1976 goto Done;
1977 }
1978 CopyMem (Image->ExitData, ExitData, Image->ExitDataSize);
1979 }
1980
1981 CoreRestoreTpl (OldTpl);
1982 //
1983 // return to StartImage
1984 //
1985 LongJump (Image->JumpContext, (UINTN)-1);
1986
1987 //
1988 // If we return from LongJump, then it is an error
1989 //
1990 ASSERT (FALSE);
1991 Status = EFI_ACCESS_DENIED;
1992 Done:
1993 CoreRestoreTpl (OldTpl);
1994 return Status;
1995 }
1996
1997
1998
1999
2000 /**
2001 Unloads an image.
2002
2003 @param ImageHandle Handle that identifies the image to be
2004 unloaded.
2005
2006 @retval EFI_SUCCESS The image has been unloaded.
2007 @retval EFI_UNSUPPORTED The image has been started, and does not support
2008 unload.
2009 @retval EFI_INVALID_PARAMPETER ImageHandle is not a valid image handle.
2010
2011 **/
2012 EFI_STATUS
2013 EFIAPI
2014 CoreUnloadImage (
2015 IN EFI_HANDLE ImageHandle
2016 )
2017 {
2018 EFI_STATUS Status;
2019 LOADED_IMAGE_PRIVATE_DATA *Image;
2020
2021 Image = CoreLoadedImageInfo (ImageHandle);
2022 if (Image == NULL ) {
2023 //
2024 // The image handle is not valid
2025 //
2026 Status = EFI_INVALID_PARAMETER;
2027 goto Done;
2028 }
2029
2030 if (Image->Started) {
2031 //
2032 // The image has been started, request it to unload.
2033 //
2034 Status = EFI_UNSUPPORTED;
2035 if (Image->Info.Unload != NULL) {
2036 Status = Image->Info.Unload (ImageHandle);
2037 }
2038
2039 } else {
2040 //
2041 // This Image hasn't been started, thus it can be unloaded
2042 //
2043 Status = EFI_SUCCESS;
2044 }
2045
2046
2047 if (!EFI_ERROR (Status)) {
2048 //
2049 // if the Image was not started or Unloaded O.K. then clean up
2050 //
2051 CoreUnloadAndCloseImage (Image, TRUE);
2052 }
2053
2054 Done:
2055 return Status;
2056 }
2057
2058
2059
2060 /**
2061 Unload the specified image.
2062
2063 @param This Indicates the calling context.
2064 @param ImageHandle The specified image handle.
2065
2066 @retval EFI_INVALID_PARAMETER Image handle is NULL.
2067 @retval EFI_UNSUPPORTED Attempt to unload an unsupported image.
2068 @retval EFI_SUCCESS Image successfully unloaded.
2069
2070 **/
2071 EFI_STATUS
2072 EFIAPI
2073 CoreUnloadImageEx (
2074 IN EFI_PE32_IMAGE_PROTOCOL *This,
2075 IN EFI_HANDLE ImageHandle
2076 )
2077 {
2078 return CoreUnloadImage (ImageHandle);
2079 }