]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Pei/Image/Image.c
clean up the un-suitable ';' location when declaring the functions.
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Image / Image.c
CommitLineData
615c6dd0 1/** @file\r
b1f6a7c6 2 Pei Core Load Image Support\r
3 \r
ed299e3c 4Copyright (c) 2006 - 2008, Intel Corporation \r
192f6d4c 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
615c6dd0 13**/\r
192f6d4c 14\r
192f6d4c 15#include <PeiMain.h>\r
16\r
b1f6a7c6 17/**\r
18 The wrapper function of PeiLoadImageLoadImage().\r
b0d803fe 19\r
b1f6a7c6 20 @param This - Pointer to EFI_PEI_LOAD_FILE_PPI.\r
21 @param FileHandle - Pointer to the FFS file header of the image.\r
22 @param ImageAddressArg - Pointer to PE/TE image.\r
23 @param ImageSizeArg - Size of PE/TE image.\r
24 @param EntryPoint - Pointer to entry point of specified image file for output.\r
25 @param AuthenticationState - Pointer to attestation authentication state of image.\r
b0d803fe 26\r
b1f6a7c6 27 @return Status of PeiLoadImageLoadImage().\r
b0d803fe 28\r
b1f6a7c6 29**/\r
b0d803fe 30EFI_STATUS\r
31EFIAPI\r
32PeiLoadImageLoadImageWrapper (\r
33 IN CONST EFI_PEI_LOAD_FILE_PPI *This,\r
34 IN EFI_PEI_FILE_HANDLE FileHandle,\r
35 OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL\r
36 OUT UINT64 *ImageSizeArg, OPTIONAL\r
37 OUT EFI_PHYSICAL_ADDRESS *EntryPoint,\r
38 OUT UINT32 *AuthenticationState\r
ed66e1bc 39 );\r
b0d803fe 40\r
41STATIC EFI_PEI_LOAD_FILE_PPI mPeiLoadImagePpi = {\r
42 PeiLoadImageLoadImageWrapper\r
43};\r
44\r
45\r
46STATIC EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = {\r
47 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
48 &gEfiPeiLoadFilePpiGuid,\r
49 &mPeiLoadImagePpi\r
50};\r
51\r
b1f6a7c6 52/**\r
53\r
54 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
55\r
56\r
57 @param FileHandle - The handle to the PE/COFF file\r
58 @param FileOffset - The offset, in bytes, into the file to read\r
59 @param ReadSize - The number of bytes to read from the file starting at FileOffset\r
60 @param Buffer - A pointer to the buffer to read the data into.\r
61\r
62 @return EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
63\r
64**/\r
b0d803fe 65EFI_STATUS\r
66EFIAPI\r
67PeiImageRead (\r
68 IN VOID *FileHandle,\r
69 IN UINTN FileOffset,\r
ed299e3c 70 IN UINTN *ReadSize,\r
b0d803fe 71 OUT VOID *Buffer\r
72 )\r
b0d803fe 73{\r
a9bfd802
LG
74 CHAR8 *Destination8;\r
75 CHAR8 *Source8;\r
76 UINTN Length;\r
77\r
78 Destination8 = Buffer;\r
79 Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
80 Length = *ReadSize;\r
81 while (Length--) {\r
82 *(Destination8++) = *(Source8++);\r
83 }\r
84\r
b0d803fe 85 return EFI_SUCCESS;\r
86}\r
87\r
b1f6a7c6 88/**\r
b0d803fe 89\r
ed299e3c 90 Support routine to get the Image read file function.\r
b0d803fe 91\r
b1f6a7c6 92 @param ImageContext - The context of the image being loaded\r
b0d803fe 93\r
b1f6a7c6 94 @retval EFI_SUCCESS - If Image function location is found\r
b0d803fe 95\r
b1f6a7c6 96**/\r
97EFI_STATUS\r
98GetImageReadFunction (\r
99 IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
100 )\r
b0d803fe 101{\r
102 VOID* MemoryBuffer;\r
103\r
104 MemoryBuffer = AllocatePages (0x400 / EFI_PAGE_SIZE + 1);\r
105 ASSERT (MemoryBuffer != NULL);\r
106\r
107 CopyMem (MemoryBuffer, (CONST VOID *) (UINTN) PeiImageRead, 0x400);\r
108\r
109 ImageContext->ImageRead = (PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer;\r
110\r
111 return EFI_SUCCESS;\r
112}\r
113\r
b1f6a7c6 114/**\r
115\r
116 Loads and relocates a PE/COFF image into memory.\r
117\r
118\r
119 @param Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated\r
120 @param ImageAddress - The base address of the relocated PE/COFF image\r
121 @param ImageSize - The size of the relocated PE/COFF image\r
122 @param EntryPoint - The entry point of the relocated PE/COFF image\r
123\r
124 @retval EFI_SUCCESS The file was loaded and relocated\r
125 @retval EFI_OUT_OF_RESOURCES There was not enough memory to load and relocate the PE/COFF file\r
ed299e3c 126 @retval EFI_INVALID_PARAMETER The image withou .reloc section can't be relocated.\r
b1f6a7c6 127\r
128**/\r
b0d803fe 129EFI_STATUS\r
130LoadAndRelocatePeCoffImage (\r
b0d803fe 131 IN VOID *Pe32Data,\r
132 OUT EFI_PHYSICAL_ADDRESS *ImageAddress,\r
133 OUT UINT64 *ImageSize,\r
134 OUT EFI_PHYSICAL_ADDRESS *EntryPoint\r
135 )\r
b0d803fe 136{\r
137 EFI_STATUS Status;\r
138 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
139\r
b0d803fe 140 ZeroMem (&ImageContext, sizeof (ImageContext));\r
141 ImageContext.Handle = Pe32Data;\r
142 Status = GetImageReadFunction (&ImageContext);\r
143\r
144 ASSERT_EFI_ERROR (Status);\r
145\r
3d7b0992 146 Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
b0d803fe 147 if (EFI_ERROR (Status)) {\r
148 return Status;\r
149 }\r
150 //\r
9626a87e
LG
151 // When Image has no reloc section, it can't be relocated into memory.\r
152 //\r
153 if (ImageContext.RelocationsStripped) {\r
288f9b38 154 DEBUG ((EFI_D_ERROR, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN) Pe32Data));\r
9626a87e
LG
155 return EFI_INVALID_PARAMETER;\r
156 }\r
157 //\r
b0d803fe 158 // Allocate Memory for the image\r
159 //\r
160 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));\r
161 ASSERT (ImageContext.ImageAddress != 0);\r
4e844595
LG
162 \r
163 //\r
164 // Skip the reserved space for the stripped PeHeader when load TeImage into memory.\r
165 //\r
166 if (ImageContext.IsTeImage) {\r
167 ImageContext.ImageAddress = ImageContext.ImageAddress + \r
168 ((EFI_TE_IMAGE_HEADER *) Pe32Data)->StrippedSize -\r
169 sizeof (EFI_TE_IMAGE_HEADER);\r
170 }\r
b0d803fe 171\r
172 //\r
173 // Load the image to our new buffer\r
174 //\r
3d7b0992 175 Status = PeCoffLoaderLoadImage (&ImageContext);\r
b0d803fe 176 if (EFI_ERROR (Status)) {\r
177 return Status;\r
178 }\r
179 //\r
180 // Relocate the image in our new buffer\r
181 //\r
3d7b0992 182 Status = PeCoffLoaderRelocateImage (&ImageContext);\r
b0d803fe 183 if (EFI_ERROR (Status)) {\r
184 return Status;\r
185 }\r
186\r
187 //\r
188 // Flush the instruction cache so the image data is written before we execute it\r
189 //\r
190 InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
191\r
192 *ImageAddress = ImageContext.ImageAddress;\r
193 *ImageSize = ImageContext.ImageSize;\r
194 *EntryPoint = ImageContext.EntryPoint;\r
195\r
196 return EFI_SUCCESS;\r
197}\r
198\r
b1f6a7c6 199/**\r
ed299e3c
LG
200 Loads a PEIM into memory for subsequent execution. If there are compressed \r
201 images or images that need to be relocated into memory for performance reasons, \r
202 this service performs that transformation.\r
b1f6a7c6 203\r
ed299e3c 204 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
b1f6a7c6 205 @param FileHandle Pointer to the FFS file header of the image.\r
206 @param ImageAddressArg Pointer to PE/TE image.\r
207 @param ImageSizeArg Size of PE/TE image.\r
208 @param EntryPoint Pointer to entry point of specified image file for output.\r
209 @param AuthenticationState - Pointer to attestation authentication state of image.\r
210\r
ed299e3c
LG
211 @retval EFI_SUCCESS Image is successfully loaded.\r
212 @retval EFI_NOT_FOUND Fail to locate necessary PPI.\r
213 @retval EFI_UNSUPPORTED Image Machine Type is not supported.\r
b1f6a7c6 214\r
215**/\r
b0d803fe 216EFI_STATUS\r
217PeiLoadImageLoadImage (\r
218 IN EFI_PEI_SERVICES **PeiServices,\r
219 IN EFI_PEI_FILE_HANDLE FileHandle,\r
220 OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL\r
221 OUT UINT64 *ImageSizeArg, OPTIONAL\r
222 OUT EFI_PHYSICAL_ADDRESS *EntryPoint,\r
223 OUT UINT32 *AuthenticationState\r
224 )\r
192f6d4c 225{\r
226 EFI_STATUS Status;\r
227 VOID *Pe32Data;\r
192f6d4c 228 EFI_PHYSICAL_ADDRESS ImageAddress;\r
229 UINT64 ImageSize;\r
230 EFI_PHYSICAL_ADDRESS ImageEntryPoint;\r
192f6d4c 231 UINT16 Machine;\r
b0d803fe 232 PEI_CORE_INSTANCE *Private;\r
233 VOID *EntryPointArg;\r
3076397e 234 EFI_SECTION_TYPE SearchType1;\r
235 EFI_SECTION_TYPE SearchType2;\r
192f6d4c 236\r
3d7b0992
LG
237 *EntryPoint = 0;\r
238 ImageSize = 0;\r
b0d803fe 239 *AuthenticationState = 0;\r
192f6d4c 240\r
3076397e 241 if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst)) {\r
242 SearchType1 = EFI_SECTION_TE;\r
243 SearchType2 = EFI_SECTION_PE32;\r
244 } else {\r
245 SearchType1 = EFI_SECTION_PE32;\r
246 SearchType2 = EFI_SECTION_TE;\r
247 }\r
192f6d4c 248 //\r
3076397e 249 // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst \r
250 // is true, TE will be searched first).\r
192f6d4c 251 //\r
252 Status = PeiServicesFfsFindSectionData (\r
3076397e 253 SearchType1,\r
b0d803fe 254 FileHandle,\r
192f6d4c 255 &Pe32Data\r
256 );\r
257 //\r
3076397e 258 // If we didn't find a first exe section, try to find the second exe section.\r
192f6d4c 259 //\r
260 if (EFI_ERROR (Status)) {\r
261 Status = PeiServicesFfsFindSectionData (\r
3076397e 262 SearchType2,\r
b0d803fe 263 FileHandle,\r
264 &Pe32Data\r
192f6d4c 265 );\r
b0d803fe 266 if (EFI_ERROR (Status)) {\r
192f6d4c 267 //\r
b0d803fe 268 // PEI core only carry the loader function fro TE and PE32 executables\r
269 // If this two section does not exist, just return.\r
192f6d4c 270 //\r
b0d803fe 271 return Status;\r
272 }\r
273 }\r
274 \r
275 Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
192f6d4c 276\r
b0d803fe 277 if (Private->PeiMemoryInstalled && \r
278 (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
3d7b0992
LG
279 //\r
280 // If memory is installed, perform the shadow operations\r
281 //\r
282 Status = LoadAndRelocatePeCoffImage (\r
283 Pe32Data,\r
284 &ImageAddress,\r
285 &ImageSize,\r
286 &ImageEntryPoint\r
287 );\r
192f6d4c 288\r
3d7b0992
LG
289 if (EFI_ERROR (Status)) {\r
290 return Status;\r
b0d803fe 291 }\r
3d7b0992
LG
292\r
293 //\r
294 // Got the entry point from the loaded Pe32Data\r
295 //\r
296 Pe32Data = (VOID *) ((UINTN) ImageAddress);\r
297 *EntryPoint = ImageEntryPoint;\r
b0d803fe 298 } else {\r
3d7b0992
LG
299 //\r
300 // Retrieve the entry point from the PE/COFF or TE image header\r
301 //\r
302 ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Pe32Data;\r
303 Status = PeCoffLoaderGetEntryPoint (Pe32Data, &EntryPointArg);\r
304 if (EFI_ERROR (Status)) {\r
305 return Status;\r
192f6d4c 306 }\r
3d7b0992 307 *EntryPoint = (EFI_PHYSICAL_ADDRESS) (UINTN) EntryPointArg;\r
192f6d4c 308 }\r
3d7b0992
LG
309 \r
310 Machine = PeCoffLoaderGetMachineType (Pe32Data);\r
192f6d4c 311 \r
312 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine)) {\r
313 return EFI_UNSUPPORTED; \r
314 }\r
315\r
b0d803fe 316 if (ImageAddressArg != NULL) {\r
317 *ImageAddressArg = ImageAddress;\r
318 }\r
319\r
320 if (ImageSizeArg != NULL) {\r
321 *ImageSizeArg = ImageSize;\r
322 }\r
323 \r
192f6d4c 324 DEBUG_CODE_BEGIN ();\r
3d7b0992
LG
325 CHAR8 *AsciiString;\r
326 CHAR8 AsciiBuffer[512];\r
327 INT32 Index;\r
328 INT32 Index1;\r
e98cd821
LG
329\r
330 //\r
331 // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi\r
332 //\r
333 if (Machine != IMAGE_FILE_MACHINE_IA64) {\r
91136124 334 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)*EntryPoint));\r
e98cd821
LG
335 } else {\r
336 //\r
337 // For IPF Image, the real entry point should be print.\r
338 //\r
91136124 339 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)(*(UINT64 *)(UINTN)*EntryPoint)));\r
e98cd821 340 }\r
192f6d4c 341 \r
e98cd821
LG
342 //\r
343 // Print Module Name by PeImage PDB file name.\r
344 //\r
3d7b0992
LG
345 AsciiString = PeCoffLoaderGetPdbPointer (Pe32Data);\r
346 \r
347 if (AsciiString != NULL) {\r
19ea58a1 348 for (Index = (INT32) AsciiStrLen (AsciiString) - 1; Index >= 0; Index --) {\r
3d7b0992
LG
349 if (AsciiString[Index] == '\\') {\r
350 break;\r
351 }\r
192f6d4c 352 }\r
192f6d4c 353\r
3d7b0992
LG
354 if (Index != 0) {\r
355 for (Index1 = 0; AsciiString[Index + 1 + Index1] != '.'; Index1 ++) {\r
356 AsciiBuffer [Index1] = AsciiString[Index + 1 + Index1];\r
192f6d4c 357 }\r
3d7b0992
LG
358 AsciiBuffer [Index1] = '\0';\r
359 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer));\r
192f6d4c 360 }\r
361 }\r
3d7b0992 362\r
192f6d4c 363 DEBUG_CODE_END ();\r
364\r
365 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));\r
366\r
367 return EFI_SUCCESS;\r
b0d803fe 368\r
369}\r
370\r
371\r
b1f6a7c6 372/**\r
373 The wrapper function of PeiLoadImageLoadImage().\r
374\r
375 @param This - Pointer to EFI_PEI_LOAD_FILE_PPI.\r
376 @param FileHandle - Pointer to the FFS file header of the image.\r
377 @param ImageAddressArg - Pointer to PE/TE image.\r
378 @param ImageSizeArg - Size of PE/TE image.\r
379 @param EntryPoint - Pointer to entry point of specified image file for output.\r
380 @param AuthenticationState - Pointer to attestation authentication state of image.\r
381\r
382 @return Status of PeiLoadImageLoadImage().\r
383\r
384**/\r
b0d803fe 385EFI_STATUS\r
386EFIAPI\r
387PeiLoadImageLoadImageWrapper (\r
388 IN CONST EFI_PEI_LOAD_FILE_PPI *This,\r
389 IN EFI_PEI_FILE_HANDLE FileHandle,\r
390 OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL\r
391 OUT UINT64 *ImageSizeArg, OPTIONAL\r
392 OUT EFI_PHYSICAL_ADDRESS *EntryPoint,\r
393 OUT UINT32 *AuthenticationState\r
394 )\r
b0d803fe 395{\r
396 return PeiLoadImageLoadImage (\r
397 GetPeiServicesTablePointer (),\r
398 FileHandle,\r
399 ImageAddressArg,\r
400 ImageSizeArg,\r
401 EntryPoint,\r
402 AuthenticationState\r
403 );\r
192f6d4c 404}\r
b0d803fe 405\r
b1f6a7c6 406/**\r
ed299e3c
LG
407 Routine to load image file for subsequent execution by LoadFile Ppi.\r
408 If any LoadFile Ppi is not found, the build-in support function for the PE32+/TE \r
409 XIP image format is used.\r
b1f6a7c6 410\r
ed299e3c
LG
411 @param PeiServices - An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
412 @param FileHandle - Pointer to the FFS file header of the image.\r
413 @param EntryPoint - Pointer to entry point of specified image file for output.\r
414 @param AuthenticationState - Pointer to attestation authentication state of image.\r
b1f6a7c6 415\r
ed299e3c
LG
416 @retval EFI_SUCCESS - Image is successfully loaded.\r
417 @retval EFI_NOT_FOUND - Fail to locate necessary PPI\r
418 @retval Others - Fail to load file.\r
b1f6a7c6 419\r
420**/\r
b0d803fe 421EFI_STATUS\r
422PeiLoadImage (\r
423 IN EFI_PEI_SERVICES **PeiServices,\r
424 IN EFI_PEI_FILE_HANDLE FileHandle,\r
425 OUT EFI_PHYSICAL_ADDRESS *EntryPoint,\r
426 OUT UINT32 *AuthenticationState\r
427 )\r
b0d803fe 428{\r
429 EFI_STATUS PpiStatus;\r
430 EFI_STATUS Status;\r
431 UINTN Index;\r
432 EFI_PEI_LOAD_FILE_PPI *LoadFile;\r
433 EFI_PHYSICAL_ADDRESS ImageAddress;\r
434 UINT64 ImageSize;\r
435\r
436 //\r
437 // If any instances of PEI_LOAD_FILE_PPI are installed, they are called.\r
438 // one at a time, until one reports EFI_SUCCESS.\r
439 //\r
440 Index = 0;\r
441 do {\r
442 PpiStatus = PeiServicesLocatePpi (\r
443 &gEfiPeiLoadFilePpiGuid,\r
444 Index,\r
445 NULL,\r
446 (VOID **)&LoadFile\r
447 );\r
448 if (!EFI_ERROR (PpiStatus)) {\r
449 Status = LoadFile->LoadFile (\r
450 LoadFile, \r
451 FileHandle, \r
452 &ImageAddress, \r
453 &ImageSize,\r
454 EntryPoint,\r
455 AuthenticationState\r
456 );\r
457 if (!EFI_ERROR (Status)) {\r
458 return Status;\r
459 }\r
460 }\r
461 Index++;\r
462 } while (!EFI_ERROR (PpiStatus));\r
463\r
464 //\r
465 // If no instances reports EFI_SUCCESS, then build-in support for\r
466 // the PE32+/TE XIP image format is used.\r
467 //\r
468 Status = PeiLoadImageLoadImage (\r
469 PeiServices, \r
470 FileHandle, \r
471 NULL, \r
472 NULL, \r
473 EntryPoint, \r
474 AuthenticationState\r
475 );\r
476 return Status;\r
477}\r
478\r
479\r
b1f6a7c6 480/**\r
b0d803fe 481\r
ed299e3c
LG
482 Install Pei Load File PPI.\r
483\r
484\r
485 @param PrivateData - Pointer to PEI_CORE_INSTANCE.\r
486 @param OldCoreData - Pointer to PEI_CORE_INSTANCE.\r
b0d803fe 487\r
b1f6a7c6 488**/\r
489VOID\r
490InitializeImageServices (\r
491 IN PEI_CORE_INSTANCE *PrivateData,\r
492 IN PEI_CORE_INSTANCE *OldCoreData\r
493 )\r
b0d803fe 494{\r
b0d803fe 495 if (OldCoreData == NULL) {\r
496 //\r
497 // The first time we are XIP (running from FLASH). We need to remember the\r
498 // FLASH address so we can reinstall the memory version that runs faster\r
499 //\r
500 PrivateData->XipLoadFile = &gPpiLoadFilePpiList;\r
501 PeiServicesInstallPpi (PrivateData->XipLoadFile);\r
502 } else {\r
503 //\r
504 // 2nd time we are running from memory so replace the XIP version with the \r
505 // new memory version. \r
506 //\r
507 PeiServicesReInstallPpi (PrivateData->XipLoadFile, &gPpiLoadFilePpiList); \r
508 }\r
509}\r
510\r
511\r
512\r