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