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