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