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