]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Pei/Image/Image.c
Enable PeiCore to dispatch the encapsulated fv images with depex expression. This...
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Image / Image.c
1 /*++
2
3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 Image.c
15
16 Abstract:
17
18 Pei Core Load Image Support
19
20 --*/
21
22 #include <PeiMain.h>
23
24 /*++
25
26 Routine Description:
27
28 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
29
30 Arguments:
31
32 FileHandle - The handle to the PE/COFF file
33 FileOffset - The offset, in bytes, into the file to read
34 ReadSize - The number of bytes to read from the file starting at FileOffset
35 Buffer - A pointer to the buffer to read the data into.
36
37 Returns:
38
39 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
40
41 --*/
42
43 EFI_STATUS
44 PeiLoadImageLoadImage (
45 IN EFI_PEI_SERVICES **PeiServices,
46 IN EFI_PEI_FILE_HANDLE FileHandle,
47 OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL
48 OUT UINT64 *ImageSizeArg, OPTIONAL
49 OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
50 OUT UINT32 *AuthenticationState
51 )
52 /*++
53
54 Routine Description:
55
56 Routine for loading file image.
57
58 Arguments:
59
60 PeiServices - The PEI core services table.
61 FileHandle - Pointer to the FFS file header of the image.
62 ImageAddressArg - Pointer to PE/TE image.
63 ImageSizeArg - Size of PE/TE image.
64 EntryPoint - Pointer to entry point of specified image file for output.
65 AuthenticationState - Pointer to attestation authentication state of image.
66
67 Returns:
68
69 Status - EFI_SUCCESS - Image is successfully loaded.
70 EFI_NOT_FOUND - Fail to locate necessary PPI
71 Others - Fail to load file.
72
73 --*/
74 ;
75
76 EFI_STATUS
77 EFIAPI
78 PeiLoadImageLoadImageWrapper (
79 IN CONST EFI_PEI_LOAD_FILE_PPI *This,
80 IN EFI_PEI_FILE_HANDLE FileHandle,
81 OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL
82 OUT UINT64 *ImageSizeArg, OPTIONAL
83 OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
84 OUT UINT32 *AuthenticationState
85 )
86 /*++
87
88 Routine Description:
89
90 The wrapper function of PeiLoadImageLoadImage().
91
92 Arguments:
93
94 This - Pointer to EFI_PEI_LOAD_FILE_PPI.
95 PeiServices - The PEI core services table.
96 FileHandle - Pointer to the FFS file header of the image.
97 ImageAddressArg - Pointer to PE/TE image.
98 ImageSizeArg - Size of PE/TE image.
99 EntryPoint - Pointer to entry point of specified image file for output.
100 AuthenticationState - Pointer to attestation authentication state of image.
101
102 Returns:
103
104 EFI_STATUS.
105
106 --*/
107 ;
108
109 STATIC EFI_PEI_LOAD_FILE_PPI mPeiLoadImagePpi = {
110 PeiLoadImageLoadImageWrapper
111 };
112
113
114 STATIC EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = {
115 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
116 &gEfiPeiLoadFilePpiGuid,
117 &mPeiLoadImagePpi
118 };
119
120 EFI_STATUS
121 EFIAPI
122 PeiImageRead (
123 IN VOID *FileHandle,
124 IN UINTN FileOffset,
125 IN OUT UINTN *ReadSize,
126 OUT VOID *Buffer
127 )
128 /*++
129
130 Routine Description:
131
132 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
133
134 Arguments:
135
136 FileHandle - The handle to the PE/COFF file
137 FileOffset - The offset, in bytes, into the file to read
138 ReadSize - The number of bytes to read from the file starting at FileOffset
139 Buffer - A pointer to the buffer to read the data into.
140
141 Returns:
142
143 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
144
145 --*/
146 {
147 CHAR8 *Destination8;
148 CHAR8 *Source8;
149 UINTN Length;
150
151 Destination8 = Buffer;
152 Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
153 Length = *ReadSize;
154 while (Length--) {
155 *(Destination8++) = *(Source8++);
156 }
157
158 return EFI_SUCCESS;
159 }
160
161 EFI_STATUS
162 GetImageReadFunction (
163 IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
164 )
165 /*++
166
167 Routine Description:
168
169 Support routine to return the Image Read
170
171 Arguments:
172
173 PeiServices - PEI Services Table
174
175 ImageContext - The context of the image being loaded
176
177 Returns:
178
179 EFI_SUCCESS - If Image function location is found
180
181 --*/
182 {
183 VOID* MemoryBuffer;
184
185 MemoryBuffer = AllocatePages (0x400 / EFI_PAGE_SIZE + 1);
186 ASSERT (MemoryBuffer != NULL);
187
188 CopyMem (MemoryBuffer, (CONST VOID *) (UINTN) PeiImageRead, 0x400);
189
190 ImageContext->ImageRead = (PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer;
191
192 return EFI_SUCCESS;
193 }
194
195 STATIC
196 EFI_STATUS
197 LoadAndRelocatePeCoffImage (
198 IN VOID *Pe32Data,
199 OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
200 OUT UINT64 *ImageSize,
201 OUT EFI_PHYSICAL_ADDRESS *EntryPoint
202 )
203 /*++
204
205 Routine Description:
206
207 Loads and relocates a PE/COFF image into memory.
208
209 Arguments:
210
211 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
212
213 ImageAddress - The base address of the relocated PE/COFF image
214
215 ImageSize - The size of the relocated PE/COFF image
216
217 EntryPoint - The entry point of the relocated PE/COFF image
218
219 Returns:
220
221 EFI_SUCCESS - The file was loaded and relocated
222
223 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
224
225 --*/
226 {
227 EFI_STATUS Status;
228 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
229
230 ZeroMem (&ImageContext, sizeof (ImageContext));
231 ImageContext.Handle = Pe32Data;
232 Status = GetImageReadFunction (&ImageContext);
233
234 ASSERT_EFI_ERROR (Status);
235
236 Status = PeCoffLoaderGetImageInfo (&ImageContext);
237 if (EFI_ERROR (Status)) {
238 return Status;
239 }
240 //
241 // When Image has no reloc section, it can't be relocated into memory.
242 //
243 if (ImageContext.RelocationsStripped) {
244 DEBUG ((EFI_D_ERROR, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN) Pe32Data));
245 return EFI_INVALID_PARAMETER;
246 }
247 //
248 // Allocate Memory for the image
249 //
250 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));
251 ASSERT (ImageContext.ImageAddress != 0);
252
253 //
254 // Skip the reserved space for the stripped PeHeader when load TeImage into memory.
255 //
256 if (ImageContext.IsTeImage) {
257 ImageContext.ImageAddress = ImageContext.ImageAddress +
258 ((EFI_TE_IMAGE_HEADER *) Pe32Data)->StrippedSize -
259 sizeof (EFI_TE_IMAGE_HEADER);
260 }
261
262 //
263 // Load the image to our new buffer
264 //
265 Status = PeCoffLoaderLoadImage (&ImageContext);
266 if (EFI_ERROR (Status)) {
267 return Status;
268 }
269 //
270 // Relocate the image in our new buffer
271 //
272 Status = PeCoffLoaderRelocateImage (&ImageContext);
273 if (EFI_ERROR (Status)) {
274 return Status;
275 }
276
277 //
278 // Flush the instruction cache so the image data is written before we execute it
279 //
280 InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
281
282 *ImageAddress = ImageContext.ImageAddress;
283 *ImageSize = ImageContext.ImageSize;
284 *EntryPoint = ImageContext.EntryPoint;
285
286 return EFI_SUCCESS;
287 }
288
289 EFI_STATUS
290 PeiLoadImageLoadImage (
291 IN EFI_PEI_SERVICES **PeiServices,
292 IN EFI_PEI_FILE_HANDLE FileHandle,
293 OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL
294 OUT UINT64 *ImageSizeArg, OPTIONAL
295 OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
296 OUT UINT32 *AuthenticationState
297 )
298 /*++
299
300 Routine Description:
301
302 Routine for loading file image.
303
304 Arguments:
305
306 PeiServices - The PEI core services table.
307 FileHandle - Pointer to the FFS file header of the image.
308 ImageAddressArg - Pointer to PE/TE image.
309 ImageSizeArg - Size of PE/TE image.
310 EntryPoint - Pointer to entry point of specified image file for output.
311 AuthenticationState - Pointer to attestation authentication state of image.
312
313 Returns:
314
315 Status - EFI_SUCCESS - Image is successfully loaded.
316 EFI_NOT_FOUND - Fail to locate necessary PPI
317 Others - Fail to load file.
318
319 --*/
320 {
321 EFI_STATUS Status;
322 VOID *Pe32Data;
323 EFI_PHYSICAL_ADDRESS ImageAddress;
324 UINT64 ImageSize;
325 EFI_PHYSICAL_ADDRESS ImageEntryPoint;
326 UINT16 Machine;
327 PEI_CORE_INSTANCE *Private;
328 VOID *EntryPointArg;
329 EFI_SECTION_TYPE SearchType1;
330 EFI_SECTION_TYPE SearchType2;
331
332 *EntryPoint = 0;
333 ImageSize = 0;
334 *AuthenticationState = 0;
335
336 if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst)) {
337 SearchType1 = EFI_SECTION_TE;
338 SearchType2 = EFI_SECTION_PE32;
339 } else {
340 SearchType1 = EFI_SECTION_PE32;
341 SearchType2 = EFI_SECTION_TE;
342 }
343 //
344 // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst
345 // is true, TE will be searched first).
346 //
347 Status = PeiServicesFfsFindSectionData (
348 SearchType1,
349 FileHandle,
350 &Pe32Data
351 );
352 //
353 // If we didn't find a first exe section, try to find the second exe section.
354 //
355 if (EFI_ERROR (Status)) {
356 Status = PeiServicesFfsFindSectionData (
357 SearchType2,
358 FileHandle,
359 &Pe32Data
360 );
361 if (EFI_ERROR (Status)) {
362 //
363 // PEI core only carry the loader function fro TE and PE32 executables
364 // If this two section does not exist, just return.
365 //
366 return Status;
367 }
368 }
369
370 Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
371
372 if (Private->PeiMemoryInstalled &&
373 (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
374 //
375 // If memory is installed, perform the shadow operations
376 //
377 Status = LoadAndRelocatePeCoffImage (
378 Pe32Data,
379 &ImageAddress,
380 &ImageSize,
381 &ImageEntryPoint
382 );
383
384 if (EFI_ERROR (Status)) {
385 return Status;
386 }
387
388 //
389 // Got the entry point from the loaded Pe32Data
390 //
391 Pe32Data = (VOID *) ((UINTN) ImageAddress);
392 *EntryPoint = ImageEntryPoint;
393 } else {
394 //
395 // Retrieve the entry point from the PE/COFF or TE image header
396 //
397 ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Pe32Data;
398 Status = PeCoffLoaderGetEntryPoint (Pe32Data, &EntryPointArg);
399 if (EFI_ERROR (Status)) {
400 return Status;
401 }
402 *EntryPoint = (EFI_PHYSICAL_ADDRESS) (UINTN) EntryPointArg;
403 }
404
405 Machine = PeCoffLoaderGetMachineType (Pe32Data);
406
407 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine)) {
408 return EFI_UNSUPPORTED;
409 }
410
411 if (ImageAddressArg != NULL) {
412 *ImageAddressArg = ImageAddress;
413 }
414
415 if (ImageSizeArg != NULL) {
416 *ImageSizeArg = ImageSize;
417 }
418
419 DEBUG_CODE_BEGIN ();
420 CHAR8 *AsciiString;
421 CHAR8 AsciiBuffer[512];
422 INT32 Index;
423 INT32 Index1;
424
425 //
426 // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi
427 //
428 if (Machine != IMAGE_FILE_MACHINE_IA64) {
429 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%10p EntryPoint=0x%10p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)*EntryPoint));
430 } else {
431 //
432 // For IPF Image, the real entry point should be print.
433 //
434 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%10p EntryPoint=0x%10p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)(*(UINT64 *)(UINTN)*EntryPoint)));
435 }
436
437 //
438 // Print Module Name by PeImage PDB file name.
439 //
440 AsciiString = PeCoffLoaderGetPdbPointer (Pe32Data);
441
442 if (AsciiString != NULL) {
443 for (Index = (INT32) AsciiStrLen (AsciiString) - 1; Index >= 0; Index --) {
444 if (AsciiString[Index] == '\\') {
445 break;
446 }
447 }
448
449 if (Index != 0) {
450 for (Index1 = 0; AsciiString[Index + 1 + Index1] != '.'; Index1 ++) {
451 AsciiBuffer [Index1] = AsciiString[Index + 1 + Index1];
452 }
453 AsciiBuffer [Index1] = '\0';
454 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer));
455 }
456 }
457
458 DEBUG_CODE_END ();
459
460 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));
461
462 return EFI_SUCCESS;
463
464 }
465
466
467 EFI_STATUS
468 EFIAPI
469 PeiLoadImageLoadImageWrapper (
470 IN CONST EFI_PEI_LOAD_FILE_PPI *This,
471 IN EFI_PEI_FILE_HANDLE FileHandle,
472 OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL
473 OUT UINT64 *ImageSizeArg, OPTIONAL
474 OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
475 OUT UINT32 *AuthenticationState
476 )
477 /*++
478
479 Routine Description:
480
481 The wrapper function of PeiLoadImageLoadImage().
482
483 Arguments:
484
485 This - Pointer to EFI_PEI_LOAD_FILE_PPI.
486 PeiServices - The PEI core services table.
487 FileHandle - Pointer to the FFS file header of the image.
488 ImageAddressArg - Pointer to PE/TE image.
489 ImageSizeArg - Size of PE/TE image.
490 EntryPoint - Pointer to entry point of specified image file for output.
491 AuthenticationState - Pointer to attestation authentication state of image.
492
493 Returns:
494
495 EFI_STATUS.
496
497 --*/
498 {
499 return PeiLoadImageLoadImage (
500 GetPeiServicesTablePointer (),
501 FileHandle,
502 ImageAddressArg,
503 ImageSizeArg,
504 EntryPoint,
505 AuthenticationState
506 );
507 }
508
509 EFI_STATUS
510 PeiLoadImage (
511 IN EFI_PEI_SERVICES **PeiServices,
512 IN EFI_PEI_FILE_HANDLE FileHandle,
513 OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
514 OUT UINT32 *AuthenticationState
515 )
516 /*++
517
518 Routine Description:
519
520 Routine for load image file.
521
522 Arguments:
523
524 PeiServices - The PEI core services table.
525 FileHandle - Pointer to the FFS file header of the image.
526 EntryPoint - Pointer to entry point of specified image file for output.
527 AuthenticationState - Pointer to attestation authentication state of image.
528
529 Returns:
530
531 Status - EFI_SUCCESS - Image is successfully loaded.
532 EFI_NOT_FOUND - Fail to locate necessary PPI
533 Others - Fail to load file.
534
535 --*/
536 {
537 EFI_STATUS PpiStatus;
538 EFI_STATUS Status;
539 UINTN Index;
540 EFI_PEI_LOAD_FILE_PPI *LoadFile;
541 EFI_PHYSICAL_ADDRESS ImageAddress;
542 UINT64 ImageSize;
543
544 //
545 // If any instances of PEI_LOAD_FILE_PPI are installed, they are called.
546 // one at a time, until one reports EFI_SUCCESS.
547 //
548 Index = 0;
549 do {
550 PpiStatus = PeiServicesLocatePpi (
551 &gEfiPeiLoadFilePpiGuid,
552 Index,
553 NULL,
554 (VOID **)&LoadFile
555 );
556 if (!EFI_ERROR (PpiStatus)) {
557 Status = LoadFile->LoadFile (
558 LoadFile,
559 FileHandle,
560 &ImageAddress,
561 &ImageSize,
562 EntryPoint,
563 AuthenticationState
564 );
565 if (!EFI_ERROR (Status)) {
566 return Status;
567 }
568 }
569 Index++;
570 } while (!EFI_ERROR (PpiStatus));
571
572 //
573 // If no instances reports EFI_SUCCESS, then build-in support for
574 // the PE32+/TE XIP image format is used.
575 //
576 Status = PeiLoadImageLoadImage (
577 PeiServices,
578 FileHandle,
579 NULL,
580 NULL,
581 EntryPoint,
582 AuthenticationState
583 );
584 return Status;
585 }
586
587
588 VOID
589 InitializeImageServices (
590 IN PEI_CORE_INSTANCE *PrivateData,
591 IN PEI_CORE_INSTANCE *OldCoreData
592 )
593 /*++
594
595 Routine Description:
596
597 Install Pei Load File PPI.
598
599 Arguments:
600
601 PrivateData - Pointer to PEI_CORE_INSTANCE.
602 OldCoreData - Pointer to PEI_CORE_INSTANCE.
603
604 Returns:
605
606 NONE.
607
608 --*/
609 {
610 if (OldCoreData == NULL) {
611 //
612 // The first time we are XIP (running from FLASH). We need to remember the
613 // FLASH address so we can reinstall the memory version that runs faster
614 //
615 PrivateData->XipLoadFile = &gPpiLoadFilePpiList;
616 PeiServicesInstallPpi (PrivateData->XipLoadFile);
617 } else {
618 //
619 // 2nd time we are running from memory so replace the XIP version with the
620 // new memory version.
621 //
622 PeiServicesReInstallPpi (PrivateData->XipLoadFile, &gPpiLoadFilePpiList);
623 }
624 }
625
626
627