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