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