]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Image/Image.c
Apply GetFileBufferByFilePath API of DxeServicesLib to replace local CoreOpenImageFil...
[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
7748df3d 4Copyright (c) 2006 - 2009, Intel Corporation. <BR>\r
28a00297 5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
504214c4 13**/\r
28a00297 14\r
9c4ac31c 15#include "DxeMain.h"\r
ec90508b 16#include "Image.h"\r
17\r
28a00297 18//\r
19// Module Globals\r
20//\r
28a00297 21LOADED_IMAGE_PRIVATE_DATA *mCurrentImage = NULL;\r
22\r
023c0fec 23LOAD_PE32_IMAGE_PRIVATE_DATA mLoadPe32PrivateData = {\r
24 LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE,\r
25 NULL,\r
26 {\r
27 CoreLoadImageEx,\r
28 CoreUnloadImageEx\r
29 }\r
30};\r
31\r
28a00297 32\r
33//\r
34// This code is needed to build the Image handle for the DXE Core\r
35//\r
36LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage = {\r
37 LOADED_IMAGE_PRIVATE_DATA_SIGNATURE, // Signature\r
38 NULL, // Image handle\r
39 EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, // Image type\r
40 TRUE, // If entrypoint has been called\r
41 NULL, // EntryPoint\r
42 {\r
43 EFI_LOADED_IMAGE_INFORMATION_REVISION, // Revision\r
44 NULL, // Parent handle\r
45 NULL, // System handle\r
46\r
47 NULL, // Device handle\r
48 NULL, // File path\r
49 NULL, // Reserved\r
50\r
51 0, // LoadOptionsSize\r
52 NULL, // LoadOptions\r
53\r
54 NULL, // ImageBase\r
55 0, // ImageSize\r
56 EfiBootServicesCode, // ImageCodeType\r
57 EfiBootServicesData // ImageDataType\r
58 },\r
59 (EFI_PHYSICAL_ADDRESS)0, // ImageBasePage\r
60 0, // NumberOfPages\r
61 NULL, // FixupData\r
62 0, // Tpl\r
63 EFI_SUCCESS, // Status\r
64 0, // ExitDataSize\r
65 NULL, // ExitData\r
66 NULL, // JumpBuffer\r
67 NULL, // JumpContext\r
68 0, // Machine\r
69 NULL, // Ebc\r
70 NULL, // RuntimeData\r
ba39e316 71 NULL // LoadedImageDevicePath\r
28a00297 72};\r
73\r
74\r
28a00297 75\r
162ed594 76/**\r
28a00297 77 Add the Image Services to EFI Boot Services Table and install the protocol\r
78 interfaces for this image.\r
79\r
57d6f36d 80 @param HobStart The HOB to initialize\r
28a00297 81\r
162ed594 82 @return Status code.\r
28a00297 83\r
162ed594 84**/\r
85EFI_STATUS\r
86CoreInitializeImageServices (\r
87 IN VOID *HobStart\r
88 )\r
28a00297 89{\r
90 EFI_STATUS Status;\r
91 LOADED_IMAGE_PRIVATE_DATA *Image;\r
92 EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress;\r
93 UINT64 DxeCoreImageLength;\r
94 VOID *DxeCoreEntryPoint;\r
95 EFI_PEI_HOB_POINTERS DxeCoreHob;\r
96 //\r
97 // Searching for image hob\r
98 //\r
99 DxeCoreHob.Raw = HobStart;\r
100 while ((DxeCoreHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, DxeCoreHob.Raw)) != NULL) {\r
101 if (CompareGuid (&DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) {\r
102 //\r
103 // Find Dxe Core HOB\r
104 //\r
105 break;\r
106 }\r
107 DxeCoreHob.Raw = GET_NEXT_HOB (DxeCoreHob);\r
108 }\r
109 ASSERT (DxeCoreHob.Raw != NULL);\r
110\r
111 DxeCoreImageBaseAddress = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress;\r
112 DxeCoreImageLength = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength;\r
113 DxeCoreEntryPoint = (VOID *) (UINTN) DxeCoreHob.MemoryAllocationModule->EntryPoint;\r
114 gDxeCoreFileName = &DxeCoreHob.MemoryAllocationModule->ModuleName;\r
115 //\r
116 // Initialize the fields for an internal driver\r
117 //\r
118 Image = &mCorePrivateImage;\r
119\r
120 Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)DxeCoreEntryPoint;\r
121 Image->ImageBasePage = DxeCoreImageBaseAddress;\r
122 Image->NumberOfPages = (UINTN)(EFI_SIZE_TO_PAGES((UINTN)(DxeCoreImageLength)));\r
123 Image->Tpl = gEfiCurrentTpl;\r
124 Image->Info.SystemTable = gDxeCoreST;\r
125 Image->Info.ImageBase = (VOID *)(UINTN)DxeCoreImageBaseAddress;\r
126 Image->Info.ImageSize = DxeCoreImageLength;\r
127\r
128 //\r
129 // Install the protocol interfaces for this image\r
130 //\r
131 Status = CoreInstallProtocolInterface (\r
132 &Image->Handle,\r
133 &gEfiLoadedImageProtocolGuid,\r
134 EFI_NATIVE_INTERFACE,\r
135 &Image->Info\r
136 );\r
137 ASSERT_EFI_ERROR (Status);\r
138\r
139 mCurrentImage = Image;\r
140\r
141 //\r
142 // Fill in DXE globals\r
143 //\r
144 gDxeCoreImageHandle = Image->Handle;\r
145 gDxeCoreLoadedImage = &Image->Info;\r
146\r
147 //\r
148 // Export DXE Core PE Loader functionality\r
149 //\r
023c0fec 150 return CoreInstallProtocolInterface (\r
151 &mLoadPe32PrivateData.Handle,\r
152 &gEfiLoadPeImageProtocolGuid,\r
153 EFI_NATIVE_INTERFACE,\r
154 &mLoadPe32PrivateData.Pe32Image\r
155 );\r
28a00297 156}\r
157\r
7748df3d
LG
158/**\r
159 Read image file (specified by UserHandle) into user specified buffer with specified offset\r
160 and length.\r
161\r
162 @param UserHandle Image file handle\r
163 @param Offset Offset to the source file\r
164 @param ReadSize For input, pointer of size to read; For output,\r
165 pointer of size actually read.\r
166 @param Buffer Buffer to write into\r
167\r
168 @retval EFI_SUCCESS Successfully read the specified part of file\r
169 into buffer.\r
170\r
171**/\r
172EFI_STATUS\r
173EFIAPI\r
174CoreReadImageFile (\r
175 IN VOID *UserHandle,\r
176 IN UINTN Offset,\r
177 IN OUT UINTN *ReadSize,\r
178 OUT VOID *Buffer\r
179 )\r
180{\r
181 UINTN EndPosition;\r
182 IMAGE_FILE_HANDLE *FHand;\r
183\r
184 FHand = (IMAGE_FILE_HANDLE *)UserHandle;\r
185 ASSERT (FHand->Signature == IMAGE_FILE_HANDLE_SIGNATURE);\r
186\r
187 //\r
188 // Move data from our local copy of the file\r
189 //\r
190 EndPosition = Offset + *ReadSize;\r
191 if (EndPosition > FHand->SourceSize) {\r
192 *ReadSize = (UINT32)(FHand->SourceSize - Offset);\r
193 }\r
194 if (Offset >= FHand->SourceSize) {\r
195 *ReadSize = 0;\r
196 }\r
197\r
198 CopyMem (Buffer, (CHAR8 *)FHand->Source + Offset, *ReadSize);\r
199 return EFI_SUCCESS;\r
200}\r
162ed594 201\r
202/**\r
203 Loads, relocates, and invokes a PE/COFF image\r
204\r
57d6f36d 205 @param BootPolicy If TRUE, indicates that the request originates\r
206 from the boot manager, and that the boot\r
207 manager is attempting to load FilePath as a\r
208 boot selection.\r
209 @param Pe32Handle The handle of PE32 image\r
210 @param Image PE image to be loaded\r
211 @param DstBuffer The buffer to store the image\r
212 @param EntryPoint A pointer to the entry point\r
213 @param Attribute The bit mask of attributes to set for the load\r
214 PE image\r
215\r
216 @retval EFI_SUCCESS The file was loaded, relocated, and invoked\r
217 @retval EFI_OUT_OF_RESOURCES There was not enough memory to load and\r
218 relocate the PE/COFF file\r
219 @retval EFI_INVALID_PARAMETER Invalid parameter\r
162ed594 220 @retval EFI_BUFFER_TOO_SMALL Buffer for image is too small\r
221\r
222**/\r
28a00297 223EFI_STATUS\r
224CoreLoadPeImage (\r
57d6f36d 225 IN BOOLEAN BootPolicy,\r
28a00297 226 IN VOID *Pe32Handle,\r
227 IN LOADED_IMAGE_PRIVATE_DATA *Image,\r
228 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,\r
229 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,\r
230 IN UINT32 Attribute\r
231 )\r
28a00297 232{\r
822360ee
LG
233 EFI_STATUS Status;\r
234 BOOLEAN DstBufAlocated;\r
235 UINTN Size;\r
28a00297 236\r
237 ZeroMem (&Image->ImageContext, sizeof (Image->ImageContext));\r
238\r
239 Image->ImageContext.Handle = Pe32Handle;\r
240 Image->ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)CoreReadImageFile;\r
241\r
242 //\r
243 // Get information about the image being loaded\r
244 //\r
3d7b0992 245 Status = PeCoffLoaderGetImageInfo (&Image->ImageContext);\r
28a00297 246 if (EFI_ERROR (Status)) {\r
247 return Status;\r
248 }\r
249\r
250 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine)) {\r
5fed8e34 251 if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image->ImageContext.Machine)) {\r
252 //\r
253 // The PE/COFF loader can support loading image types that can be executed.\r
254 // If we loaded an image type that we can not execute return EFI_UNSUPORTED.\r
255 //\r
256 return EFI_UNSUPPORTED;\r
257 }\r
28a00297 258 }\r
57d6f36d 259\r
a0ae8996
LG
260 //\r
261 // Set EFI memory type based on ImageType\r
262 //\r
263 switch (Image->ImageContext.ImageType) {\r
264 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:\r
265 Image->ImageContext.ImageCodeMemoryType = EfiLoaderCode;\r
266 Image->ImageContext.ImageDataMemoryType = EfiLoaderData;\r
267 break;\r
268 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:\r
269 Image->ImageContext.ImageCodeMemoryType = EfiBootServicesCode;\r
270 Image->ImageContext.ImageDataMemoryType = EfiBootServicesData;\r
271 break;\r
272 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:\r
273 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER:\r
274 Image->ImageContext.ImageCodeMemoryType = EfiRuntimeServicesCode;\r
275 Image->ImageContext.ImageDataMemoryType = EfiRuntimeServicesData;\r
276 break;\r
277 default:\r
278 Image->ImageContext.ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM;\r
279 return EFI_UNSUPPORTED;\r
280 }\r
28a00297 281\r
282 //\r
283 // Allocate memory of the correct memory type aligned on the required image boundry\r
284 //\r
285 DstBufAlocated = FALSE;\r
286 if (DstBuffer == 0) {\r
287 //\r
288 // Allocate Destination Buffer as caller did not pass it in\r
289 //\r
290\r
291 if (Image->ImageContext.SectionAlignment > EFI_PAGE_SIZE) {\r
292 Size = (UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment;\r
293 } else {\r
294 Size = (UINTN)Image->ImageContext.ImageSize;\r
295 }\r
296\r
297 Image->NumberOfPages = EFI_SIZE_TO_PAGES (Size);\r
298\r
299 //\r
300 // If the image relocations have not been stripped, then load at any address.\r
301 // Otherwise load at the address at which it was linked.\r
302 //\r
303 // Memory below 1MB should be treated reserved for CSM and there should be\r
304 // no modules whose preferred load addresses are below 1MB.\r
305 //\r
306 Status = EFI_OUT_OF_RESOURCES;\r
307 if (Image->ImageContext.ImageAddress >= 0x100000 || Image->ImageContext.RelocationsStripped) {\r
308 Status = CoreAllocatePages (\r
309 AllocateAddress,\r
310 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
311 Image->NumberOfPages,\r
312 &Image->ImageContext.ImageAddress\r
313 );\r
314 }\r
315 if (EFI_ERROR (Status) && !Image->ImageContext.RelocationsStripped) {\r
316 Status = CoreAllocatePages (\r
317 AllocateAnyPages,\r
318 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
319 Image->NumberOfPages,\r
320 &Image->ImageContext.ImageAddress\r
321 );\r
322 }\r
323 if (EFI_ERROR (Status)) {\r
324 return Status;\r
325 }\r
326 DstBufAlocated = TRUE;\r
327 } else {\r
328 //\r
329 // Caller provided the destination buffer\r
330 //\r
331\r
332 if (Image->ImageContext.RelocationsStripped && (Image->ImageContext.ImageAddress != DstBuffer)) {\r
333 //\r
334 // If the image relocations were stripped, and the caller provided a\r
335 // destination buffer address that does not match the address that the\r
336 // image is linked at, then the image cannot be loaded.\r
337 //\r
338 return EFI_INVALID_PARAMETER;\r
339 }\r
340\r
341 if (Image->NumberOfPages != 0 &&\r
342 Image->NumberOfPages <\r
343 (EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment))) {\r
344 Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);\r
345 return EFI_BUFFER_TOO_SMALL;\r
346 }\r
347\r
348 Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);\r
349 Image->ImageContext.ImageAddress = DstBuffer;\r
350 }\r
351\r
352 Image->ImageBasePage = Image->ImageContext.ImageAddress;\r
1046284d
LG
353 if (!Image->ImageContext.IsTeImage) {\r
354 Image->ImageContext.ImageAddress =\r
355 (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &\r
356 ~((UINTN)Image->ImageContext.SectionAlignment - 1);\r
357 }\r
28a00297 358\r
359 //\r
360 // Load the image from the file into the allocated memory\r
361 //\r
3d7b0992 362 Status = PeCoffLoaderLoadImage (&Image->ImageContext);\r
28a00297 363 if (EFI_ERROR (Status)) {\r
364 goto Done;\r
365 }\r
366\r
367 //\r
368 // If this is a Runtime Driver, then allocate memory for the FixupData that\r
369 // is used to relocate the image when SetVirtualAddressMap() is called. The\r
370 // relocation is done by the Runtime AP.\r
371 //\r
71f68914 372 if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) != 0) {\r
28a00297 373 if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {\r
9c4ac31c 374 Image->ImageContext.FixupData = AllocateRuntimePool ((UINTN)(Image->ImageContext.FixupDataSize));\r
28a00297 375 if (Image->ImageContext.FixupData == NULL) {\r
376 Status = EFI_OUT_OF_RESOURCES;\r
377 goto Done;\r
378 }\r
379 }\r
380 }\r
381\r
382 //\r
383 // Relocate the image in memory\r
384 //\r
3d7b0992 385 Status = PeCoffLoaderRelocateImage (&Image->ImageContext);\r
28a00297 386 if (EFI_ERROR (Status)) {\r
387 goto Done;\r
388 }\r
389\r
390 //\r
391 // Flush the Instruction Cache\r
392 //\r
393 InvalidateInstructionCacheRange ((VOID *)(UINTN)Image->ImageContext.ImageAddress, (UINTN)Image->ImageContext.ImageSize);\r
394\r
395 //\r
396 // Copy the machine type from the context to the image private data. This\r
397 // is needed during image unload to know if we should call an EBC protocol\r
398 // to unload the image.\r
399 //\r
400 Image->Machine = Image->ImageContext.Machine;\r
401\r
402 //\r
403 // Get the image entry point. If it's an EBC image, then call into the\r
404 // interpreter to create a thunk for the entry point and use the returned\r
405 // value for the entry point.\r
406 //\r
407 Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)Image->ImageContext.EntryPoint;\r
408 if (Image->ImageContext.Machine == EFI_IMAGE_MACHINE_EBC) {\r
409 //\r
410 // Locate the EBC interpreter protocol\r
411 //\r
412 Status = CoreLocateProtocol (&gEfiEbcProtocolGuid, NULL, (VOID **)&Image->Ebc);\r
413 if (EFI_ERROR(Status)) {\r
57d6f36d 414 DEBUG ((DEBUG_LOAD | DEBUG_ERROR, "CoreLoadPeImage: There is no EBC interpreter for an EBC image.\n"));\r
28a00297 415 goto Done;\r
416 }\r
417\r
418 //\r
419 // Register a callback for flushing the instruction cache so that created\r
420 // thunks can be flushed.\r
421 //\r
422 Status = Image->Ebc->RegisterICacheFlush (Image->Ebc, (EBC_ICACHE_FLUSH)InvalidateInstructionCacheRange);\r
423 if (EFI_ERROR(Status)) {\r
424 goto Done;\r
425 }\r
426\r
427 //\r
428 // Create a thunk for the image's entry point. This will be the new\r
429 // entry point for the image.\r
430 //\r
431 Status = Image->Ebc->CreateThunk (\r
432 Image->Ebc,\r
433 Image->Handle,\r
e94a9ff7 434 (VOID *)(UINTN) Image->ImageContext.EntryPoint,\r
435 (VOID **) &Image->EntryPoint\r
28a00297 436 );\r
437 if (EFI_ERROR(Status)) {\r
438 goto Done;\r
439 }\r
440 }\r
441\r
442 //\r
443 // Fill in the image information for the Loaded Image Protocol\r
444 //\r
445 Image->Type = Image->ImageContext.ImageType;\r
446 Image->Info.ImageBase = (VOID *)(UINTN)Image->ImageContext.ImageAddress;\r
447 Image->Info.ImageSize = Image->ImageContext.ImageSize;\r
448 Image->Info.ImageCodeType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType);\r
449 Image->Info.ImageDataType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageDataMemoryType);\r
71f68914 450 if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) != 0) {\r
28a00297 451 if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {\r
452 //\r
453 // Make a list off all the RT images so we can let the RT AP know about them.\r
454 //\r
9c4ac31c 455 Image->RuntimeData = AllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY));\r
28a00297 456 if (Image->RuntimeData == NULL) {\r
457 goto Done;\r
458 }\r
459 Image->RuntimeData->ImageBase = Image->Info.ImageBase;\r
460 Image->RuntimeData->ImageSize = (UINT64) (Image->Info.ImageSize);\r
461 Image->RuntimeData->RelocationData = Image->ImageContext.FixupData;\r
462 Image->RuntimeData->Handle = Image->Handle;\r
463 InsertTailList (&gRuntime->ImageHead, &Image->RuntimeData->Link);\r
464 }\r
465 }\r
466\r
467 //\r
468 // Fill in the entry point of the image if it is available\r
469 //\r
470 if (EntryPoint != NULL) {\r
471 *EntryPoint = Image->ImageContext.EntryPoint;\r
472 }\r
473\r
474 //\r
475 // Print the load address and the PDB file name if it is available\r
476 //\r
477\r
478 DEBUG_CODE_BEGIN ();\r
479\r
480 UINTN Index;\r
481 UINTN StartIndex;\r
482 CHAR8 EfiFileName[256];\r
57d6f36d 483\r
022c6d45 484\r
e94a9ff7 485 DEBUG ((DEBUG_INFO | DEBUG_LOAD,\r
91136124 486 "Loading driver at 0x%11p EntryPoint=0x%11p ",\r
e94a9ff7 487 (VOID *)(UINTN) Image->ImageContext.ImageAddress,\r
4e2dd553 488 FUNCTION_ENTRY_POINT (Image->ImageContext.EntryPoint)));\r
022c6d45 489\r
57d6f36d 490\r
e98cd821 491 //\r
57dfc48f 492 // Print Module Name by Pdb file path.\r
493 // Windows and Unix style file path are all trimmed correctly.\r
e98cd821 494 //\r
28a00297 495 if (Image->ImageContext.PdbPointer != NULL) {\r
496 StartIndex = 0;\r
497 for (Index = 0; Image->ImageContext.PdbPointer[Index] != 0; Index++) {\r
57dfc48f 498 if ((Image->ImageContext.PdbPointer[Index] == '\\') || (Image->ImageContext.PdbPointer[Index] == '/')) {\r
28a00297 499 StartIndex = Index + 1;\r
500 }\r
501 }\r
502 //\r
503 // Copy the PDB file name to our temporary string, and replace .pdb with .efi\r
57dfc48f 504 // The PDB file name is limited in the range of 0~255.\r
505 // If the length is bigger than 255, trim the redudant characters to avoid overflow in array boundary.\r
28a00297 506 //\r
57dfc48f 507 for (Index = 0; Index < sizeof (EfiFileName) - 4; Index++) {\r
28a00297 508 EfiFileName[Index] = Image->ImageContext.PdbPointer[Index + StartIndex];\r
509 if (EfiFileName[Index] == 0) {\r
510 EfiFileName[Index] = '.';\r
511 }\r
512 if (EfiFileName[Index] == '.') {\r
513 EfiFileName[Index + 1] = 'e';\r
514 EfiFileName[Index + 2] = 'f';\r
515 EfiFileName[Index + 3] = 'i';\r
516 EfiFileName[Index + 4] = 0;\r
517 break;\r
518 }\r
519 }\r
57dfc48f 520\r
521 if (Index == sizeof (EfiFileName) - 4) {\r
522 EfiFileName[Index] = 0;\r
523 }\r
162ed594 524 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex]));\r
28a00297 525 }\r
162ed594 526 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "\n"));\r
28a00297 527\r
528 DEBUG_CODE_END ();\r
529\r
530 return EFI_SUCCESS;\r
531\r
532Done:\r
533\r
534 //\r
535 // Free memory.\r
536 //\r
537\r
538 if (DstBufAlocated) {\r
539 CoreFreePages (Image->ImageContext.ImageAddress, Image->NumberOfPages);\r
540 }\r
541\r
542 if (Image->ImageContext.FixupData != NULL) {\r
543 CoreFreePool (Image->ImageContext.FixupData);\r
544 }\r
545\r
546 return Status;\r
547}\r
548\r
549\r
28a00297 550\r
162ed594 551/**\r
28a00297 552 Get the image's private data from its handle.\r
553\r
57d6f36d 554 @param ImageHandle The image handle\r
28a00297 555\r
162ed594 556 @return Return the image private data associated with ImageHandle.\r
28a00297 557\r
162ed594 558**/\r
559LOADED_IMAGE_PRIVATE_DATA *\r
560CoreLoadedImageInfo (\r
561 IN EFI_HANDLE ImageHandle\r
562 )\r
28a00297 563{\r
564 EFI_STATUS Status;\r
565 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
566 LOADED_IMAGE_PRIVATE_DATA *Image;\r
567\r
568 Status = CoreHandleProtocol (\r
569 ImageHandle,\r
570 &gEfiLoadedImageProtocolGuid,\r
571 (VOID **)&LoadedImage\r
572 );\r
573 if (!EFI_ERROR (Status)) {\r
574 Image = LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage);\r
575 } else {\r
e94a9ff7 576 DEBUG ((DEBUG_LOAD, "CoreLoadedImageInfo: Not an ImageHandle %p\n", ImageHandle));\r
28a00297 577 Image = NULL;\r
578 }\r
579\r
580 return Image;\r
581}\r
582\r
162ed594 583\r
c0a23f8c 584/**\r
585 Unloads EFI image from memory.\r
586\r
587 @param Image EFI image\r
588 @param FreePage Free allocated pages\r
589\r
590**/\r
591VOID\r
592CoreUnloadAndCloseImage (\r
593 IN LOADED_IMAGE_PRIVATE_DATA *Image,\r
594 IN BOOLEAN FreePage\r
595 )\r
596{\r
597 EFI_STATUS Status;\r
598 UINTN HandleCount;\r
599 EFI_HANDLE *HandleBuffer;\r
600 UINTN HandleIndex;\r
601 EFI_GUID **ProtocolGuidArray;\r
602 UINTN ArrayCount;\r
603 UINTN ProtocolIndex;\r
604 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;\r
605 UINTN OpenInfoCount;\r
606 UINTN OpenInfoIndex;\r
607\r
608 if (Image->Ebc != NULL) {\r
609 //\r
610 // If EBC protocol exists we must perform cleanups for this image.\r
611 //\r
612 Image->Ebc->UnloadImage (Image->Ebc, Image->Handle);\r
613 }\r
614\r
615 //\r
616 // Unload image, free Image->ImageContext->ModHandle\r
617 //\r
618 PeCoffLoaderUnloadImage (&Image->ImageContext);\r
619\r
620 //\r
621 // Free our references to the image handle\r
622 //\r
623 if (Image->Handle != NULL) {\r
624\r
625 Status = CoreLocateHandleBuffer (\r
626 AllHandles,\r
627 NULL,\r
628 NULL,\r
629 &HandleCount,\r
630 &HandleBuffer\r
631 );\r
632 if (!EFI_ERROR (Status)) {\r
633 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {\r
634 Status = CoreProtocolsPerHandle (\r
635 HandleBuffer[HandleIndex],\r
636 &ProtocolGuidArray,\r
637 &ArrayCount\r
638 );\r
639 if (!EFI_ERROR (Status)) {\r
640 for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {\r
641 Status = CoreOpenProtocolInformation (\r
642 HandleBuffer[HandleIndex],\r
643 ProtocolGuidArray[ProtocolIndex],\r
644 &OpenInfo,\r
645 &OpenInfoCount\r
646 );\r
647 if (!EFI_ERROR (Status)) {\r
648 for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {\r
649 if (OpenInfo[OpenInfoIndex].AgentHandle == Image->Handle) {\r
650 Status = CoreCloseProtocol (\r
651 HandleBuffer[HandleIndex],\r
652 ProtocolGuidArray[ProtocolIndex],\r
653 Image->Handle,\r
654 OpenInfo[OpenInfoIndex].ControllerHandle\r
655 );\r
656 }\r
657 }\r
658 if (OpenInfo != NULL) {\r
659 CoreFreePool(OpenInfo);\r
660 }\r
661 }\r
662 }\r
663 if (ProtocolGuidArray != NULL) {\r
664 CoreFreePool(ProtocolGuidArray);\r
665 }\r
666 }\r
667 }\r
668 if (HandleBuffer != NULL) {\r
669 CoreFreePool (HandleBuffer);\r
670 }\r
671 }\r
672\r
673 CoreRemoveDebugImageInfoEntry (Image->Handle);\r
674\r
675 Status = CoreUninstallProtocolInterface (\r
676 Image->Handle,\r
677 &gEfiLoadedImageDevicePathProtocolGuid,\r
678 Image->LoadedImageDevicePath\r
679 );\r
680\r
681 Status = CoreUninstallProtocolInterface (\r
682 Image->Handle,\r
683 &gEfiLoadedImageProtocolGuid,\r
684 &Image->Info\r
685 );\r
686\r
7547649f 687 if (Image->ImageContext.HiiResourceData != 0) {\r
688 Status = CoreUninstallProtocolInterface (\r
689 Image->Handle,\r
690 &gEfiHiiPackageListProtocolGuid,\r
691 (VOID *) (UINTN) Image->ImageContext.HiiResourceData\r
692 );\r
693 }\r
694\r
c0a23f8c 695 }\r
696\r
697 if (Image->RuntimeData != NULL) {\r
698 if (Image->RuntimeData->Link.ForwardLink != NULL) {\r
699 //\r
700 // Remove the Image from the Runtime Image list as we are about to Free it!\r
701 //\r
702 RemoveEntryList (&Image->RuntimeData->Link);\r
703 }\r
704 CoreFreePool (Image->RuntimeData);\r
705 }\r
706\r
707 //\r
708 // Free the Image from memory\r
709 //\r
710 if ((Image->ImageBasePage != 0) && FreePage) {\r
711 CoreFreePages (Image->ImageBasePage, Image->NumberOfPages);\r
712 }\r
713\r
714 //\r
715 // Done with the Image structure\r
716 //\r
717 if (Image->Info.FilePath != NULL) {\r
718 CoreFreePool (Image->Info.FilePath);\r
719 }\r
720\r
721 if (Image->LoadedImageDevicePath != NULL) {\r
722 CoreFreePool (Image->LoadedImageDevicePath);\r
723 }\r
724\r
725 if (Image->FixupData != NULL) {\r
726 CoreFreePool (Image->FixupData);\r
727 }\r
728\r
729 CoreFreePool (Image);\r
730}\r
731\r
732\r
162ed594 733/**\r
734 Loads an EFI image into memory and returns a handle to the image.\r
735\r
57d6f36d 736 @param BootPolicy If TRUE, indicates that the request originates\r
737 from the boot manager, and that the boot\r
738 manager is attempting to load FilePath as a\r
739 boot selection.\r
740 @param ParentImageHandle The caller's image handle.\r
741 @param FilePath The specific file path from which the image is\r
742 loaded.\r
743 @param SourceBuffer If not NULL, a pointer to the memory location\r
744 containing a copy of the image to be loaded.\r
745 @param SourceSize The size in bytes of SourceBuffer.\r
746 @param DstBuffer The buffer to store the image\r
747 @param NumberOfPages If not NULL, it inputs a pointer to the page\r
748 number of DstBuffer and outputs a pointer to\r
749 the page number of the image. If this number is\r
750 not enough, return EFI_BUFFER_TOO_SMALL and\r
751 this parameter contains the required number.\r
752 @param ImageHandle Pointer to the returned image handle that is\r
753 created when the image is successfully loaded.\r
754 @param EntryPoint A pointer to the entry point\r
755 @param Attribute The bit mask of attributes to set for the load\r
756 PE image\r
757\r
758 @retval EFI_SUCCESS The image was loaded into memory.\r
759 @retval EFI_NOT_FOUND The FilePath was not found.\r
760 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
761 @retval EFI_BUFFER_TOO_SMALL The buffer is too small\r
762 @retval EFI_UNSUPPORTED The image type is not supported, or the device\r
763 path cannot be parsed to locate the proper\r
764 protocol for loading the file.\r
765 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient\r
162ed594 766 resources.\r
767\r
768**/\r
28a00297 769EFI_STATUS\r
770CoreLoadImageCommon (\r
771 IN BOOLEAN BootPolicy,\r
772 IN EFI_HANDLE ParentImageHandle,\r
773 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
774 IN VOID *SourceBuffer OPTIONAL,\r
775 IN UINTN SourceSize,\r
776 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,\r
777 IN OUT UINTN *NumberOfPages OPTIONAL,\r
778 OUT EFI_HANDLE *ImageHandle,\r
779 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,\r
780 IN UINT32 Attribute\r
781 )\r
28a00297 782{\r
783 LOADED_IMAGE_PRIVATE_DATA *Image;\r
784 LOADED_IMAGE_PRIVATE_DATA *ParentImage;\r
785 IMAGE_FILE_HANDLE FHand;\r
786 EFI_STATUS Status;\r
787 EFI_STATUS SecurityStatus;\r
788 EFI_HANDLE DeviceHandle;\r
789 UINT32 AuthenticationStatus;\r
790 EFI_DEVICE_PATH_PROTOCOL *OriginalFilePath;\r
791 EFI_DEVICE_PATH_PROTOCOL *HandleFilePath;\r
792 UINTN FilePathSize;\r
793\r
794 SecurityStatus = EFI_SUCCESS;\r
795\r
796 ASSERT (gEfiCurrentTpl < TPL_NOTIFY);\r
797 ParentImage = NULL;\r
798\r
799 //\r
800 // The caller must pass in a valid ParentImageHandle\r
801 //\r
802 if (ImageHandle == NULL || ParentImageHandle == NULL) {\r
803 return EFI_INVALID_PARAMETER;\r
804 }\r
805\r
806 ParentImage = CoreLoadedImageInfo (ParentImageHandle);\r
807 if (ParentImage == NULL) {\r
162ed594 808 DEBUG((DEBUG_LOAD|DEBUG_ERROR, "LoadImageEx: Parent handle not an image handle\n"));\r
28a00297 809 return EFI_INVALID_PARAMETER;\r
810 }\r
811\r
7748df3d
LG
812 ZeroMem (&FHand, sizeof (IMAGE_FILE_HANDLE));\r
813 FHand.Signature = IMAGE_FILE_HANDLE_SIGNATURE;\r
28a00297 814 OriginalFilePath = FilePath;\r
7748df3d
LG
815 HandleFilePath = FilePath;\r
816 DeviceHandle = NULL;\r
817 Status = EFI_SUCCESS;\r
818 AuthenticationStatus = 0;\r
819 //\r
820 // If the caller passed a copy of the file, then just use it\r
821 //\r
822 if (SourceBuffer != NULL) {\r
823 FHand.Source = SourceBuffer;\r
824 FHand.SourceSize = SourceSize;\r
825 CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &HandleFilePath, &DeviceHandle);\r
826 if (SourceSize > 0) {\r
827 Status = EFI_SUCCESS;\r
828 } else {\r
829 Status = EFI_LOAD_ERROR;\r
830 }\r
831 } else {\r
832 if (FilePath == NULL) {\r
833 return EFI_INVALID_PARAMETER;\r
834 }\r
835 //\r
836 // Get the source file buffer by its device path.\r
837 //\r
838 FHand.Source = GetFileBufferByFilePath (\r
839 BootPolicy, \r
840 FilePath,\r
841 &FHand.SourceSize,\r
842 &AuthenticationStatus\r
843 );\r
844 if (FHand.Source == NULL) {\r
845 Status = EFI_LOAD_ERROR;\r
846 } else {\r
847 //\r
848 // Try to get the image device handle by checking the match protocol.\r
849 //\r
850 FHand.FreeBuffer = TRUE;\r
851 Status = CoreLocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &HandleFilePath, &DeviceHandle);\r
852 if (EFI_ERROR (Status)) {\r
853 HandleFilePath = FilePath;\r
854 Status = CoreLocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &HandleFilePath, &DeviceHandle);\r
855 if (EFI_ERROR (Status)) {\r
856 if (!BootPolicy) {\r
857 HandleFilePath = FilePath;\r
858 Status = CoreLocateDevicePath (&gEfiLoadFile2ProtocolGuid, &HandleFilePath, &DeviceHandle);\r
859 }\r
860 if (EFI_ERROR (Status)) {\r
861 HandleFilePath = FilePath;\r
862 Status = CoreLocateDevicePath (&gEfiLoadFileProtocolGuid, &HandleFilePath, &DeviceHandle);\r
863 }\r
864 }\r
865 }\r
866 }\r
867 }\r
868\r
28a00297 869 if (Status == EFI_ALREADY_STARTED) {\r
870 Image = NULL;\r
871 goto Done;\r
872 } else if (EFI_ERROR (Status)) {\r
873 return Status;\r
874 }\r
875\r
876 //\r
877 // Verify the Authentication Status through the Security Architectural Protocol\r
878 //\r
879 if ((gSecurity != NULL) && (OriginalFilePath != NULL)) {\r
880 SecurityStatus = gSecurity->FileAuthenticationState (\r
881 gSecurity,\r
882 AuthenticationStatus,\r
883 OriginalFilePath\r
884 );\r
885 if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {\r
886 Status = SecurityStatus;\r
887 Image = NULL;\r
888 goto Done;\r
889 }\r
890 }\r
891\r
892\r
893 //\r
894 // Allocate a new image structure\r
895 //\r
9c4ac31c 896 Image = AllocateZeroPool (sizeof(LOADED_IMAGE_PRIVATE_DATA));\r
28a00297 897 if (Image == NULL) {\r
898 return EFI_OUT_OF_RESOURCES;\r
899 }\r
900\r
901 //\r
902 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath\r
903 //\r
cfe9de52 904 FilePath = OriginalFilePath;\r
28a00297 905 Status = CoreHandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath);\r
906 if (!EFI_ERROR (Status)) {\r
9c4ac31c 907 FilePathSize = GetDevicePathSize (HandleFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
e94a9ff7 908 FilePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *)FilePath) + FilePathSize );\r
28a00297 909 }\r
910\r
911 //\r
912 // Initialize the fields for an internal driver\r
913 //\r
914 Image->Signature = LOADED_IMAGE_PRIVATE_DATA_SIGNATURE;\r
915 Image->Info.SystemTable = gDxeCoreST;\r
916 Image->Info.DeviceHandle = DeviceHandle;\r
162ed594 917 Image->Info.Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;\r
9c4ac31c 918 Image->Info.FilePath = DuplicateDevicePath (FilePath);\r
28a00297 919 Image->Info.ParentHandle = ParentImageHandle;\r
920\r
85658066 921\r
28a00297 922 if (NumberOfPages != NULL) {\r
923 Image->NumberOfPages = *NumberOfPages ;\r
924 } else {\r
925 Image->NumberOfPages = 0 ;\r
926 }\r
927\r
928 //\r
929 // Install the protocol interfaces for this image\r
930 // don't fire notifications yet\r
931 //\r
932 Status = CoreInstallProtocolInterfaceNotify (\r
933 &Image->Handle,\r
934 &gEfiLoadedImageProtocolGuid,\r
935 EFI_NATIVE_INTERFACE,\r
936 &Image->Info,\r
937 FALSE\r
938 );\r
939 if (EFI_ERROR (Status)) {\r
940 goto Done;\r
941 }\r
942\r
943 //\r
944 // Load the image. If EntryPoint is Null, it will not be set.\r
945 //\r
822360ee 946 Status = CoreLoadPeImage (BootPolicy, &FHand, Image, DstBuffer, EntryPoint, Attribute);\r
28a00297 947 if (EFI_ERROR (Status)) {\r
948 if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_OUT_OF_RESOURCES)) {\r
949 if (NumberOfPages != NULL) {\r
950 *NumberOfPages = Image->NumberOfPages;\r
951 }\r
952 }\r
953 goto Done;\r
954 }\r
955\r
152af594 956 if (NumberOfPages != NULL) {\r
957 *NumberOfPages = Image->NumberOfPages;\r
57d6f36d 958 }\r
152af594 959\r
28a00297 960 //\r
961 // Register the image in the Debug Image Info Table if the attribute is set\r
962 //\r
71f68914 963 if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION) != 0) {\r
28a00297 964 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, &Image->Info, Image->Handle);\r
965 }\r
966\r
967 //\r
968 //Reinstall loaded image protocol to fire any notifications\r
969 //\r
970 Status = CoreReinstallProtocolInterface (\r
971 Image->Handle,\r
972 &gEfiLoadedImageProtocolGuid,\r
973 &Image->Info,\r
974 &Image->Info\r
975 );\r
976 if (EFI_ERROR (Status)) {\r
977 goto Done;\r
978 }\r
979\r
ba39e316 980 //\r
981 // If DevicePath parameter to the LoadImage() is not NULL, then make a copy of DevicePath,\r
982 // otherwise Loaded Image Device Path Protocol is installed with a NULL interface pointer.\r
983 //\r
984 if (OriginalFilePath != NULL) {\r
9c4ac31c 985 Image->LoadedImageDevicePath = DuplicateDevicePath (OriginalFilePath);\r
ba39e316 986 }\r
987\r
988 //\r
989 // Install Loaded Image Device Path Protocol onto the image handle of a PE/COFE image\r
990 //\r
991 Status = CoreInstallProtocolInterface (\r
992 &Image->Handle,\r
993 &gEfiLoadedImageDevicePathProtocolGuid,\r
994 EFI_NATIVE_INTERFACE,\r
995 Image->LoadedImageDevicePath\r
996 );\r
997 if (EFI_ERROR (Status)) {\r
998 goto Done;\r
999 }\r
28a00297 1000\r
7547649f 1001 //\r
1002 // Install HII Package List Protocol onto the image handle\r
1003 //\r
1004 if (Image->ImageContext.HiiResourceData != 0) {\r
1005 Status = CoreInstallProtocolInterface (\r
1006 &Image->Handle,\r
1007 &gEfiHiiPackageListProtocolGuid,\r
1008 EFI_NATIVE_INTERFACE,\r
1009 (VOID *) (UINTN) Image->ImageContext.HiiResourceData\r
1010 );\r
1011 if (EFI_ERROR (Status)) {\r
1012 goto Done;\r
1013 }\r
1014 }\r
1015\r
28a00297 1016 //\r
1017 // Success. Return the image handle\r
1018 //\r
1019 *ImageHandle = Image->Handle;\r
1020\r
1021Done:\r
1022 //\r
1023 // All done accessing the source file\r
1024 // If we allocated the Source buffer, free it\r
1025 //\r
1026 if (FHand.FreeBuffer) {\r
1027 CoreFreePool (FHand.Source);\r
1028 }\r
1029\r
1030 //\r
1031 // There was an error. If there's an Image structure, free it\r
1032 //\r
1033 if (EFI_ERROR (Status)) {\r
1034 if (Image != NULL) {\r
1035 CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer == 0));\r
1036 *ImageHandle = NULL;\r
1037 }\r
1038 } else if (EFI_ERROR (SecurityStatus)) {\r
1039 Status = SecurityStatus;\r
1040 }\r
1041\r
1042 return Status;\r
1043}\r
1044\r
1045\r
1046\r
162ed594 1047\r
1048/**\r
1049 Loads an EFI image into memory and returns a handle to the image.\r
1050\r
57d6f36d 1051 @param BootPolicy If TRUE, indicates that the request originates\r
1052 from the boot manager, and that the boot\r
1053 manager is attempting to load FilePath as a\r
1054 boot selection.\r
1055 @param ParentImageHandle The caller's image handle.\r
1056 @param FilePath The specific file path from which the image is\r
1057 loaded.\r
1058 @param SourceBuffer If not NULL, a pointer to the memory location\r
1059 containing a copy of the image to be loaded.\r
1060 @param SourceSize The size in bytes of SourceBuffer.\r
1061 @param ImageHandle Pointer to the returned image handle that is\r
1062 created when the image is successfully loaded.\r
1063\r
1064 @retval EFI_SUCCESS The image was loaded into memory.\r
1065 @retval EFI_NOT_FOUND The FilePath was not found.\r
1066 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
1067 @retval EFI_UNSUPPORTED The image type is not supported, or the device\r
1068 path cannot be parsed to locate the proper\r
1069 protocol for loading the file.\r
1070 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient\r
162ed594 1071 resources.\r
1072\r
1073**/\r
28a00297 1074EFI_STATUS\r
1075EFIAPI\r
1076CoreLoadImage (\r
1077 IN BOOLEAN BootPolicy,\r
1078 IN EFI_HANDLE ParentImageHandle,\r
1079 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
1080 IN VOID *SourceBuffer OPTIONAL,\r
1081 IN UINTN SourceSize,\r
1082 OUT EFI_HANDLE *ImageHandle\r
1083 )\r
28a00297 1084{\r
1085 EFI_STATUS Status;\r
7cff25d6 1086 UINT64 Tick;\r
28a00297 1087\r
7cff25d6 1088 Tick = 0;\r
1089 PERF_CODE (\r
1090 Tick = GetPerformanceCounter ();\r
1091 );\r
28a00297 1092\r
1093 Status = CoreLoadImageCommon (\r
1094 BootPolicy,\r
1095 ParentImageHandle,\r
1096 FilePath,\r
1097 SourceBuffer,\r
1098 SourceSize,\r
1be0dda6 1099 (EFI_PHYSICAL_ADDRESS) (UINTN) NULL,\r
28a00297 1100 NULL,\r
1101 ImageHandle,\r
1102 NULL,\r
1103 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION | EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION\r
1104 );\r
1105\r
bc6b5892 1106 PERF_START (*ImageHandle, "LoadImage:", NULL, Tick);\r
1107 PERF_END (*ImageHandle, "LoadImage:", NULL, 0);\r
28a00297 1108\r
1109 return Status;\r
1110}\r
1111\r
1112\r
023c0fec 1113\r
1114/**\r
1115 Loads an EFI image into memory and returns a handle to the image with extended parameters.\r
1116\r
1117 @param This Calling context\r
1118 @param ParentImageHandle The caller's image handle.\r
1119 @param FilePath The specific file path from which the image is\r
1120 loaded.\r
1121 @param SourceBuffer If not NULL, a pointer to the memory location\r
1122 containing a copy of the image to be loaded.\r
1123 @param SourceSize The size in bytes of SourceBuffer.\r
1124 @param DstBuffer The buffer to store the image.\r
1125 @param NumberOfPages For input, specifies the space size of the\r
1126 image by caller if not NULL. For output,\r
1127 specifies the actual space size needed.\r
1128 @param ImageHandle Image handle for output.\r
1129 @param EntryPoint Image entry point for output.\r
1130 @param Attribute The bit mask of attributes to set for the load\r
1131 PE image.\r
1132\r
1133 @retval EFI_SUCCESS The image was loaded into memory.\r
1134 @retval EFI_NOT_FOUND The FilePath was not found.\r
1135 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
1136 @retval EFI_UNSUPPORTED The image type is not supported, or the device\r
1137 path cannot be parsed to locate the proper\r
1138 protocol for loading the file.\r
1139 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient\r
1140 resources.\r
1141\r
1142**/\r
1143EFI_STATUS\r
1144EFIAPI\r
1145CoreLoadImageEx (\r
1146 IN EFI_PE32_IMAGE_PROTOCOL *This,\r
1147 IN EFI_HANDLE ParentImageHandle,\r
1148 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
1149 IN VOID *SourceBuffer OPTIONAL,\r
1150 IN UINTN SourceSize,\r
1151 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,\r
1152 OUT UINTN *NumberOfPages OPTIONAL,\r
1153 OUT EFI_HANDLE *ImageHandle,\r
1154 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,\r
1155 IN UINT32 Attribute\r
1156 )\r
1157{\r
1158 return CoreLoadImageCommon (\r
1159 TRUE,\r
1160 ParentImageHandle,\r
1161 FilePath,\r
1162 SourceBuffer,\r
1163 SourceSize,\r
1164 DstBuffer,\r
1165 NumberOfPages,\r
1166 ImageHandle,\r
1167 EntryPoint,\r
1168 Attribute\r
1169 );\r
1170}\r
1171\r
1172\r
162ed594 1173/**\r
1174 Transfer control to a loaded image's entry point.\r
1175\r
57d6f36d 1176 @param ImageHandle Handle of image to be started.\r
1177 @param ExitDataSize Pointer of the size to ExitData\r
1178 @param ExitData Pointer to a pointer to a data buffer that\r
1179 includes a Null-terminated Unicode string,\r
1180 optionally followed by additional binary data.\r
1181 The string is a description that the caller may\r
1182 use to further indicate the reason for the\r
1183 image's exit.\r
1184\r
1185 @retval EFI_INVALID_PARAMETER Invalid parameter\r
1186 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate\r
1187 @retval EFI_SUCCESS Successfully transfer control to the image's\r
162ed594 1188 entry point.\r
1189\r
1190**/\r
28a00297 1191EFI_STATUS\r
1192EFIAPI\r
1193CoreStartImage (\r
1194 IN EFI_HANDLE ImageHandle,\r
1195 OUT UINTN *ExitDataSize,\r
1196 OUT CHAR16 **ExitData OPTIONAL\r
1197 )\r
28a00297 1198{\r
1199 EFI_STATUS Status;\r
1200 LOADED_IMAGE_PRIVATE_DATA *Image;\r
1201 LOADED_IMAGE_PRIVATE_DATA *LastImage;\r
1202 UINT64 HandleDatabaseKey;\r
1203 UINTN SetJumpFlag;\r
1204\r
1205 Image = CoreLoadedImageInfo (ImageHandle);\r
4008328a 1206 if (Image == NULL || Image->Started) {\r
28a00297 1207 return EFI_INVALID_PARAMETER;\r
1208 }\r
1209\r
db0b7ad5
LG
1210 //\r
1211 // The image to be started must have the machine type supported by DxeCore.\r
1212 //\r
1213 ASSERT (EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->Machine));\r
919df8e6 1214 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->Machine)) {\r
919df8e6
LG
1215 return EFI_UNSUPPORTED;\r
1216 }\r
1217\r
28a00297 1218 //\r
1219 // Don't profile Objects or invalid start requests\r
1220 //\r
bc6b5892 1221 PERF_START (ImageHandle, "StartImage:", NULL, 0);\r
28a00297 1222\r
1223\r
1224 //\r
1225 // Push the current start image context, and\r
1226 // link the current image to the head. This is the\r
1227 // only image that can call Exit()\r
1228 //\r
1229 HandleDatabaseKey = CoreGetHandleDatabaseKey ();\r
1230 LastImage = mCurrentImage;\r
1231 mCurrentImage = Image;\r
1232 Image->Tpl = gEfiCurrentTpl;\r
1233\r
1234 //\r
1235 // Set long jump for Exit() support\r
1236 // JumpContext must be aligned on a CPU specific boundary.\r
1237 // Overallocate the buffer and force the required alignment\r
1238 //\r
9c4ac31c 1239 Image->JumpBuffer = AllocatePool (sizeof (BASE_LIBRARY_JUMP_BUFFER) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);\r
28a00297 1240 if (Image->JumpBuffer == NULL) {\r
bc6b5892 1241 PERF_END (ImageHandle, "StartImage:", NULL, 0);\r
28a00297 1242 return EFI_OUT_OF_RESOURCES;\r
1243 }\r
1244 Image->JumpContext = ALIGN_POINTER (Image->JumpBuffer, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);\r
1245\r
1246 SetJumpFlag = SetJump (Image->JumpContext);\r
1247 //\r
1248 // The initial call to SetJump() must always return 0.\r
1249 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().\r
1250 //\r
71f68914 1251 if (SetJumpFlag == 0) {\r
28a00297 1252 //\r
1253 // Call the image's entry point\r
1254 //\r
1255 Image->Started = TRUE;\r
1256 Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable);\r
1257\r
1258 //\r
1259 // Add some debug information if the image returned with error.\r
1260 // This make the user aware and check if the driver image have already released\r
1261 // all the resource in this situation.\r
1262 //\r
1263 DEBUG_CODE_BEGIN ();\r
1264 if (EFI_ERROR (Image->Status)) {\r
91136124 1265 DEBUG ((DEBUG_ERROR, "Error: Image at %11p start failed: %r\n", Image->Info.ImageBase, Image->Status));\r
28a00297 1266 }\r
1267 DEBUG_CODE_END ();\r
1268\r
1269 //\r
1270 // If the image returns, exit it through Exit()\r
1271 //\r
1272 CoreExit (ImageHandle, Image->Status, 0, NULL);\r
1273 }\r
1274\r
1275 //\r
1276 // Image has completed. Verify the tpl is the same\r
1277 //\r
1278 ASSERT (Image->Tpl == gEfiCurrentTpl);\r
1279 CoreRestoreTpl (Image->Tpl);\r
1280\r
1281 CoreFreePool (Image->JumpBuffer);\r
1282\r
1283 //\r
1284 // Pop the current start image context\r
1285 //\r
1286 mCurrentImage = LastImage;\r
1287\r
1288 //\r
1289 // Go connect any handles that were created or modified while the image executed.\r
1290 //\r
1291 CoreConnectHandlesByKey (HandleDatabaseKey);\r
1292\r
1293 //\r
1294 // Handle the image's returned ExitData\r
1295 //\r
1296 DEBUG_CODE_BEGIN ();\r
1297 if (Image->ExitDataSize != 0 || Image->ExitData != NULL) {\r
1298\r
7df7393f 1299 DEBUG ((DEBUG_LOAD, "StartImage: ExitDataSize %d, ExitData %p", (UINT32)Image->ExitDataSize, Image->ExitData));\r
28a00297 1300 if (Image->ExitData != NULL) {\r
162ed594 1301 DEBUG ((DEBUG_LOAD, " (%hs)", Image->ExitData));\r
28a00297 1302 }\r
162ed594 1303 DEBUG ((DEBUG_LOAD, "\n"));\r
28a00297 1304 }\r
1305 DEBUG_CODE_END ();\r
1306\r
1307 //\r
1308 // Return the exit data to the caller\r
1309 //\r
1310 if (ExitData != NULL && ExitDataSize != NULL) {\r
1311 *ExitDataSize = Image->ExitDataSize;\r
1312 *ExitData = Image->ExitData;\r
1313 } else {\r
1314 //\r
1315 // Caller doesn't want the exit data, free it\r
1316 //\r
1317 CoreFreePool (Image->ExitData);\r
1318 Image->ExitData = NULL;\r
1319 }\r
1320\r
1321 //\r
1322 // Save the Status because Image will get destroyed if it is unloaded.\r
1323 //\r
1324 Status = Image->Status;\r
1325\r
1326 //\r
1327 // If the image returned an error, or if the image is an application\r
1328 // unload it\r
1329 //\r
1330 if (EFI_ERROR (Image->Status) || Image->Type == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
1331 CoreUnloadAndCloseImage (Image, TRUE);\r
1332 }\r
1333\r
1334 //\r
1335 // Done\r
1336 //\r
bc6b5892 1337 PERF_END (ImageHandle, "StartImage:", NULL, 0);\r
28a00297 1338 return Status;\r
1339}\r
1340\r
162ed594 1341/**\r
1342 Terminates the currently loaded EFI image and returns control to boot services.\r
1343\r
57d6f36d 1344 @param ImageHandle Handle that identifies the image. This\r
1345 parameter is passed to the image on entry.\r
1346 @param Status The image's exit code.\r
1347 @param ExitDataSize The size, in bytes, of ExitData. Ignored if\r
1348 ExitStatus is EFI_SUCCESS.\r
1349 @param ExitData Pointer to a data buffer that includes a\r
1350 Null-terminated Unicode string, optionally\r
1351 followed by additional binary data. The string\r
1352 is a description that the caller may use to\r
1353 further indicate the reason for the image's\r
1354 exit.\r
1355\r
1356 @retval EFI_INVALID_PARAMETER Image handle is NULL or it is not current\r
1357 image.\r
1358 @retval EFI_SUCCESS Successfully terminates the currently loaded\r
1359 EFI image.\r
1360 @retval EFI_ACCESS_DENIED Should never reach there.\r
162ed594 1361 @retval EFI_OUT_OF_RESOURCES Could not allocate pool\r
1362\r
1363**/\r
28a00297 1364EFI_STATUS\r
1365EFIAPI\r
1366CoreExit (\r
1367 IN EFI_HANDLE ImageHandle,\r
1368 IN EFI_STATUS Status,\r
1369 IN UINTN ExitDataSize,\r
1370 IN CHAR16 *ExitData OPTIONAL\r
1371 )\r
28a00297 1372{\r
1373 LOADED_IMAGE_PRIVATE_DATA *Image;\r
1374 EFI_TPL OldTpl;\r
1375\r
1376 //\r
1377 // Prevent possible reentrance to this function\r
1378 // for the same ImageHandle\r
57d6f36d 1379 //\r
1380 OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
1381\r
28a00297 1382 Image = CoreLoadedImageInfo (ImageHandle);\r
4008328a 1383 if (Image == NULL) {\r
28a00297 1384 Status = EFI_INVALID_PARAMETER;\r
1385 goto Done;\r
1386 }\r
1387\r
1388 if (!Image->Started) {\r
1389 //\r
1390 // The image has not been started so just free its resources\r
1391 //\r
1392 CoreUnloadAndCloseImage (Image, TRUE);\r
1393 Status = EFI_SUCCESS;\r
1394 goto Done;\r
1395 }\r
1396\r
1397 //\r
1398 // Image has been started, verify this image can exit\r
1399 //\r
1400 if (Image != mCurrentImage) {\r
162ed594 1401 DEBUG ((DEBUG_LOAD|DEBUG_ERROR, "Exit: Image is not exitable image\n"));\r
28a00297 1402 Status = EFI_INVALID_PARAMETER;\r
1403 goto Done;\r
1404 }\r
1405\r
1406 //\r
1407 // Set status\r
1408 //\r
1409 Image->Status = Status;\r
1410\r
1411 //\r
1412 // If there's ExitData info, move it\r
1413 //\r
1414 if (ExitData != NULL) {\r
1415 Image->ExitDataSize = ExitDataSize;\r
9c4ac31c 1416 Image->ExitData = AllocatePool (Image->ExitDataSize);\r
28a00297 1417 if (Image->ExitData == NULL) {\r
1418 Status = EFI_OUT_OF_RESOURCES;\r
1419 goto Done;\r
1420 }\r
1421 CopyMem (Image->ExitData, ExitData, Image->ExitDataSize);\r
1422 }\r
1423\r
1424 CoreRestoreTpl (OldTpl);\r
1425 //\r
1426 // return to StartImage\r
1427 //\r
1428 LongJump (Image->JumpContext, (UINTN)-1);\r
1429\r
1430 //\r
1431 // If we return from LongJump, then it is an error\r
1432 //\r
1433 ASSERT (FALSE);\r
1434 Status = EFI_ACCESS_DENIED;\r
1435Done:\r
1436 CoreRestoreTpl (OldTpl);\r
1437 return Status;\r
1438}\r
1439\r
1440\r
1441\r
28a00297 1442\r
162ed594 1443/**\r
28a00297 1444 Unloads an image.\r
1445\r
57d6f36d 1446 @param ImageHandle Handle that identifies the image to be\r
1447 unloaded.\r
28a00297 1448\r
57d6f36d 1449 @retval EFI_SUCCESS The image has been unloaded.\r
1450 @retval EFI_UNSUPPORTED The image has been sarted, and does not support\r
1451 unload.\r
162ed594 1452 @retval EFI_INVALID_PARAMPETER ImageHandle is not a valid image handle.\r
28a00297 1453\r
162ed594 1454**/\r
1455EFI_STATUS\r
1456EFIAPI\r
1457CoreUnloadImage (\r
1458 IN EFI_HANDLE ImageHandle\r
1459 )\r
28a00297 1460{\r
1461 EFI_STATUS Status;\r
1462 LOADED_IMAGE_PRIVATE_DATA *Image;\r
28a00297 1463\r
28a00297 1464 Image = CoreLoadedImageInfo (ImageHandle);\r
1465 if (Image == NULL ) {\r
1466 //\r
1467 // The image handle is not valid\r
1468 //\r
1469 Status = EFI_INVALID_PARAMETER;\r
1470 goto Done;\r
1471 }\r
1472\r
1473 if (Image->Started) {\r
1474 //\r
1475 // The image has been started, request it to unload.\r
1476 //\r
1477 Status = EFI_UNSUPPORTED;\r
1478 if (Image->Info.Unload != NULL) {\r
1479 Status = Image->Info.Unload (ImageHandle);\r
1480 }\r
1481\r
1482 } else {\r
1483 //\r
1484 // This Image hasn't been started, thus it can be unloaded\r
1485 //\r
1486 Status = EFI_SUCCESS;\r
1487 }\r
1488\r
1489\r
1490 if (!EFI_ERROR (Status)) {\r
1491 //\r
1492 // if the Image was not started or Unloaded O.K. then clean up\r
1493 //\r
1494 CoreUnloadAndCloseImage (Image, TRUE);\r
1495 }\r
1496\r
1497Done:\r
28a00297 1498 return Status;\r
1499}\r
1500\r
023c0fec 1501\r
1502\r
1503/**\r
1504 Unload the specified image.\r
1505\r
1506 @param This Indicates the calling context.\r
1507 @param ImageHandle The specified image handle.\r
1508\r
1509 @retval EFI_INVALID_PARAMETER Image handle is NULL.\r
1510 @retval EFI_UNSUPPORTED Attempt to unload an unsupported image.\r
1511 @retval EFI_SUCCESS Image successfully unloaded.\r
1512\r
1513**/\r
1514EFI_STATUS\r
1515EFIAPI\r
1516CoreUnloadImageEx (\r
1517 IN EFI_PE32_IMAGE_PROTOCOL *This,\r
1518 IN EFI_HANDLE ImageHandle\r
1519 )\r
1520{\r
1521 return CoreUnloadImage (ImageHandle);\r
1522}\r