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