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