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