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 *
GetMachineTypeName(UINT16 MachineType)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
PeCoffEmuProtocolNotify(IN EFI_EVENT Event,IN VOID * Context)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
CoreInitializeImageServices(IN VOID * HobStart)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
CoreReadImageFile(IN VOID * UserHandle,IN UINTN Offset,IN OUT UINTN * ReadSize,OUT VOID * Buffer)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
CheckAndMarkFixLoadingMemoryUsageBitMap(IN EFI_PHYSICAL_ADDRESS ImageBase,IN UINTN ImageSize)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
GetPeCoffImageFixLoadingAssignedAddress(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT * ImageContext)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
CoreIsImageTypeSupported(IN OUT LOADED_IMAGE_PRIVATE_DATA * Image)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
CoreLoadPeImage(IN BOOLEAN BootPolicy,IN VOID * Pe32Handle,IN LOADED_IMAGE_PRIVATE_DATA * Image,IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,OUT EFI_PHYSICAL_ADDRESS * EntryPoint OPTIONAL,IN UINT32 Attribute)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 if (Image->PeCoffEmu != NULL) {
760 Status = Image->PeCoffEmu->RegisterImage (Image->PeCoffEmu,
761 Image->ImageBasePage,
762 EFI_PAGES_TO_SIZE (Image->NumberOfPages),
763 &Image->EntryPoint);
764 if (EFI_ERROR (Status)) {
765 DEBUG ((DEBUG_LOAD | DEBUG_ERROR,
766 "CoreLoadPeImage: Failed to register foreign image with emulator.\n"));
767 goto Done;
768 }
769 }
770
771 //
772 // Fill in the image information for the Loaded Image Protocol
773 //
774 Image->Type = Image->ImageContext.ImageType;
775 Image->Info.ImageBase = (VOID *)(UINTN)Image->ImageContext.ImageAddress;
776 Image->Info.ImageSize = Image->ImageContext.ImageSize;
777 Image->Info.ImageCodeType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType);
778 Image->Info.ImageDataType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageDataMemoryType);
779 if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) != 0) {
780 if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
781 //
782 // Make a list off all the RT images so we can let the RT AP know about them.
783 //
784 Image->RuntimeData = AllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY));
785 if (Image->RuntimeData == NULL) {
786 goto Done;
787 }
788 Image->RuntimeData->ImageBase = Image->Info.ImageBase;
789 Image->RuntimeData->ImageSize = (UINT64) (Image->Info.ImageSize);
790 Image->RuntimeData->RelocationData = Image->ImageContext.FixupData;
791 Image->RuntimeData->Handle = Image->Handle;
792 InsertTailList (&gRuntime->ImageHead, &Image->RuntimeData->Link);
793 InsertImageRecord (Image->RuntimeData);
794 }
795 }
796
797 //
798 // Fill in the entry point of the image if it is available
799 //
800 if (EntryPoint != NULL) {
801 *EntryPoint = Image->ImageContext.EntryPoint;
802 }
803
804 //
805 // Print the load address and the PDB file name if it is available
806 //
807
808 DEBUG_CODE_BEGIN ();
809
810 UINTN Index;
811 UINTN StartIndex;
812 CHAR8 EfiFileName[256];
813
814
815 DEBUG ((DEBUG_INFO | DEBUG_LOAD,
816 "Loading driver at 0x%11p EntryPoint=0x%11p ",
817 (VOID *)(UINTN) Image->ImageContext.ImageAddress,
818 FUNCTION_ENTRY_POINT (Image->ImageContext.EntryPoint)));
819
820
821 //
822 // Print Module Name by Pdb file path.
823 // Windows and Unix style file path are all trimmed correctly.
824 //
825 if (Image->ImageContext.PdbPointer != NULL) {
826 StartIndex = 0;
827 for (Index = 0; Image->ImageContext.PdbPointer[Index] != 0; Index++) {
828 if ((Image->ImageContext.PdbPointer[Index] == '\\') || (Image->ImageContext.PdbPointer[Index] == '/')) {
829 StartIndex = Index + 1;
830 }
831 }
832 //
833 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
834 // The PDB file name is limited in the range of 0~255.
835 // If the length is bigger than 255, trim the redudant characters to avoid overflow in array boundary.
836 //
837 for (Index = 0; Index < sizeof (EfiFileName) - 4; Index++) {
838 EfiFileName[Index] = Image->ImageContext.PdbPointer[Index + StartIndex];
839 if (EfiFileName[Index] == 0) {
840 EfiFileName[Index] = '.';
841 }
842 if (EfiFileName[Index] == '.') {
843 EfiFileName[Index + 1] = 'e';
844 EfiFileName[Index + 2] = 'f';
845 EfiFileName[Index + 3] = 'i';
846 EfiFileName[Index + 4] = 0;
847 break;
848 }
849 }
850
851 if (Index == sizeof (EfiFileName) - 4) {
852 EfiFileName[Index] = 0;
853 }
854 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex]));
855 }
856 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "\n"));
857
858 DEBUG_CODE_END ();
859
860 return EFI_SUCCESS;
861
862 Done:
863
864 //
865 // Free memory.
866 //
867
868 if (DstBufAlocated) {
869 CoreFreePages (Image->ImageContext.ImageAddress, Image->NumberOfPages);
870 Image->ImageContext.ImageAddress = 0;
871 Image->ImageBasePage = 0;
872 }
873
874 if (Image->ImageContext.FixupData != NULL) {
875 CoreFreePool (Image->ImageContext.FixupData);
876 }
877
878 return Status;
879 }
880
881
882
883 /**
884 Get the image's private data from its handle.
885
886 @param ImageHandle The image handle
887
888 @return Return the image private data associated with ImageHandle.
889
890 **/
891 LOADED_IMAGE_PRIVATE_DATA *
CoreLoadedImageInfo(IN EFI_HANDLE ImageHandle)892 CoreLoadedImageInfo (
893 IN EFI_HANDLE ImageHandle
894 )
895 {
896 EFI_STATUS Status;
897 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
898 LOADED_IMAGE_PRIVATE_DATA *Image;
899
900 Status = CoreHandleProtocol (
901 ImageHandle,
902 &gEfiLoadedImageProtocolGuid,
903 (VOID **)&LoadedImage
904 );
905 if (!EFI_ERROR (Status)) {
906 Image = LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage);
907 } else {
908 DEBUG ((DEBUG_LOAD, "CoreLoadedImageInfo: Not an ImageHandle %p\n", ImageHandle));
909 Image = NULL;
910 }
911
912 return Image;
913 }
914
915
916 /**
917 Unloads EFI image from memory.
918
919 @param Image EFI image
920 @param FreePage Free allocated pages
921
922 **/
923 VOID
CoreUnloadAndCloseImage(IN LOADED_IMAGE_PRIVATE_DATA * Image,IN BOOLEAN FreePage)924 CoreUnloadAndCloseImage (
925 IN LOADED_IMAGE_PRIVATE_DATA *Image,
926 IN BOOLEAN FreePage
927 )
928 {
929 EFI_STATUS Status;
930 UINTN HandleCount;
931 EFI_HANDLE *HandleBuffer;
932 UINTN HandleIndex;
933 EFI_GUID **ProtocolGuidArray;
934 UINTN ArrayCount;
935 UINTN ProtocolIndex;
936 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;
937 UINTN OpenInfoCount;
938 UINTN OpenInfoIndex;
939
940 HandleBuffer = NULL;
941 ProtocolGuidArray = NULL;
942
943 if (Image->Started) {
944 UnregisterMemoryProfileImage (Image);
945 }
946
947 UnprotectUefiImage (&Image->Info, Image->LoadedImageDevicePath);
948
949 if (Image->PeCoffEmu != NULL) {
950 //
951 // If the PE/COFF Emulator protocol exists we must unregister the image.
952 //
953 Image->PeCoffEmu->UnregisterImage (Image->PeCoffEmu, Image->ImageBasePage);
954 }
955
956 //
957 // Unload image, free Image->ImageContext->ModHandle
958 //
959 PeCoffLoaderUnloadImage (&Image->ImageContext);
960
961 //
962 // Free our references to the image handle
963 //
964 if (Image->Handle != NULL) {
965
966 Status = CoreLocateHandleBuffer (
967 AllHandles,
968 NULL,
969 NULL,
970 &HandleCount,
971 &HandleBuffer
972 );
973 if (!EFI_ERROR (Status)) {
974 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
975 Status = CoreProtocolsPerHandle (
976 HandleBuffer[HandleIndex],
977 &ProtocolGuidArray,
978 &ArrayCount
979 );
980 if (!EFI_ERROR (Status)) {
981 for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
982 Status = CoreOpenProtocolInformation (
983 HandleBuffer[HandleIndex],
984 ProtocolGuidArray[ProtocolIndex],
985 &OpenInfo,
986 &OpenInfoCount
987 );
988 if (!EFI_ERROR (Status)) {
989 for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
990 if (OpenInfo[OpenInfoIndex].AgentHandle == Image->Handle) {
991 Status = CoreCloseProtocol (
992 HandleBuffer[HandleIndex],
993 ProtocolGuidArray[ProtocolIndex],
994 Image->Handle,
995 OpenInfo[OpenInfoIndex].ControllerHandle
996 );
997 }
998 }
999 if (OpenInfo != NULL) {
1000 CoreFreePool(OpenInfo);
1001 }
1002 }
1003 }
1004 if (ProtocolGuidArray != NULL) {
1005 CoreFreePool(ProtocolGuidArray);
1006 }
1007 }
1008 }
1009 if (HandleBuffer != NULL) {
1010 CoreFreePool (HandleBuffer);
1011 }
1012 }
1013
1014 CoreRemoveDebugImageInfoEntry (Image->Handle);
1015
1016 Status = CoreUninstallProtocolInterface (
1017 Image->Handle,
1018 &gEfiLoadedImageDevicePathProtocolGuid,
1019 Image->LoadedImageDevicePath
1020 );
1021
1022 Status = CoreUninstallProtocolInterface (
1023 Image->Handle,
1024 &gEfiLoadedImageProtocolGuid,
1025 &Image->Info
1026 );
1027
1028 if (Image->ImageContext.HiiResourceData != 0) {
1029 Status = CoreUninstallProtocolInterface (
1030 Image->Handle,
1031 &gEfiHiiPackageListProtocolGuid,
1032 (VOID *) (UINTN) Image->ImageContext.HiiResourceData
1033 );
1034 }
1035
1036 }
1037
1038 if (Image->RuntimeData != NULL) {
1039 if (Image->RuntimeData->Link.ForwardLink != NULL) {
1040 //
1041 // Remove the Image from the Runtime Image list as we are about to Free it!
1042 //
1043 RemoveEntryList (&Image->RuntimeData->Link);
1044 RemoveImageRecord (Image->RuntimeData);
1045 }
1046 CoreFreePool (Image->RuntimeData);
1047 }
1048
1049 //
1050 // Free the Image from memory
1051 //
1052 if ((Image->ImageBasePage != 0) && FreePage) {
1053 CoreFreePages (Image->ImageBasePage, Image->NumberOfPages);
1054 }
1055
1056 //
1057 // Done with the Image structure
1058 //
1059 if (Image->Info.FilePath != NULL) {
1060 CoreFreePool (Image->Info.FilePath);
1061 }
1062
1063 if (Image->LoadedImageDevicePath != NULL) {
1064 CoreFreePool (Image->LoadedImageDevicePath);
1065 }
1066
1067 if (Image->FixupData != NULL) {
1068 CoreFreePool (Image->FixupData);
1069 }
1070
1071 CoreFreePool (Image);
1072 }
1073
1074
1075 /**
1076 Loads an EFI image into memory and returns a handle to the image.
1077
1078 @param BootPolicy If TRUE, indicates that the request originates
1079 from the boot manager, and that the boot
1080 manager is attempting to load FilePath as a
1081 boot selection.
1082 @param ParentImageHandle The caller's image handle.
1083 @param FilePath The specific file path from which the image is
1084 loaded.
1085 @param SourceBuffer If not NULL, a pointer to the memory location
1086 containing a copy of the image to be loaded.
1087 @param SourceSize The size in bytes of SourceBuffer.
1088 @param DstBuffer The buffer to store the image
1089 @param NumberOfPages If not NULL, it inputs a pointer to the page
1090 number of DstBuffer and outputs a pointer to
1091 the page number of the image. If this number is
1092 not enough, return EFI_BUFFER_TOO_SMALL and
1093 this parameter contains the required number.
1094 @param ImageHandle Pointer to the returned image handle that is
1095 created when the image is successfully loaded.
1096 @param EntryPoint A pointer to the entry point
1097 @param Attribute The bit mask of attributes to set for the load
1098 PE image
1099
1100 @retval EFI_SUCCESS The image was loaded into memory.
1101 @retval EFI_NOT_FOUND The FilePath was not found.
1102 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1103 @retval EFI_BUFFER_TOO_SMALL The buffer is too small
1104 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1105 path cannot be parsed to locate the proper
1106 protocol for loading the file.
1107 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1108 resources.
1109 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1110 understood.
1111 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1112 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1113 image from being loaded. NULL is returned in *ImageHandle.
1114 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1115 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1116 platform policy specifies that the image should not be started.
1117
1118 **/
1119 EFI_STATUS
CoreLoadImageCommon(IN BOOLEAN BootPolicy,IN EFI_HANDLE ParentImageHandle,IN EFI_DEVICE_PATH_PROTOCOL * FilePath,IN VOID * SourceBuffer OPTIONAL,IN UINTN SourceSize,IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,IN OUT UINTN * NumberOfPages OPTIONAL,OUT EFI_HANDLE * ImageHandle,OUT EFI_PHYSICAL_ADDRESS * EntryPoint OPTIONAL,IN UINT32 Attribute)1120 CoreLoadImageCommon (
1121 IN BOOLEAN BootPolicy,
1122 IN EFI_HANDLE ParentImageHandle,
1123 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
1124 IN VOID *SourceBuffer OPTIONAL,
1125 IN UINTN SourceSize,
1126 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
1127 IN OUT UINTN *NumberOfPages OPTIONAL,
1128 OUT EFI_HANDLE *ImageHandle,
1129 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
1130 IN UINT32 Attribute
1131 )
1132 {
1133 LOADED_IMAGE_PRIVATE_DATA *Image;
1134 LOADED_IMAGE_PRIVATE_DATA *ParentImage;
1135 IMAGE_FILE_HANDLE FHand;
1136 EFI_STATUS Status;
1137 EFI_STATUS SecurityStatus;
1138 EFI_HANDLE DeviceHandle;
1139 UINT32 AuthenticationStatus;
1140 EFI_DEVICE_PATH_PROTOCOL *OriginalFilePath;
1141 EFI_DEVICE_PATH_PROTOCOL *HandleFilePath;
1142 EFI_DEVICE_PATH_PROTOCOL *InputFilePath;
1143 EFI_DEVICE_PATH_PROTOCOL *Node;
1144 UINTN FilePathSize;
1145 BOOLEAN ImageIsFromFv;
1146 BOOLEAN ImageIsFromLoadFile;
1147
1148 SecurityStatus = EFI_SUCCESS;
1149
1150 ASSERT (gEfiCurrentTpl < TPL_NOTIFY);
1151 ParentImage = NULL;
1152
1153 //
1154 // The caller must pass in a valid ParentImageHandle
1155 //
1156 if (ImageHandle == NULL || ParentImageHandle == NULL) {
1157 return EFI_INVALID_PARAMETER;
1158 }
1159
1160 ParentImage = CoreLoadedImageInfo (ParentImageHandle);
1161 if (ParentImage == NULL) {
1162 DEBUG((DEBUG_LOAD|DEBUG_ERROR, "LoadImageEx: Parent handle not an image handle\n"));
1163 return EFI_INVALID_PARAMETER;
1164 }
1165
1166 ZeroMem (&FHand, sizeof (IMAGE_FILE_HANDLE));
1167 FHand.Signature = IMAGE_FILE_HANDLE_SIGNATURE;
1168 OriginalFilePath = FilePath;
1169 InputFilePath = FilePath;
1170 HandleFilePath = FilePath;
1171 DeviceHandle = NULL;
1172 Status = EFI_SUCCESS;
1173 AuthenticationStatus = 0;
1174 ImageIsFromFv = FALSE;
1175 ImageIsFromLoadFile = FALSE;
1176
1177 //
1178 // If the caller passed a copy of the file, then just use it
1179 //
1180 if (SourceBuffer != NULL) {
1181 FHand.Source = SourceBuffer;
1182 FHand.SourceSize = SourceSize;
1183 Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &HandleFilePath, &DeviceHandle);
1184 if (EFI_ERROR (Status)) {
1185 DeviceHandle = NULL;
1186 }
1187 if (SourceSize > 0) {
1188 Status = EFI_SUCCESS;
1189 } else {
1190 Status = EFI_LOAD_ERROR;
1191 }
1192 } else {
1193 if (FilePath == NULL) {
1194 return EFI_INVALID_PARAMETER;
1195 }
1196
1197 //
1198 // Try to get the image device handle by checking the match protocol.
1199 //
1200 Node = NULL;
1201 Status = CoreLocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &HandleFilePath, &DeviceHandle);
1202 if (!EFI_ERROR (Status)) {
1203 ImageIsFromFv = TRUE;
1204 } else {
1205 HandleFilePath = FilePath;
1206 Status = CoreLocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &HandleFilePath, &DeviceHandle);
1207 if (EFI_ERROR (Status)) {
1208 if (!BootPolicy) {
1209 HandleFilePath = FilePath;
1210 Status = CoreLocateDevicePath (&gEfiLoadFile2ProtocolGuid, &HandleFilePath, &DeviceHandle);
1211 }
1212 if (EFI_ERROR (Status)) {
1213 HandleFilePath = FilePath;
1214 Status = CoreLocateDevicePath (&gEfiLoadFileProtocolGuid, &HandleFilePath, &DeviceHandle);
1215 if (!EFI_ERROR (Status)) {
1216 ImageIsFromLoadFile = TRUE;
1217 Node = HandleFilePath;
1218 }
1219 }
1220 }
1221 }
1222
1223 //
1224 // Get the source file buffer by its device path.
1225 //
1226 FHand.Source = GetFileBufferByFilePath (
1227 BootPolicy,
1228 FilePath,
1229 &FHand.SourceSize,
1230 &AuthenticationStatus
1231 );
1232 if (FHand.Source == NULL) {
1233 Status = EFI_NOT_FOUND;
1234 } else {
1235 FHand.FreeBuffer = TRUE;
1236 if (ImageIsFromLoadFile) {
1237 //
1238 // LoadFile () may cause the device path of the Handle be updated.
1239 //
1240 OriginalFilePath = AppendDevicePath (DevicePathFromHandle (DeviceHandle), Node);
1241 }
1242 }
1243 }
1244
1245 if (EFI_ERROR (Status)) {
1246 Image = NULL;
1247 goto Done;
1248 }
1249
1250 if (gSecurity2 != NULL) {
1251 //
1252 // Verify File Authentication through the Security2 Architectural Protocol
1253 //
1254 SecurityStatus = gSecurity2->FileAuthentication (
1255 gSecurity2,
1256 OriginalFilePath,
1257 FHand.Source,
1258 FHand.SourceSize,
1259 BootPolicy
1260 );
1261 if (!EFI_ERROR (SecurityStatus) && ImageIsFromFv) {
1262 //
1263 // When Security2 is installed, Security Architectural Protocol must be published.
1264 //
1265 ASSERT (gSecurity != NULL);
1266
1267 //
1268 // Verify the Authentication Status through the Security Architectural Protocol
1269 // Only on images that have been read using Firmware Volume protocol.
1270 //
1271 SecurityStatus = gSecurity->FileAuthenticationState (
1272 gSecurity,
1273 AuthenticationStatus,
1274 OriginalFilePath
1275 );
1276 }
1277 } else if ((gSecurity != NULL) && (OriginalFilePath != NULL)) {
1278 //
1279 // Verify the Authentication Status through the Security Architectural Protocol
1280 //
1281 SecurityStatus = gSecurity->FileAuthenticationState (
1282 gSecurity,
1283 AuthenticationStatus,
1284 OriginalFilePath
1285 );
1286 }
1287
1288 //
1289 // Check Security Status.
1290 //
1291 if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {
1292 if (SecurityStatus == EFI_ACCESS_DENIED) {
1293 //
1294 // Image was not loaded because the platform policy prohibits the image from being loaded.
1295 // It's the only place we could meet EFI_ACCESS_DENIED.
1296 //
1297 *ImageHandle = NULL;
1298 }
1299 Status = SecurityStatus;
1300 Image = NULL;
1301 goto Done;
1302 }
1303
1304 //
1305 // Allocate a new image structure
1306 //
1307 Image = AllocateZeroPool (sizeof(LOADED_IMAGE_PRIVATE_DATA));
1308 if (Image == NULL) {
1309 Status = EFI_OUT_OF_RESOURCES;
1310 goto Done;
1311 }
1312
1313 //
1314 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
1315 //
1316 FilePath = OriginalFilePath;
1317 if (DeviceHandle != NULL) {
1318 Status = CoreHandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath);
1319 if (!EFI_ERROR (Status)) {
1320 FilePathSize = GetDevicePathSize (HandleFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
1321 FilePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *)FilePath) + FilePathSize );
1322 }
1323 }
1324 //
1325 // Initialize the fields for an internal driver
1326 //
1327 Image->Signature = LOADED_IMAGE_PRIVATE_DATA_SIGNATURE;
1328 Image->Info.SystemTable = gDxeCoreST;
1329 Image->Info.DeviceHandle = DeviceHandle;
1330 Image->Info.Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
1331 Image->Info.FilePath = DuplicateDevicePath (FilePath);
1332 Image->Info.ParentHandle = ParentImageHandle;
1333
1334
1335 if (NumberOfPages != NULL) {
1336 Image->NumberOfPages = *NumberOfPages ;
1337 } else {
1338 Image->NumberOfPages = 0 ;
1339 }
1340
1341 //
1342 // Install the protocol interfaces for this image
1343 // don't fire notifications yet
1344 //
1345 Status = CoreInstallProtocolInterfaceNotify (
1346 &Image->Handle,
1347 &gEfiLoadedImageProtocolGuid,
1348 EFI_NATIVE_INTERFACE,
1349 &Image->Info,
1350 FALSE
1351 );
1352 if (EFI_ERROR (Status)) {
1353 goto Done;
1354 }
1355
1356 //
1357 // Load the image. If EntryPoint is Null, it will not be set.
1358 //
1359 Status = CoreLoadPeImage (BootPolicy, &FHand, Image, DstBuffer, EntryPoint, Attribute);
1360 if (EFI_ERROR (Status)) {
1361 if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_OUT_OF_RESOURCES)) {
1362 if (NumberOfPages != NULL) {
1363 *NumberOfPages = Image->NumberOfPages;
1364 }
1365 }
1366 goto Done;
1367 }
1368
1369 if (NumberOfPages != NULL) {
1370 *NumberOfPages = Image->NumberOfPages;
1371 }
1372
1373 //
1374 // Register the image in the Debug Image Info Table if the attribute is set
1375 //
1376 if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION) != 0) {
1377 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, &Image->Info, Image->Handle);
1378 }
1379
1380 //
1381 //Reinstall loaded image protocol to fire any notifications
1382 //
1383 Status = CoreReinstallProtocolInterface (
1384 Image->Handle,
1385 &gEfiLoadedImageProtocolGuid,
1386 &Image->Info,
1387 &Image->Info
1388 );
1389 if (EFI_ERROR (Status)) {
1390 goto Done;
1391 }
1392
1393 //
1394 // If DevicePath parameter to the LoadImage() is not NULL, then make a copy of DevicePath,
1395 // otherwise Loaded Image Device Path Protocol is installed with a NULL interface pointer.
1396 //
1397 if (OriginalFilePath != NULL) {
1398 Image->LoadedImageDevicePath = DuplicateDevicePath (OriginalFilePath);
1399 }
1400
1401 //
1402 // Install Loaded Image Device Path Protocol onto the image handle of a PE/COFE image
1403 //
1404 Status = CoreInstallProtocolInterface (
1405 &Image->Handle,
1406 &gEfiLoadedImageDevicePathProtocolGuid,
1407 EFI_NATIVE_INTERFACE,
1408 Image->LoadedImageDevicePath
1409 );
1410 if (EFI_ERROR (Status)) {
1411 goto Done;
1412 }
1413
1414 //
1415 // Install HII Package List Protocol onto the image handle
1416 //
1417 if (Image->ImageContext.HiiResourceData != 0) {
1418 Status = CoreInstallProtocolInterface (
1419 &Image->Handle,
1420 &gEfiHiiPackageListProtocolGuid,
1421 EFI_NATIVE_INTERFACE,
1422 (VOID *) (UINTN) Image->ImageContext.HiiResourceData
1423 );
1424 if (EFI_ERROR (Status)) {
1425 goto Done;
1426 }
1427 }
1428 ProtectUefiImage (&Image->Info, Image->LoadedImageDevicePath);
1429
1430 //
1431 // Success. Return the image handle
1432 //
1433 *ImageHandle = Image->Handle;
1434
1435 Done:
1436 //
1437 // All done accessing the source file
1438 // If we allocated the Source buffer, free it
1439 //
1440 if (FHand.FreeBuffer) {
1441 CoreFreePool (FHand.Source);
1442 }
1443 if (OriginalFilePath != InputFilePath) {
1444 CoreFreePool (OriginalFilePath);
1445 }
1446
1447 //
1448 // There was an error. If there's an Image structure, free it
1449 //
1450 if (EFI_ERROR (Status)) {
1451 if (Image != NULL) {
1452 CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer == 0));
1453 Image = NULL;
1454 }
1455 } else if (EFI_ERROR (SecurityStatus)) {
1456 Status = SecurityStatus;
1457 }
1458
1459 //
1460 // Track the return status from LoadImage.
1461 //
1462 if (Image != NULL) {
1463 Image->LoadImageStatus = Status;
1464 }
1465
1466 return Status;
1467 }
1468
1469
1470
1471
1472 /**
1473 Loads an EFI image into memory and returns a handle to the image.
1474
1475 @param BootPolicy If TRUE, indicates that the request originates
1476 from the boot manager, and that the boot
1477 manager is attempting to load FilePath as a
1478 boot selection.
1479 @param ParentImageHandle The caller's image handle.
1480 @param FilePath The specific file path from which the image is
1481 loaded.
1482 @param SourceBuffer If not NULL, a pointer to the memory location
1483 containing a copy of the image to be loaded.
1484 @param SourceSize The size in bytes of SourceBuffer.
1485 @param ImageHandle Pointer to the returned image handle that is
1486 created when the image is successfully loaded.
1487
1488 @retval EFI_SUCCESS The image was loaded into memory.
1489 @retval EFI_NOT_FOUND The FilePath was not found.
1490 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1491 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1492 path cannot be parsed to locate the proper
1493 protocol for loading the file.
1494 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1495 resources.
1496 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1497 understood.
1498 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1499 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1500 image from being loaded. NULL is returned in *ImageHandle.
1501 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1502 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1503 platform policy specifies that the image should not be started.
1504
1505 **/
1506 EFI_STATUS
1507 EFIAPI
CoreLoadImage(IN BOOLEAN BootPolicy,IN EFI_HANDLE ParentImageHandle,IN EFI_DEVICE_PATH_PROTOCOL * FilePath,IN VOID * SourceBuffer OPTIONAL,IN UINTN SourceSize,OUT EFI_HANDLE * ImageHandle)1508 CoreLoadImage (
1509 IN BOOLEAN BootPolicy,
1510 IN EFI_HANDLE ParentImageHandle,
1511 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
1512 IN VOID *SourceBuffer OPTIONAL,
1513 IN UINTN SourceSize,
1514 OUT EFI_HANDLE *ImageHandle
1515 )
1516 {
1517 EFI_STATUS Status;
1518 EFI_HANDLE Handle;
1519
1520 PERF_LOAD_IMAGE_BEGIN (NULL);
1521
1522 Status = CoreLoadImageCommon (
1523 BootPolicy,
1524 ParentImageHandle,
1525 FilePath,
1526 SourceBuffer,
1527 SourceSize,
1528 (EFI_PHYSICAL_ADDRESS) (UINTN) NULL,
1529 NULL,
1530 ImageHandle,
1531 NULL,
1532 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION | EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
1533 );
1534
1535 Handle = NULL;
1536 if (!EFI_ERROR (Status)) {
1537 //
1538 // ImageHandle will be valid only Status is success.
1539 //
1540 Handle = *ImageHandle;
1541 }
1542
1543 PERF_LOAD_IMAGE_END (Handle);
1544
1545 return Status;
1546 }
1547
1548 /**
1549 Transfer control to a loaded image's entry point.
1550
1551 @param ImageHandle Handle of image to be started.
1552 @param ExitDataSize Pointer of the size to ExitData
1553 @param ExitData Pointer to a pointer to a data buffer that
1554 includes a Null-terminated string,
1555 optionally followed by additional binary data.
1556 The string is a description that the caller may
1557 use to further indicate the reason for the
1558 image's exit.
1559
1560 @retval EFI_INVALID_PARAMETER Invalid parameter
1561 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1562 @retval EFI_SECURITY_VIOLATION The current platform policy specifies that the image should not be started.
1563 @retval EFI_SUCCESS Successfully transfer control to the image's
1564 entry point.
1565
1566 **/
1567 EFI_STATUS
1568 EFIAPI
CoreStartImage(IN EFI_HANDLE ImageHandle,OUT UINTN * ExitDataSize,OUT CHAR16 ** ExitData OPTIONAL)1569 CoreStartImage (
1570 IN EFI_HANDLE ImageHandle,
1571 OUT UINTN *ExitDataSize,
1572 OUT CHAR16 **ExitData OPTIONAL
1573 )
1574 {
1575 EFI_STATUS Status;
1576 LOADED_IMAGE_PRIVATE_DATA *Image;
1577 LOADED_IMAGE_PRIVATE_DATA *LastImage;
1578 UINT64 HandleDatabaseKey;
1579 UINTN SetJumpFlag;
1580 EFI_HANDLE Handle;
1581
1582 Handle = ImageHandle;
1583
1584 Image = CoreLoadedImageInfo (ImageHandle);
1585 if (Image == NULL || Image->Started) {
1586 return EFI_INVALID_PARAMETER;
1587 }
1588 if (EFI_ERROR (Image->LoadImageStatus)) {
1589 return Image->LoadImageStatus;
1590 }
1591
1592 //
1593 // The image to be started must have the machine type supported by DxeCore.
1594 //
1595 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->Machine) &&
1596 Image->PeCoffEmu == NULL) {
1597 //
1598 // Do not ASSERT here, because image might be loaded via EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED
1599 // But it can not be started.
1600 //
1601 DEBUG ((EFI_D_ERROR, "Image type %s can't be started ", GetMachineTypeName(Image->Machine)));
1602 DEBUG ((EFI_D_ERROR, "on %s UEFI system.\n", GetMachineTypeName(mDxeCoreImageMachineType)));
1603 return EFI_UNSUPPORTED;
1604 }
1605
1606 PERF_START_IMAGE_BEGIN (Handle);
1607
1608
1609 //
1610 // Push the current start image context, and
1611 // link the current image to the head. This is the
1612 // only image that can call Exit()
1613 //
1614 HandleDatabaseKey = CoreGetHandleDatabaseKey ();
1615 LastImage = mCurrentImage;
1616 mCurrentImage = Image;
1617 Image->Tpl = gEfiCurrentTpl;
1618
1619 //
1620 // Set long jump for Exit() support
1621 // JumpContext must be aligned on a CPU specific boundary.
1622 // Overallocate the buffer and force the required alignment
1623 //
1624 Image->JumpBuffer = AllocatePool (sizeof (BASE_LIBRARY_JUMP_BUFFER) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);
1625 if (Image->JumpBuffer == NULL) {
1626 //
1627 // Image may be unloaded after return with failure,
1628 // then ImageHandle may be invalid, so use NULL handle to record perf log.
1629 //
1630 PERF_START_IMAGE_END (NULL);
1631
1632 //
1633 // Pop the current start image context
1634 //
1635 mCurrentImage = LastImage;
1636
1637 return EFI_OUT_OF_RESOURCES;
1638 }
1639 Image->JumpContext = ALIGN_POINTER (Image->JumpBuffer, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);
1640
1641 SetJumpFlag = SetJump (Image->JumpContext);
1642 //
1643 // The initial call to SetJump() must always return 0.
1644 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
1645 //
1646 if (SetJumpFlag == 0) {
1647 RegisterMemoryProfileImage (Image, (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION ? EFI_FV_FILETYPE_APPLICATION : EFI_FV_FILETYPE_DRIVER));
1648 //
1649 // Call the image's entry point
1650 //
1651 Image->Started = TRUE;
1652 Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable);
1653
1654 //
1655 // Add some debug information if the image returned with error.
1656 // This make the user aware and check if the driver image have already released
1657 // all the resource in this situation.
1658 //
1659 DEBUG_CODE_BEGIN ();
1660 if (EFI_ERROR (Image->Status)) {
1661 DEBUG ((DEBUG_ERROR, "Error: Image at %11p start failed: %r\n", Image->Info.ImageBase, Image->Status));
1662 }
1663 DEBUG_CODE_END ();
1664
1665 //
1666 // If the image returns, exit it through Exit()
1667 //
1668 CoreExit (ImageHandle, Image->Status, 0, NULL);
1669 }
1670
1671 //
1672 // Image has completed. Verify the tpl is the same
1673 //
1674 ASSERT (Image->Tpl == gEfiCurrentTpl);
1675 CoreRestoreTpl (Image->Tpl);
1676
1677 CoreFreePool (Image->JumpBuffer);
1678
1679 //
1680 // Pop the current start image context
1681 //
1682 mCurrentImage = LastImage;
1683
1684 //
1685 // UEFI Specification - StartImage() - EFI 1.10 Extension
1686 // To maintain compatibility with UEFI drivers that are written to the EFI
1687 // 1.02 Specification, StartImage() must monitor the handle database before
1688 // and after each image is started. If any handles are created or modified
1689 // when an image is started, then EFI_BOOT_SERVICES.ConnectController() must
1690 // be called with the Recursive parameter set to TRUE for each of the newly
1691 // created or modified handles before StartImage() returns.
1692 //
1693 if (Image->Type != EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
1694 CoreConnectHandlesByKey (HandleDatabaseKey);
1695 }
1696
1697 //
1698 // Handle the image's returned ExitData
1699 //
1700 DEBUG_CODE_BEGIN ();
1701 if (Image->ExitDataSize != 0 || Image->ExitData != NULL) {
1702
1703 DEBUG ((DEBUG_LOAD, "StartImage: ExitDataSize %d, ExitData %p", (UINT32)Image->ExitDataSize, Image->ExitData));
1704 if (Image->ExitData != NULL) {
1705 DEBUG ((DEBUG_LOAD, " (%hs)", Image->ExitData));
1706 }
1707 DEBUG ((DEBUG_LOAD, "\n"));
1708 }
1709 DEBUG_CODE_END ();
1710
1711 //
1712 // Return the exit data to the caller
1713 //
1714 if (ExitData != NULL && ExitDataSize != NULL) {
1715 *ExitDataSize = Image->ExitDataSize;
1716 *ExitData = Image->ExitData;
1717 } else {
1718 //
1719 // Caller doesn't want the exit data, free it
1720 //
1721 CoreFreePool (Image->ExitData);
1722 Image->ExitData = NULL;
1723 }
1724
1725 //
1726 // Save the Status because Image will get destroyed if it is unloaded.
1727 //
1728 Status = Image->Status;
1729
1730 //
1731 // If the image returned an error, or if the image is an application
1732 // unload it
1733 //
1734 if (EFI_ERROR (Image->Status) || Image->Type == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
1735 CoreUnloadAndCloseImage (Image, TRUE);
1736 //
1737 // ImageHandle may be invalid after the image is unloaded, so use NULL handle to record perf log.
1738 //
1739 Handle = NULL;
1740 }
1741
1742 //
1743 // Done
1744 //
1745 PERF_START_IMAGE_END (Handle);
1746 return Status;
1747 }
1748
1749 /**
1750 Terminates the currently loaded EFI image and returns control to boot services.
1751
1752 @param ImageHandle Handle that identifies the image. This
1753 parameter is passed to the image on entry.
1754 @param Status The image's exit code.
1755 @param ExitDataSize The size, in bytes, of ExitData. Ignored if
1756 ExitStatus is EFI_SUCCESS.
1757 @param ExitData Pointer to a data buffer that includes a
1758 Null-terminated Unicode string, optionally
1759 followed by additional binary data. The string
1760 is a description that the caller may use to
1761 further indicate the reason for the image's
1762 exit.
1763
1764 @retval EFI_INVALID_PARAMETER Image handle is NULL or it is not current
1765 image.
1766 @retval EFI_SUCCESS Successfully terminates the currently loaded
1767 EFI image.
1768 @retval EFI_ACCESS_DENIED Should never reach there.
1769 @retval EFI_OUT_OF_RESOURCES Could not allocate pool
1770
1771 **/
1772 EFI_STATUS
1773 EFIAPI
CoreExit(IN EFI_HANDLE ImageHandle,IN EFI_STATUS Status,IN UINTN ExitDataSize,IN CHAR16 * ExitData OPTIONAL)1774 CoreExit (
1775 IN EFI_HANDLE ImageHandle,
1776 IN EFI_STATUS Status,
1777 IN UINTN ExitDataSize,
1778 IN CHAR16 *ExitData OPTIONAL
1779 )
1780 {
1781 LOADED_IMAGE_PRIVATE_DATA *Image;
1782 EFI_TPL OldTpl;
1783
1784 //
1785 // Prevent possible reentrance to this function
1786 // for the same ImageHandle
1787 //
1788 OldTpl = CoreRaiseTpl (TPL_NOTIFY);
1789
1790 Image = CoreLoadedImageInfo (ImageHandle);
1791 if (Image == NULL) {
1792 Status = EFI_INVALID_PARAMETER;
1793 goto Done;
1794 }
1795
1796 if (!Image->Started) {
1797 //
1798 // The image has not been started so just free its resources
1799 //
1800 CoreUnloadAndCloseImage (Image, TRUE);
1801 Status = EFI_SUCCESS;
1802 goto Done;
1803 }
1804
1805 //
1806 // Image has been started, verify this image can exit
1807 //
1808 if (Image != mCurrentImage) {
1809 DEBUG ((DEBUG_LOAD|DEBUG_ERROR, "Exit: Image is not exitable image\n"));
1810 Status = EFI_INVALID_PARAMETER;
1811 goto Done;
1812 }
1813
1814 //
1815 // Set status
1816 //
1817 Image->Status = Status;
1818
1819 //
1820 // If there's ExitData info, move it
1821 //
1822 if (ExitData != NULL) {
1823 Image->ExitDataSize = ExitDataSize;
1824 Image->ExitData = AllocatePool (Image->ExitDataSize);
1825 if (Image->ExitData == NULL) {
1826 Status = EFI_OUT_OF_RESOURCES;
1827 goto Done;
1828 }
1829 CopyMem (Image->ExitData, ExitData, Image->ExitDataSize);
1830 }
1831
1832 CoreRestoreTpl (OldTpl);
1833 //
1834 // return to StartImage
1835 //
1836 LongJump (Image->JumpContext, (UINTN)-1);
1837
1838 //
1839 // If we return from LongJump, then it is an error
1840 //
1841 ASSERT (FALSE);
1842 Status = EFI_ACCESS_DENIED;
1843 Done:
1844 CoreRestoreTpl (OldTpl);
1845 return Status;
1846 }
1847
1848
1849
1850
1851 /**
1852 Unloads an image.
1853
1854 @param ImageHandle Handle that identifies the image to be
1855 unloaded.
1856
1857 @retval EFI_SUCCESS The image has been unloaded.
1858 @retval EFI_UNSUPPORTED The image has been started, and does not support
1859 unload.
1860 @retval EFI_INVALID_PARAMPETER ImageHandle is not a valid image handle.
1861
1862 **/
1863 EFI_STATUS
1864 EFIAPI
CoreUnloadImage(IN EFI_HANDLE ImageHandle)1865 CoreUnloadImage (
1866 IN EFI_HANDLE ImageHandle
1867 )
1868 {
1869 EFI_STATUS Status;
1870 LOADED_IMAGE_PRIVATE_DATA *Image;
1871
1872 Image = CoreLoadedImageInfo (ImageHandle);
1873 if (Image == NULL ) {
1874 //
1875 // The image handle is not valid
1876 //
1877 Status = EFI_INVALID_PARAMETER;
1878 goto Done;
1879 }
1880
1881 if (Image->Started) {
1882 //
1883 // The image has been started, request it to unload.
1884 //
1885 Status = EFI_UNSUPPORTED;
1886 if (Image->Info.Unload != NULL) {
1887 Status = Image->Info.Unload (ImageHandle);
1888 }
1889
1890 } else {
1891 //
1892 // This Image hasn't been started, thus it can be unloaded
1893 //
1894 Status = EFI_SUCCESS;
1895 }
1896
1897
1898 if (!EFI_ERROR (Status)) {
1899 //
1900 // if the Image was not started or Unloaded O.K. then clean up
1901 //
1902 CoreUnloadAndCloseImage (Image, TRUE);
1903 }
1904
1905 Done:
1906 return Status;
1907 }
1908