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