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