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