]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/Image/Image.c
0d0ba5be85fdd175a4e7d1f91e99de60571f1102
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Image / Image.c
1 /** @file
2 Core image handling services to load and unload PeImage.
3
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "DxeMain.h"
10 #include "Image.h"
11
12 //
13 // Module Globals
14 //
15 LOADED_IMAGE_PRIVATE_DATA *mCurrentImage = NULL;
16
17 LOAD_PE32_IMAGE_PRIVATE_DATA mLoadPe32PrivateData = {
18 LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE,
19 NULL,
20 {
21 CoreLoadImageEx,
22 CoreUnloadImageEx
23 }
24 };
25
26
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, // Ebc
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 //
80 // EBC machine is not listed in this table, because EBC is in the default supported scopes of other machine type.
81 //
82 GLOBAL_REMOVE_IF_UNREFERENCED MACHINE_TYPE_INFO mMachineTypeInfo[] = {
83 {EFI_IMAGE_MACHINE_IA32, L"IA32"},
84 {EFI_IMAGE_MACHINE_IA64, L"IA64"},
85 {EFI_IMAGE_MACHINE_X64, L"X64"},
86 {EFI_IMAGE_MACHINE_ARMTHUMB_MIXED, L"ARM"},
87 {EFI_IMAGE_MACHINE_AARCH64, L"AARCH64"}
88 };
89
90 UINT16 mDxeCoreImageMachineType = 0;
91
92 /**
93 Return machine type name.
94
95 @param MachineType The machine type
96
97 @return machine type name
98 **/
99 CHAR16 *
100 GetMachineTypeName (
101 UINT16 MachineType
102 )
103 {
104 UINTN Index;
105
106 for (Index = 0; Index < sizeof(mMachineTypeInfo)/sizeof(mMachineTypeInfo[0]); Index++) {
107 if (mMachineTypeInfo[Index].MachineType == MachineType) {
108 return mMachineTypeInfo[Index].MachineTypeName;
109 }
110 }
111
112 return L"<Unknown>";
113 }
114
115 /**
116 Add the Image Services to EFI Boot Services Table and install the protocol
117 interfaces for this image.
118
119 @param HobStart The HOB to initialize
120
121 @return Status code.
122
123 **/
124 EFI_STATUS
125 CoreInitializeImageServices (
126 IN VOID *HobStart
127 )
128 {
129 EFI_STATUS Status;
130 LOADED_IMAGE_PRIVATE_DATA *Image;
131 EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress;
132 UINT64 DxeCoreImageLength;
133 VOID *DxeCoreEntryPoint;
134 EFI_PEI_HOB_POINTERS DxeCoreHob;
135
136 //
137 // Searching for image hob
138 //
139 DxeCoreHob.Raw = HobStart;
140 while ((DxeCoreHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, DxeCoreHob.Raw)) != NULL) {
141 if (CompareGuid (&DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) {
142 //
143 // Find Dxe Core HOB
144 //
145 break;
146 }
147 DxeCoreHob.Raw = GET_NEXT_HOB (DxeCoreHob);
148 }
149 ASSERT (DxeCoreHob.Raw != NULL);
150
151 DxeCoreImageBaseAddress = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress;
152 DxeCoreImageLength = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength;
153 DxeCoreEntryPoint = (VOID *) (UINTN) DxeCoreHob.MemoryAllocationModule->EntryPoint;
154 gDxeCoreFileName = &DxeCoreHob.MemoryAllocationModule->ModuleName;
155
156 //
157 // Initialize the fields for an internal driver
158 //
159 Image = &mCorePrivateImage;
160
161 Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)DxeCoreEntryPoint;
162 Image->ImageBasePage = DxeCoreImageBaseAddress;
163 Image->NumberOfPages = (UINTN)(EFI_SIZE_TO_PAGES((UINTN)(DxeCoreImageLength)));
164 Image->Tpl = gEfiCurrentTpl;
165 Image->Info.SystemTable = gDxeCoreST;
166 Image->Info.ImageBase = (VOID *)(UINTN)DxeCoreImageBaseAddress;
167 Image->Info.ImageSize = DxeCoreImageLength;
168
169 //
170 // Install the protocol interfaces for this image
171 //
172 Status = CoreInstallProtocolInterface (
173 &Image->Handle,
174 &gEfiLoadedImageProtocolGuid,
175 EFI_NATIVE_INTERFACE,
176 &Image->Info
177 );
178 ASSERT_EFI_ERROR (Status);
179
180 mCurrentImage = Image;
181
182 //
183 // Fill in DXE globals
184 //
185 mDxeCoreImageMachineType = PeCoffLoaderGetMachineType (Image->Info.ImageBase);
186 gDxeCoreImageHandle = Image->Handle;
187 gDxeCoreLoadedImage = &Image->Info;
188
189 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
190 //
191 // Export DXE Core PE Loader functionality for backward compatibility.
192 //
193 Status = CoreInstallProtocolInterface (
194 &mLoadPe32PrivateData.Handle,
195 &gEfiLoadPeImageProtocolGuid,
196 EFI_NATIVE_INTERFACE,
197 &mLoadPe32PrivateData.Pe32Image
198 );
199 }
200
201 ProtectUefiImage (&Image->Info, Image->LoadedImageDevicePath);
202
203 return Status;
204 }
205
206 /**
207 Read image file (specified by UserHandle) into user specified buffer with specified offset
208 and length.
209
210 @param UserHandle Image file handle
211 @param Offset Offset to the source file
212 @param ReadSize For input, pointer of size to read; For output,
213 pointer of size actually read.
214 @param Buffer Buffer to write into
215
216 @retval EFI_SUCCESS Successfully read the specified part of file
217 into buffer.
218
219 **/
220 EFI_STATUS
221 EFIAPI
222 CoreReadImageFile (
223 IN VOID *UserHandle,
224 IN UINTN Offset,
225 IN OUT UINTN *ReadSize,
226 OUT VOID *Buffer
227 )
228 {
229 UINTN EndPosition;
230 IMAGE_FILE_HANDLE *FHand;
231
232 if (UserHandle == NULL || ReadSize == NULL || Buffer == NULL) {
233 return EFI_INVALID_PARAMETER;
234 }
235
236 if (MAX_ADDRESS - Offset < *ReadSize) {
237 return EFI_INVALID_PARAMETER;
238 }
239
240 FHand = (IMAGE_FILE_HANDLE *)UserHandle;
241 ASSERT (FHand->Signature == IMAGE_FILE_HANDLE_SIGNATURE);
242
243 //
244 // Move data from our local copy of the file
245 //
246 EndPosition = Offset + *ReadSize;
247 if (EndPosition > FHand->SourceSize) {
248 *ReadSize = (UINT32)(FHand->SourceSize - Offset);
249 }
250 if (Offset >= FHand->SourceSize) {
251 *ReadSize = 0;
252 }
253
254 CopyMem (Buffer, (CHAR8 *)FHand->Source + Offset, *ReadSize);
255 return EFI_SUCCESS;
256 }
257 /**
258 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
259 memory range is available, the function will mark the corresponding bits to 1 which indicates the memory range is used.
260 The function is only invoked when load modules at fixed address feature is enabled.
261
262 @param ImageBase The base address the image will be loaded at.
263 @param ImageSize The size of the image
264
265 @retval EFI_SUCCESS The memory range the image will be loaded in is available
266 @retval EFI_NOT_FOUND The memory range the image will be loaded in is not available
267 **/
268 EFI_STATUS
269 CheckAndMarkFixLoadingMemoryUsageBitMap (
270 IN EFI_PHYSICAL_ADDRESS ImageBase,
271 IN UINTN ImageSize
272 )
273 {
274 UINT32 DxeCodePageNumber;
275 UINT64 DxeCodeSize;
276 EFI_PHYSICAL_ADDRESS DxeCodeBase;
277 UINTN BaseOffsetPageNumber;
278 UINTN TopOffsetPageNumber;
279 UINTN Index;
280 //
281 // The DXE code range includes RuntimeCodePage range and Boot time code range.
282 //
283 DxeCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);
284 DxeCodePageNumber += PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);
285 DxeCodeSize = EFI_PAGES_TO_SIZE(DxeCodePageNumber);
286 DxeCodeBase = gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress - DxeCodeSize;
287
288 //
289 // If the memory usage bit map is not initialized, do it. Every bit in the array
290 // indicate the status of the corresponding memory page, available or not
291 //
292 if (mDxeCodeMemoryRangeUsageBitMap == NULL) {
293 mDxeCodeMemoryRangeUsageBitMap = AllocateZeroPool(((DxeCodePageNumber/64) + 1)*sizeof(UINT64));
294 }
295 //
296 // If the Dxe code memory range is not allocated or the bit map array allocation failed, return EFI_NOT_FOUND
297 //
298 if (!gLoadFixedAddressCodeMemoryReady || mDxeCodeMemoryRangeUsageBitMap == NULL) {
299 return EFI_NOT_FOUND;
300 }
301 //
302 // Test the memory range for loading the image in the DXE code range.
303 //
304 if (gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress < ImageBase + ImageSize ||
305 DxeCodeBase > ImageBase) {
306 return EFI_NOT_FOUND;
307 }
308 //
309 // Test if the memory is avalaible or not.
310 //
311 BaseOffsetPageNumber = EFI_SIZE_TO_PAGES((UINT32)(ImageBase - DxeCodeBase));
312 TopOffsetPageNumber = EFI_SIZE_TO_PAGES((UINT32)(ImageBase + ImageSize - DxeCodeBase));
313 for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {
314 if ((mDxeCodeMemoryRangeUsageBitMap[Index / 64] & LShiftU64(1, (Index % 64))) != 0) {
315 //
316 // This page is already used.
317 //
318 return EFI_NOT_FOUND;
319 }
320 }
321
322 //
323 // Being here means the memory range is available. So mark the bits for the memory range
324 //
325 for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {
326 mDxeCodeMemoryRangeUsageBitMap[Index / 64] |= LShiftU64(1, (Index % 64));
327 }
328 return EFI_SUCCESS;
329 }
330 /**
331
332 Get the fixed loading address from image header assigned by build tool. This function only be called
333 when Loading module at Fixed address feature enabled.
334
335 @param ImageContext Pointer to the image context structure that describes the PE/COFF
336 image that needs to be examined by this function.
337 @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools .
338 @retval EFI_NOT_FOUND The image has no assigned fixed loading address.
339
340 **/
341 EFI_STATUS
342 GetPeCoffImageFixLoadingAssignedAddress(
343 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
344 )
345 {
346 UINTN SectionHeaderOffset;
347 EFI_STATUS Status;
348 EFI_IMAGE_SECTION_HEADER SectionHeader;
349 EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
350 UINT16 Index;
351 UINTN Size;
352 UINT16 NumberOfSections;
353 IMAGE_FILE_HANDLE *Handle;
354 UINT64 ValueInSectionHeader;
355
356
357 Status = EFI_NOT_FOUND;
358
359 //
360 // Get PeHeader pointer
361 //
362 Handle = (IMAGE_FILE_HANDLE*)ImageContext->Handle;
363 ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )Handle->Source + ImageContext->PeCoffHeaderOffset);
364 SectionHeaderOffset = ImageContext->PeCoffHeaderOffset +
365 sizeof (UINT32) +
366 sizeof (EFI_IMAGE_FILE_HEADER) +
367 ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader;
368 NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;
369
370 //
371 // Get base address from the first section header that doesn't point to code section.
372 //
373 for (Index = 0; Index < NumberOfSections; Index++) {
374 //
375 // Read section header from file
376 //
377 Size = sizeof (EFI_IMAGE_SECTION_HEADER);
378 Status = ImageContext->ImageRead (
379 ImageContext->Handle,
380 SectionHeaderOffset,
381 &Size,
382 &SectionHeader
383 );
384 if (EFI_ERROR (Status)) {
385 return Status;
386 }
387 if (Size != sizeof (EFI_IMAGE_SECTION_HEADER)) {
388 return EFI_NOT_FOUND;
389 }
390
391 Status = EFI_NOT_FOUND;
392
393 if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {
394 //
395 // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header
396 // that doesn't point to code section in image header, as well as ImageBase field of image header. And there is an
397 // assumption that when the feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations
398 // & PointerToLineNumbers fields should NOT be Zero, or else, these 2 fields should be set to Zero
399 //
400 ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations);
401 if (ValueInSectionHeader != 0) {
402 //
403 // When the feature is configured as load module at fixed absolute address, the ImageAddress field of ImageContext
404 // hold the spcified address. If the feature is configured as load module at fixed offset, ImageAddress hold an offset
405 // relative to top address
406 //
407 if ((INT64)PcdGet64(PcdLoadModuleAtFixAddressEnable) < 0) {
408 ImageContext->ImageAddress = gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress + (INT64)(INTN)ImageContext->ImageAddress;
409 }
410 //
411 // Check if the memory range is available.
412 //
413 Status = CheckAndMarkFixLoadingMemoryUsageBitMap (ImageContext->ImageAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment));
414 }
415 break;
416 }
417 SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
418 }
419 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));
420 return Status;
421 }
422 /**
423 Loads, relocates, and invokes a PE/COFF image
424
425 @param BootPolicy If TRUE, indicates that the request originates
426 from the boot manager, and that the boot
427 manager is attempting to load FilePath as a
428 boot selection.
429 @param Pe32Handle The handle of PE32 image
430 @param Image PE image to be loaded
431 @param DstBuffer The buffer to store the image
432 @param EntryPoint A pointer to the entry point
433 @param Attribute The bit mask of attributes to set for the load
434 PE image
435
436 @retval EFI_SUCCESS The file was loaded, relocated, and invoked
437 @retval EFI_OUT_OF_RESOURCES There was not enough memory to load and
438 relocate the PE/COFF file
439 @retval EFI_INVALID_PARAMETER Invalid parameter
440 @retval EFI_BUFFER_TOO_SMALL Buffer for image is too small
441
442 **/
443 EFI_STATUS
444 CoreLoadPeImage (
445 IN BOOLEAN BootPolicy,
446 IN VOID *Pe32Handle,
447 IN LOADED_IMAGE_PRIVATE_DATA *Image,
448 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
449 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
450 IN UINT32 Attribute
451 )
452 {
453 EFI_STATUS Status;
454 BOOLEAN DstBufAlocated;
455 UINTN Size;
456
457 ZeroMem (&Image->ImageContext, sizeof (Image->ImageContext));
458
459 Image->ImageContext.Handle = Pe32Handle;
460 Image->ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)CoreReadImageFile;
461
462 //
463 // Get information about the image being loaded
464 //
465 Status = PeCoffLoaderGetImageInfo (&Image->ImageContext);
466 if (EFI_ERROR (Status)) {
467 return Status;
468 }
469
470 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine)) {
471 if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image->ImageContext.Machine)) {
472 //
473 // The PE/COFF loader can support loading image types that can be executed.
474 // If we loaded an image type that we can not execute return EFI_UNSUPORTED.
475 //
476 DEBUG ((EFI_D_ERROR, "Image type %s can't be loaded ", GetMachineTypeName(Image->ImageContext.Machine)));
477 DEBUG ((EFI_D_ERROR, "on %s UEFI system.\n", GetMachineTypeName(mDxeCoreImageMachineType)));
478 return EFI_UNSUPPORTED;
479 }
480 }
481
482 //
483 // Set EFI memory type based on ImageType
484 //
485 switch (Image->ImageContext.ImageType) {
486 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:
487 Image->ImageContext.ImageCodeMemoryType = EfiLoaderCode;
488 Image->ImageContext.ImageDataMemoryType = EfiLoaderData;
489 break;
490 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
491 Image->ImageContext.ImageCodeMemoryType = EfiBootServicesCode;
492 Image->ImageContext.ImageDataMemoryType = EfiBootServicesData;
493 break;
494 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
495 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER:
496 Image->ImageContext.ImageCodeMemoryType = EfiRuntimeServicesCode;
497 Image->ImageContext.ImageDataMemoryType = EfiRuntimeServicesData;
498 break;
499 default:
500 Image->ImageContext.ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM;
501 return EFI_UNSUPPORTED;
502 }
503
504 //
505 // Allocate memory of the correct memory type aligned on the required image boundary
506 //
507 DstBufAlocated = FALSE;
508 if (DstBuffer == 0) {
509 //
510 // Allocate Destination Buffer as caller did not pass it in
511 //
512
513 if (Image->ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
514 Size = (UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment;
515 } else {
516 Size = (UINTN)Image->ImageContext.ImageSize;
517 }
518
519 Image->NumberOfPages = EFI_SIZE_TO_PAGES (Size);
520
521 //
522 // If the image relocations have not been stripped, then load at any address.
523 // Otherwise load at the address at which it was linked.
524 //
525 // Memory below 1MB should be treated reserved for CSM and there should be
526 // no modules whose preferred load addresses are below 1MB.
527 //
528 Status = EFI_OUT_OF_RESOURCES;
529 //
530 // If Loading Module At Fixed Address feature is enabled, the module should be loaded to
531 // a specified address.
532 //
533 if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 ) {
534 Status = GetPeCoffImageFixLoadingAssignedAddress (&(Image->ImageContext));
535
536 if (EFI_ERROR (Status)) {
537 //
538 // If the code memory is not ready, invoke CoreAllocatePage with AllocateAnyPages to load the driver.
539 //
540 DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED ERROR: Loading module at fixed address failed since specified memory is not available.\n"));
541
542 Status = CoreAllocatePages (
543 AllocateAnyPages,
544 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),
545 Image->NumberOfPages,
546 &Image->ImageContext.ImageAddress
547 );
548 }
549 } else {
550 if (Image->ImageContext.ImageAddress >= 0x100000 || Image->ImageContext.RelocationsStripped) {
551 Status = CoreAllocatePages (
552 AllocateAddress,
553 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),
554 Image->NumberOfPages,
555 &Image->ImageContext.ImageAddress
556 );
557 }
558 if (EFI_ERROR (Status) && !Image->ImageContext.RelocationsStripped) {
559 Status = CoreAllocatePages (
560 AllocateAnyPages,
561 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),
562 Image->NumberOfPages,
563 &Image->ImageContext.ImageAddress
564 );
565 }
566 }
567 if (EFI_ERROR (Status)) {
568 return Status;
569 }
570 DstBufAlocated = TRUE;
571 } else {
572 //
573 // Caller provided the destination buffer
574 //
575
576 if (Image->ImageContext.RelocationsStripped && (Image->ImageContext.ImageAddress != DstBuffer)) {
577 //
578 // If the image relocations were stripped, and the caller provided a
579 // destination buffer address that does not match the address that the
580 // image is linked at, then the image cannot be loaded.
581 //
582 return EFI_INVALID_PARAMETER;
583 }
584
585 if (Image->NumberOfPages != 0 &&
586 Image->NumberOfPages <
587 (EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment))) {
588 Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);
589 return EFI_BUFFER_TOO_SMALL;
590 }
591
592 Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);
593 Image->ImageContext.ImageAddress = DstBuffer;
594 }
595
596 Image->ImageBasePage = Image->ImageContext.ImageAddress;
597 if (!Image->ImageContext.IsTeImage) {
598 Image->ImageContext.ImageAddress =
599 (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &
600 ~((UINTN)Image->ImageContext.SectionAlignment - 1);
601 }
602
603 //
604 // Load the image from the file into the allocated memory
605 //
606 Status = PeCoffLoaderLoadImage (&Image->ImageContext);
607 if (EFI_ERROR (Status)) {
608 goto Done;
609 }
610
611 //
612 // If this is a Runtime Driver, then allocate memory for the FixupData that
613 // is used to relocate the image when SetVirtualAddressMap() is called. The
614 // relocation is done by the Runtime AP.
615 //
616 if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) != 0) {
617 if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
618 Image->ImageContext.FixupData = AllocateRuntimePool ((UINTN)(Image->ImageContext.FixupDataSize));
619 if (Image->ImageContext.FixupData == NULL) {
620 Status = EFI_OUT_OF_RESOURCES;
621 goto Done;
622 }
623 }
624 }
625
626 //
627 // Relocate the image in memory
628 //
629 Status = PeCoffLoaderRelocateImage (&Image->ImageContext);
630 if (EFI_ERROR (Status)) {
631 goto Done;
632 }
633
634 //
635 // Flush the Instruction Cache
636 //
637 InvalidateInstructionCacheRange ((VOID *)(UINTN)Image->ImageContext.ImageAddress, (UINTN)Image->ImageContext.ImageSize);
638
639 //
640 // Copy the machine type from the context to the image private data. This
641 // is needed during image unload to know if we should call an EBC protocol
642 // to unload the image.
643 //
644 Image->Machine = Image->ImageContext.Machine;
645
646 //
647 // Get the image entry point. If it's an EBC image, then call into the
648 // interpreter to create a thunk for the entry point and use the returned
649 // value for the entry point.
650 //
651 Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)Image->ImageContext.EntryPoint;
652 if (Image->ImageContext.Machine == EFI_IMAGE_MACHINE_EBC) {
653 //
654 // Locate the EBC interpreter protocol
655 //
656 Status = CoreLocateProtocol (&gEfiEbcProtocolGuid, NULL, (VOID **)&Image->Ebc);
657 if (EFI_ERROR(Status) || Image->Ebc == NULL) {
658 DEBUG ((DEBUG_LOAD | DEBUG_ERROR, "CoreLoadPeImage: There is no EBC interpreter for an EBC image.\n"));
659 goto Done;
660 }
661
662 //
663 // Register a callback for flushing the instruction cache so that created
664 // thunks can be flushed.
665 //
666 Status = Image->Ebc->RegisterICacheFlush (Image->Ebc, (EBC_ICACHE_FLUSH)InvalidateInstructionCacheRange);
667 if (EFI_ERROR(Status)) {
668 goto Done;
669 }
670
671 //
672 // Create a thunk for the image's entry point. This will be the new
673 // entry point for the image.
674 //
675 Status = Image->Ebc->CreateThunk (
676 Image->Ebc,
677 Image->Handle,
678 (VOID *)(UINTN) Image->ImageContext.EntryPoint,
679 (VOID **) &Image->EntryPoint
680 );
681 if (EFI_ERROR(Status)) {
682 goto Done;
683 }
684 }
685
686 //
687 // Fill in the image information for the Loaded Image Protocol
688 //
689 Image->Type = Image->ImageContext.ImageType;
690 Image->Info.ImageBase = (VOID *)(UINTN)Image->ImageContext.ImageAddress;
691 Image->Info.ImageSize = Image->ImageContext.ImageSize;
692 Image->Info.ImageCodeType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType);
693 Image->Info.ImageDataType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageDataMemoryType);
694 if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) != 0) {
695 if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
696 //
697 // Make a list off all the RT images so we can let the RT AP know about them.
698 //
699 Image->RuntimeData = AllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY));
700 if (Image->RuntimeData == NULL) {
701 goto Done;
702 }
703 Image->RuntimeData->ImageBase = Image->Info.ImageBase;
704 Image->RuntimeData->ImageSize = (UINT64) (Image->Info.ImageSize);
705 Image->RuntimeData->RelocationData = Image->ImageContext.FixupData;
706 Image->RuntimeData->Handle = Image->Handle;
707 InsertTailList (&gRuntime->ImageHead, &Image->RuntimeData->Link);
708 InsertImageRecord (Image->RuntimeData);
709 }
710 }
711
712 //
713 // Fill in the entry point of the image if it is available
714 //
715 if (EntryPoint != NULL) {
716 *EntryPoint = Image->ImageContext.EntryPoint;
717 }
718
719 //
720 // Print the load address and the PDB file name if it is available
721 //
722
723 DEBUG_CODE_BEGIN ();
724
725 UINTN Index;
726 UINTN StartIndex;
727 CHAR8 EfiFileName[256];
728
729
730 DEBUG ((DEBUG_INFO | DEBUG_LOAD,
731 "Loading driver at 0x%11p EntryPoint=0x%11p ",
732 (VOID *)(UINTN) Image->ImageContext.ImageAddress,
733 FUNCTION_ENTRY_POINT (Image->ImageContext.EntryPoint)));
734
735
736 //
737 // Print Module Name by Pdb file path.
738 // Windows and Unix style file path are all trimmed correctly.
739 //
740 if (Image->ImageContext.PdbPointer != NULL) {
741 StartIndex = 0;
742 for (Index = 0; Image->ImageContext.PdbPointer[Index] != 0; Index++) {
743 if ((Image->ImageContext.PdbPointer[Index] == '\\') || (Image->ImageContext.PdbPointer[Index] == '/')) {
744 StartIndex = Index + 1;
745 }
746 }
747 //
748 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
749 // The PDB file name is limited in the range of 0~255.
750 // If the length is bigger than 255, trim the redudant characters to avoid overflow in array boundary.
751 //
752 for (Index = 0; Index < sizeof (EfiFileName) - 4; Index++) {
753 EfiFileName[Index] = Image->ImageContext.PdbPointer[Index + StartIndex];
754 if (EfiFileName[Index] == 0) {
755 EfiFileName[Index] = '.';
756 }
757 if (EfiFileName[Index] == '.') {
758 EfiFileName[Index + 1] = 'e';
759 EfiFileName[Index + 2] = 'f';
760 EfiFileName[Index + 3] = 'i';
761 EfiFileName[Index + 4] = 0;
762 break;
763 }
764 }
765
766 if (Index == sizeof (EfiFileName) - 4) {
767 EfiFileName[Index] = 0;
768 }
769 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex]));
770 }
771 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "\n"));
772
773 DEBUG_CODE_END ();
774
775 return EFI_SUCCESS;
776
777 Done:
778
779 //
780 // Free memory.
781 //
782
783 if (DstBufAlocated) {
784 CoreFreePages (Image->ImageContext.ImageAddress, Image->NumberOfPages);
785 Image->ImageContext.ImageAddress = 0;
786 Image->ImageBasePage = 0;
787 }
788
789 if (Image->ImageContext.FixupData != NULL) {
790 CoreFreePool (Image->ImageContext.FixupData);
791 }
792
793 return Status;
794 }
795
796
797
798 /**
799 Get the image's private data from its handle.
800
801 @param ImageHandle The image handle
802
803 @return Return the image private data associated with ImageHandle.
804
805 **/
806 LOADED_IMAGE_PRIVATE_DATA *
807 CoreLoadedImageInfo (
808 IN EFI_HANDLE ImageHandle
809 )
810 {
811 EFI_STATUS Status;
812 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
813 LOADED_IMAGE_PRIVATE_DATA *Image;
814
815 Status = CoreHandleProtocol (
816 ImageHandle,
817 &gEfiLoadedImageProtocolGuid,
818 (VOID **)&LoadedImage
819 );
820 if (!EFI_ERROR (Status)) {
821 Image = LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage);
822 } else {
823 DEBUG ((DEBUG_LOAD, "CoreLoadedImageInfo: Not an ImageHandle %p\n", ImageHandle));
824 Image = NULL;
825 }
826
827 return Image;
828 }
829
830
831 /**
832 Unloads EFI image from memory.
833
834 @param Image EFI image
835 @param FreePage Free allocated pages
836
837 **/
838 VOID
839 CoreUnloadAndCloseImage (
840 IN LOADED_IMAGE_PRIVATE_DATA *Image,
841 IN BOOLEAN FreePage
842 )
843 {
844 EFI_STATUS Status;
845 UINTN HandleCount;
846 EFI_HANDLE *HandleBuffer;
847 UINTN HandleIndex;
848 EFI_GUID **ProtocolGuidArray;
849 UINTN ArrayCount;
850 UINTN ProtocolIndex;
851 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;
852 UINTN OpenInfoCount;
853 UINTN OpenInfoIndex;
854
855 HandleBuffer = NULL;
856 ProtocolGuidArray = NULL;
857
858 if (Image->Started) {
859 UnregisterMemoryProfileImage (Image);
860 }
861
862 UnprotectUefiImage (&Image->Info, Image->LoadedImageDevicePath);
863
864 if (Image->Ebc != NULL) {
865 //
866 // If EBC protocol exists we must perform cleanups for this image.
867 //
868 Image->Ebc->UnloadImage (Image->Ebc, Image->Handle);
869 }
870
871 //
872 // Unload image, free Image->ImageContext->ModHandle
873 //
874 PeCoffLoaderUnloadImage (&Image->ImageContext);
875
876 //
877 // Free our references to the image handle
878 //
879 if (Image->Handle != NULL) {
880
881 Status = CoreLocateHandleBuffer (
882 AllHandles,
883 NULL,
884 NULL,
885 &HandleCount,
886 &HandleBuffer
887 );
888 if (!EFI_ERROR (Status)) {
889 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
890 Status = CoreProtocolsPerHandle (
891 HandleBuffer[HandleIndex],
892 &ProtocolGuidArray,
893 &ArrayCount
894 );
895 if (!EFI_ERROR (Status)) {
896 for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
897 Status = CoreOpenProtocolInformation (
898 HandleBuffer[HandleIndex],
899 ProtocolGuidArray[ProtocolIndex],
900 &OpenInfo,
901 &OpenInfoCount
902 );
903 if (!EFI_ERROR (Status)) {
904 for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
905 if (OpenInfo[OpenInfoIndex].AgentHandle == Image->Handle) {
906 Status = CoreCloseProtocol (
907 HandleBuffer[HandleIndex],
908 ProtocolGuidArray[ProtocolIndex],
909 Image->Handle,
910 OpenInfo[OpenInfoIndex].ControllerHandle
911 );
912 }
913 }
914 if (OpenInfo != NULL) {
915 CoreFreePool(OpenInfo);
916 }
917 }
918 }
919 if (ProtocolGuidArray != NULL) {
920 CoreFreePool(ProtocolGuidArray);
921 }
922 }
923 }
924 if (HandleBuffer != NULL) {
925 CoreFreePool (HandleBuffer);
926 }
927 }
928
929 CoreRemoveDebugImageInfoEntry (Image->Handle);
930
931 Status = CoreUninstallProtocolInterface (
932 Image->Handle,
933 &gEfiLoadedImageDevicePathProtocolGuid,
934 Image->LoadedImageDevicePath
935 );
936
937 Status = CoreUninstallProtocolInterface (
938 Image->Handle,
939 &gEfiLoadedImageProtocolGuid,
940 &Image->Info
941 );
942
943 if (Image->ImageContext.HiiResourceData != 0) {
944 Status = CoreUninstallProtocolInterface (
945 Image->Handle,
946 &gEfiHiiPackageListProtocolGuid,
947 (VOID *) (UINTN) Image->ImageContext.HiiResourceData
948 );
949 }
950
951 }
952
953 if (Image->RuntimeData != NULL) {
954 if (Image->RuntimeData->Link.ForwardLink != NULL) {
955 //
956 // Remove the Image from the Runtime Image list as we are about to Free it!
957 //
958 RemoveEntryList (&Image->RuntimeData->Link);
959 RemoveImageRecord (Image->RuntimeData);
960 }
961 CoreFreePool (Image->RuntimeData);
962 }
963
964 //
965 // Free the Image from memory
966 //
967 if ((Image->ImageBasePage != 0) && FreePage) {
968 CoreFreePages (Image->ImageBasePage, Image->NumberOfPages);
969 }
970
971 //
972 // Done with the Image structure
973 //
974 if (Image->Info.FilePath != NULL) {
975 CoreFreePool (Image->Info.FilePath);
976 }
977
978 if (Image->LoadedImageDevicePath != NULL) {
979 CoreFreePool (Image->LoadedImageDevicePath);
980 }
981
982 if (Image->FixupData != NULL) {
983 CoreFreePool (Image->FixupData);
984 }
985
986 CoreFreePool (Image);
987 }
988
989
990 /**
991 Loads an EFI image into memory and returns a handle to the image.
992
993 @param BootPolicy If TRUE, indicates that the request originates
994 from the boot manager, and that the boot
995 manager is attempting to load FilePath as a
996 boot selection.
997 @param ParentImageHandle The caller's image handle.
998 @param FilePath The specific file path from which the image is
999 loaded.
1000 @param SourceBuffer If not NULL, a pointer to the memory location
1001 containing a copy of the image to be loaded.
1002 @param SourceSize The size in bytes of SourceBuffer.
1003 @param DstBuffer The buffer to store the image
1004 @param NumberOfPages If not NULL, it inputs a pointer to the page
1005 number of DstBuffer and outputs a pointer to
1006 the page number of the image. If this number is
1007 not enough, return EFI_BUFFER_TOO_SMALL and
1008 this parameter contains the required number.
1009 @param ImageHandle Pointer to the returned image handle that is
1010 created when the image is successfully loaded.
1011 @param EntryPoint A pointer to the entry point
1012 @param Attribute The bit mask of attributes to set for the load
1013 PE image
1014
1015 @retval EFI_SUCCESS The image was loaded into memory.
1016 @retval EFI_NOT_FOUND The FilePath was not found.
1017 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1018 @retval EFI_BUFFER_TOO_SMALL The buffer is too small
1019 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1020 path cannot be parsed to locate the proper
1021 protocol for loading the file.
1022 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1023 resources.
1024 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1025 understood.
1026 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1027 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1028 image from being loaded. NULL is returned in *ImageHandle.
1029 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1030 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1031 platform policy specifies that the image should not be started.
1032
1033 **/
1034 EFI_STATUS
1035 CoreLoadImageCommon (
1036 IN BOOLEAN BootPolicy,
1037 IN EFI_HANDLE ParentImageHandle,
1038 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
1039 IN VOID *SourceBuffer OPTIONAL,
1040 IN UINTN SourceSize,
1041 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
1042 IN OUT UINTN *NumberOfPages OPTIONAL,
1043 OUT EFI_HANDLE *ImageHandle,
1044 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
1045 IN UINT32 Attribute
1046 )
1047 {
1048 LOADED_IMAGE_PRIVATE_DATA *Image;
1049 LOADED_IMAGE_PRIVATE_DATA *ParentImage;
1050 IMAGE_FILE_HANDLE FHand;
1051 EFI_STATUS Status;
1052 EFI_STATUS SecurityStatus;
1053 EFI_HANDLE DeviceHandle;
1054 UINT32 AuthenticationStatus;
1055 EFI_DEVICE_PATH_PROTOCOL *OriginalFilePath;
1056 EFI_DEVICE_PATH_PROTOCOL *HandleFilePath;
1057 EFI_DEVICE_PATH_PROTOCOL *InputFilePath;
1058 EFI_DEVICE_PATH_PROTOCOL *Node;
1059 UINTN FilePathSize;
1060 BOOLEAN ImageIsFromFv;
1061 BOOLEAN ImageIsFromLoadFile;
1062
1063 SecurityStatus = EFI_SUCCESS;
1064
1065 ASSERT (gEfiCurrentTpl < TPL_NOTIFY);
1066 ParentImage = NULL;
1067
1068 //
1069 // The caller must pass in a valid ParentImageHandle
1070 //
1071 if (ImageHandle == NULL || ParentImageHandle == NULL) {
1072 return EFI_INVALID_PARAMETER;
1073 }
1074
1075 ParentImage = CoreLoadedImageInfo (ParentImageHandle);
1076 if (ParentImage == NULL) {
1077 DEBUG((DEBUG_LOAD|DEBUG_ERROR, "LoadImageEx: Parent handle not an image handle\n"));
1078 return EFI_INVALID_PARAMETER;
1079 }
1080
1081 ZeroMem (&FHand, sizeof (IMAGE_FILE_HANDLE));
1082 FHand.Signature = IMAGE_FILE_HANDLE_SIGNATURE;
1083 OriginalFilePath = FilePath;
1084 InputFilePath = FilePath;
1085 HandleFilePath = FilePath;
1086 DeviceHandle = NULL;
1087 Status = EFI_SUCCESS;
1088 AuthenticationStatus = 0;
1089 ImageIsFromFv = FALSE;
1090 ImageIsFromLoadFile = FALSE;
1091
1092 //
1093 // If the caller passed a copy of the file, then just use it
1094 //
1095 if (SourceBuffer != NULL) {
1096 FHand.Source = SourceBuffer;
1097 FHand.SourceSize = SourceSize;
1098 Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &HandleFilePath, &DeviceHandle);
1099 if (EFI_ERROR (Status)) {
1100 DeviceHandle = NULL;
1101 }
1102 if (SourceSize > 0) {
1103 Status = EFI_SUCCESS;
1104 } else {
1105 Status = EFI_LOAD_ERROR;
1106 }
1107 } else {
1108 if (FilePath == NULL) {
1109 return EFI_INVALID_PARAMETER;
1110 }
1111
1112 //
1113 // Try to get the image device handle by checking the match protocol.
1114 //
1115 Node = NULL;
1116 Status = CoreLocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &HandleFilePath, &DeviceHandle);
1117 if (!EFI_ERROR (Status)) {
1118 ImageIsFromFv = TRUE;
1119 } else {
1120 HandleFilePath = FilePath;
1121 Status = CoreLocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &HandleFilePath, &DeviceHandle);
1122 if (EFI_ERROR (Status)) {
1123 if (!BootPolicy) {
1124 HandleFilePath = FilePath;
1125 Status = CoreLocateDevicePath (&gEfiLoadFile2ProtocolGuid, &HandleFilePath, &DeviceHandle);
1126 }
1127 if (EFI_ERROR (Status)) {
1128 HandleFilePath = FilePath;
1129 Status = CoreLocateDevicePath (&gEfiLoadFileProtocolGuid, &HandleFilePath, &DeviceHandle);
1130 if (!EFI_ERROR (Status)) {
1131 ImageIsFromLoadFile = TRUE;
1132 Node = HandleFilePath;
1133 }
1134 }
1135 }
1136 }
1137
1138 //
1139 // Get the source file buffer by its device path.
1140 //
1141 FHand.Source = GetFileBufferByFilePath (
1142 BootPolicy,
1143 FilePath,
1144 &FHand.SourceSize,
1145 &AuthenticationStatus
1146 );
1147 if (FHand.Source == NULL) {
1148 Status = EFI_NOT_FOUND;
1149 } else {
1150 FHand.FreeBuffer = TRUE;
1151 if (ImageIsFromLoadFile) {
1152 //
1153 // LoadFile () may cause the device path of the Handle be updated.
1154 //
1155 OriginalFilePath = AppendDevicePath (DevicePathFromHandle (DeviceHandle), Node);
1156 }
1157 }
1158 }
1159
1160 if (EFI_ERROR (Status)) {
1161 Image = NULL;
1162 goto Done;
1163 }
1164
1165 if (gSecurity2 != NULL) {
1166 //
1167 // Verify File Authentication through the Security2 Architectural Protocol
1168 //
1169 SecurityStatus = gSecurity2->FileAuthentication (
1170 gSecurity2,
1171 OriginalFilePath,
1172 FHand.Source,
1173 FHand.SourceSize,
1174 BootPolicy
1175 );
1176 if (!EFI_ERROR (SecurityStatus) && ImageIsFromFv) {
1177 //
1178 // When Security2 is installed, Security Architectural Protocol must be published.
1179 //
1180 ASSERT (gSecurity != NULL);
1181
1182 //
1183 // Verify the Authentication Status through the Security Architectural Protocol
1184 // Only on images that have been read using Firmware Volume protocol.
1185 //
1186 SecurityStatus = gSecurity->FileAuthenticationState (
1187 gSecurity,
1188 AuthenticationStatus,
1189 OriginalFilePath
1190 );
1191 }
1192 } else if ((gSecurity != NULL) && (OriginalFilePath != NULL)) {
1193 //
1194 // Verify the Authentication Status through the Security Architectural Protocol
1195 //
1196 SecurityStatus = gSecurity->FileAuthenticationState (
1197 gSecurity,
1198 AuthenticationStatus,
1199 OriginalFilePath
1200 );
1201 }
1202
1203 //
1204 // Check Security Status.
1205 //
1206 if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {
1207 if (SecurityStatus == EFI_ACCESS_DENIED) {
1208 //
1209 // Image was not loaded because the platform policy prohibits the image from being loaded.
1210 // It's the only place we could meet EFI_ACCESS_DENIED.
1211 //
1212 *ImageHandle = NULL;
1213 }
1214 Status = SecurityStatus;
1215 Image = NULL;
1216 goto Done;
1217 }
1218
1219 //
1220 // Allocate a new image structure
1221 //
1222 Image = AllocateZeroPool (sizeof(LOADED_IMAGE_PRIVATE_DATA));
1223 if (Image == NULL) {
1224 Status = EFI_OUT_OF_RESOURCES;
1225 goto Done;
1226 }
1227
1228 //
1229 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
1230 //
1231 FilePath = OriginalFilePath;
1232 if (DeviceHandle != NULL) {
1233 Status = CoreHandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath);
1234 if (!EFI_ERROR (Status)) {
1235 FilePathSize = GetDevicePathSize (HandleFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
1236 FilePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *)FilePath) + FilePathSize );
1237 }
1238 }
1239 //
1240 // Initialize the fields for an internal driver
1241 //
1242 Image->Signature = LOADED_IMAGE_PRIVATE_DATA_SIGNATURE;
1243 Image->Info.SystemTable = gDxeCoreST;
1244 Image->Info.DeviceHandle = DeviceHandle;
1245 Image->Info.Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
1246 Image->Info.FilePath = DuplicateDevicePath (FilePath);
1247 Image->Info.ParentHandle = ParentImageHandle;
1248
1249
1250 if (NumberOfPages != NULL) {
1251 Image->NumberOfPages = *NumberOfPages ;
1252 } else {
1253 Image->NumberOfPages = 0 ;
1254 }
1255
1256 //
1257 // Install the protocol interfaces for this image
1258 // don't fire notifications yet
1259 //
1260 Status = CoreInstallProtocolInterfaceNotify (
1261 &Image->Handle,
1262 &gEfiLoadedImageProtocolGuid,
1263 EFI_NATIVE_INTERFACE,
1264 &Image->Info,
1265 FALSE
1266 );
1267 if (EFI_ERROR (Status)) {
1268 goto Done;
1269 }
1270
1271 //
1272 // Load the image. If EntryPoint is Null, it will not be set.
1273 //
1274 Status = CoreLoadPeImage (BootPolicy, &FHand, Image, DstBuffer, EntryPoint, Attribute);
1275 if (EFI_ERROR (Status)) {
1276 if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_OUT_OF_RESOURCES)) {
1277 if (NumberOfPages != NULL) {
1278 *NumberOfPages = Image->NumberOfPages;
1279 }
1280 }
1281 goto Done;
1282 }
1283
1284 if (NumberOfPages != NULL) {
1285 *NumberOfPages = Image->NumberOfPages;
1286 }
1287
1288 //
1289 // Register the image in the Debug Image Info Table if the attribute is set
1290 //
1291 if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION) != 0) {
1292 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, &Image->Info, Image->Handle);
1293 }
1294
1295 //
1296 //Reinstall loaded image protocol to fire any notifications
1297 //
1298 Status = CoreReinstallProtocolInterface (
1299 Image->Handle,
1300 &gEfiLoadedImageProtocolGuid,
1301 &Image->Info,
1302 &Image->Info
1303 );
1304 if (EFI_ERROR (Status)) {
1305 goto Done;
1306 }
1307
1308 //
1309 // If DevicePath parameter to the LoadImage() is not NULL, then make a copy of DevicePath,
1310 // otherwise Loaded Image Device Path Protocol is installed with a NULL interface pointer.
1311 //
1312 if (OriginalFilePath != NULL) {
1313 Image->LoadedImageDevicePath = DuplicateDevicePath (OriginalFilePath);
1314 }
1315
1316 //
1317 // Install Loaded Image Device Path Protocol onto the image handle of a PE/COFE image
1318 //
1319 Status = CoreInstallProtocolInterface (
1320 &Image->Handle,
1321 &gEfiLoadedImageDevicePathProtocolGuid,
1322 EFI_NATIVE_INTERFACE,
1323 Image->LoadedImageDevicePath
1324 );
1325 if (EFI_ERROR (Status)) {
1326 goto Done;
1327 }
1328
1329 //
1330 // Install HII Package List Protocol onto the image handle
1331 //
1332 if (Image->ImageContext.HiiResourceData != 0) {
1333 Status = CoreInstallProtocolInterface (
1334 &Image->Handle,
1335 &gEfiHiiPackageListProtocolGuid,
1336 EFI_NATIVE_INTERFACE,
1337 (VOID *) (UINTN) Image->ImageContext.HiiResourceData
1338 );
1339 if (EFI_ERROR (Status)) {
1340 goto Done;
1341 }
1342 }
1343 ProtectUefiImage (&Image->Info, Image->LoadedImageDevicePath);
1344
1345 //
1346 // Success. Return the image handle
1347 //
1348 *ImageHandle = Image->Handle;
1349
1350 Done:
1351 //
1352 // All done accessing the source file
1353 // If we allocated the Source buffer, free it
1354 //
1355 if (FHand.FreeBuffer) {
1356 CoreFreePool (FHand.Source);
1357 }
1358 if (OriginalFilePath != InputFilePath) {
1359 CoreFreePool (OriginalFilePath);
1360 }
1361
1362 //
1363 // There was an error. If there's an Image structure, free it
1364 //
1365 if (EFI_ERROR (Status)) {
1366 if (Image != NULL) {
1367 CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer == 0));
1368 Image = NULL;
1369 }
1370 } else if (EFI_ERROR (SecurityStatus)) {
1371 Status = SecurityStatus;
1372 }
1373
1374 //
1375 // Track the return status from LoadImage.
1376 //
1377 if (Image != NULL) {
1378 Image->LoadImageStatus = Status;
1379 }
1380
1381 return Status;
1382 }
1383
1384
1385
1386
1387 /**
1388 Loads an EFI image into memory and returns a handle to the image.
1389
1390 @param BootPolicy If TRUE, indicates that the request originates
1391 from the boot manager, and that the boot
1392 manager is attempting to load FilePath as a
1393 boot selection.
1394 @param ParentImageHandle The caller's image handle.
1395 @param FilePath The specific file path from which the image is
1396 loaded.
1397 @param SourceBuffer If not NULL, a pointer to the memory location
1398 containing a copy of the image to be loaded.
1399 @param SourceSize The size in bytes of SourceBuffer.
1400 @param ImageHandle Pointer to the returned image handle that is
1401 created when the image is successfully loaded.
1402
1403 @retval EFI_SUCCESS The image was loaded into memory.
1404 @retval EFI_NOT_FOUND The FilePath was not found.
1405 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1406 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1407 path cannot be parsed to locate the proper
1408 protocol for loading the file.
1409 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1410 resources.
1411 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1412 understood.
1413 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1414 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1415 image from being loaded. NULL is returned in *ImageHandle.
1416 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1417 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1418 platform policy specifies that the image should not be started.
1419
1420 **/
1421 EFI_STATUS
1422 EFIAPI
1423 CoreLoadImage (
1424 IN BOOLEAN BootPolicy,
1425 IN EFI_HANDLE ParentImageHandle,
1426 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
1427 IN VOID *SourceBuffer OPTIONAL,
1428 IN UINTN SourceSize,
1429 OUT EFI_HANDLE *ImageHandle
1430 )
1431 {
1432 EFI_STATUS Status;
1433 EFI_HANDLE Handle;
1434
1435 PERF_LOAD_IMAGE_BEGIN (NULL);
1436
1437 Status = CoreLoadImageCommon (
1438 BootPolicy,
1439 ParentImageHandle,
1440 FilePath,
1441 SourceBuffer,
1442 SourceSize,
1443 (EFI_PHYSICAL_ADDRESS) (UINTN) NULL,
1444 NULL,
1445 ImageHandle,
1446 NULL,
1447 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION | EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION
1448 );
1449
1450 Handle = NULL;
1451 if (!EFI_ERROR (Status)) {
1452 //
1453 // ImageHandle will be valid only Status is success.
1454 //
1455 Handle = *ImageHandle;
1456 }
1457
1458 PERF_LOAD_IMAGE_END (Handle);
1459
1460 return Status;
1461 }
1462
1463
1464
1465 /**
1466 Loads an EFI image into memory and returns a handle to the image with extended parameters.
1467
1468 @param This Calling context
1469 @param ParentImageHandle The caller's image handle.
1470 @param FilePath The specific file path from which the image is
1471 loaded.
1472 @param SourceBuffer If not NULL, a pointer to the memory location
1473 containing a copy of the image to be loaded.
1474 @param SourceSize The size in bytes of SourceBuffer.
1475 @param DstBuffer The buffer to store the image.
1476 @param NumberOfPages For input, specifies the space size of the
1477 image by caller if not NULL. For output,
1478 specifies the actual space size needed.
1479 @param ImageHandle Image handle for output.
1480 @param EntryPoint Image entry point for output.
1481 @param Attribute The bit mask of attributes to set for the load
1482 PE image.
1483
1484 @retval EFI_SUCCESS The image was loaded into memory.
1485 @retval EFI_NOT_FOUND The FilePath was not found.
1486 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1487 @retval EFI_UNSUPPORTED The image type is not supported, or the device
1488 path cannot be parsed to locate the proper
1489 protocol for loading the file.
1490 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient
1491 resources.
1492 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not
1493 understood.
1494 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.
1495 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the
1496 image from being loaded. NULL is returned in *ImageHandle.
1497 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a
1498 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
1499 platform policy specifies that the image should not be started.
1500
1501 **/
1502 EFI_STATUS
1503 EFIAPI
1504 CoreLoadImageEx (
1505 IN EFI_PE32_IMAGE_PROTOCOL *This,
1506 IN EFI_HANDLE ParentImageHandle,
1507 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
1508 IN VOID *SourceBuffer OPTIONAL,
1509 IN UINTN SourceSize,
1510 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
1511 OUT UINTN *NumberOfPages OPTIONAL,
1512 OUT EFI_HANDLE *ImageHandle,
1513 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
1514 IN UINT32 Attribute
1515 )
1516 {
1517 EFI_STATUS Status;
1518 EFI_HANDLE Handle;
1519
1520 PERF_LOAD_IMAGE_BEGIN (NULL);
1521
1522 Status = CoreLoadImageCommon (
1523 TRUE,
1524 ParentImageHandle,
1525 FilePath,
1526 SourceBuffer,
1527 SourceSize,
1528 DstBuffer,
1529 NumberOfPages,
1530 ImageHandle,
1531 EntryPoint,
1532 Attribute
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 /**
1550 Transfer control to a loaded image's entry point.
1551
1552 @param ImageHandle Handle of image to be started.
1553 @param ExitDataSize Pointer of the size to ExitData
1554 @param ExitData Pointer to a pointer to a data buffer that
1555 includes a Null-terminated string,
1556 optionally followed by additional binary data.
1557 The string is a description that the caller may
1558 use to further indicate the reason for the
1559 image's exit.
1560
1561 @retval EFI_INVALID_PARAMETER Invalid parameter
1562 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1563 @retval EFI_SECURITY_VIOLATION The current platform policy specifies that the image should not be started.
1564 @retval EFI_SUCCESS Successfully transfer control to the image's
1565 entry point.
1566
1567 **/
1568 EFI_STATUS
1569 EFIAPI
1570 CoreStartImage (
1571 IN EFI_HANDLE ImageHandle,
1572 OUT UINTN *ExitDataSize,
1573 OUT CHAR16 **ExitData OPTIONAL
1574 )
1575 {
1576 EFI_STATUS Status;
1577 LOADED_IMAGE_PRIVATE_DATA *Image;
1578 LOADED_IMAGE_PRIVATE_DATA *LastImage;
1579 UINT64 HandleDatabaseKey;
1580 UINTN SetJumpFlag;
1581 EFI_HANDLE Handle;
1582
1583 Handle = ImageHandle;
1584
1585 Image = CoreLoadedImageInfo (ImageHandle);
1586 if (Image == NULL || Image->Started) {
1587 return EFI_INVALID_PARAMETER;
1588 }
1589 if (EFI_ERROR (Image->LoadImageStatus)) {
1590 return Image->LoadImageStatus;
1591 }
1592
1593 //
1594 // The image to be started must have the machine type supported by DxeCore.
1595 //
1596 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->Machine)) {
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
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
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
1909
1910
1911 /**
1912 Unload the specified image.
1913
1914 @param This Indicates the calling context.
1915 @param ImageHandle The specified image handle.
1916
1917 @retval EFI_INVALID_PARAMETER Image handle is NULL.
1918 @retval EFI_UNSUPPORTED Attempt to unload an unsupported image.
1919 @retval EFI_SUCCESS Image successfully unloaded.
1920
1921 **/
1922 EFI_STATUS
1923 EFIAPI
1924 CoreUnloadImageEx (
1925 IN EFI_PE32_IMAGE_PROTOCOL *This,
1926 IN EFI_HANDLE ImageHandle
1927 )
1928 {
1929 return CoreUnloadImage (ImageHandle);
1930 }