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