]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Pei/Image/Image.c
Fix alignment requirement when Load IPF TeImage into memory.
[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 // Allocate Memory for the image
242 //
243 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));
244 ASSERT (ImageContext.ImageAddress != 0);
245
246 //
247 // Skip the reserved space for the stripped PeHeader when load TeImage into memory.
248 //
249 if (ImageContext.IsTeImage) {
250 ImageContext.ImageAddress = ImageContext.ImageAddress +
251 ((EFI_TE_IMAGE_HEADER *) Pe32Data)->StrippedSize -
252 sizeof (EFI_TE_IMAGE_HEADER);
253 }
254
255 //
256 // Load the image to our new buffer
257 //
258 Status = PeCoffLoaderLoadImage (&ImageContext);
259 if (EFI_ERROR (Status)) {
260 return Status;
261 }
262 //
263 // Relocate the image in our new buffer
264 //
265 Status = PeCoffLoaderRelocateImage (&ImageContext);
266 if (EFI_ERROR (Status)) {
267 return Status;
268 }
269
270 //
271 // Flush the instruction cache so the image data is written before we execute it
272 //
273 InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
274
275 *ImageAddress = ImageContext.ImageAddress;
276 *ImageSize = ImageContext.ImageSize;
277 *EntryPoint = ImageContext.EntryPoint;
278
279 return EFI_SUCCESS;
280 }
281
282 EFI_STATUS
283 PeiLoadImageLoadImage (
284 IN EFI_PEI_SERVICES **PeiServices,
285 IN EFI_PEI_FILE_HANDLE FileHandle,
286 OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL
287 OUT UINT64 *ImageSizeArg, OPTIONAL
288 OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
289 OUT UINT32 *AuthenticationState
290 )
291 /*++
292
293 Routine Description:
294
295 Routine for loading file image.
296
297 Arguments:
298
299 PeiServices - The PEI core services table.
300 FileHandle - Pointer to the FFS file header of the image.
301 ImageAddressArg - Pointer to PE/TE image.
302 ImageSizeArg - Size of PE/TE image.
303 EntryPoint - Pointer to entry point of specified image file for output.
304 AuthenticationState - Pointer to attestation authentication state of image.
305
306 Returns:
307
308 Status - EFI_SUCCESS - Image is successfully loaded.
309 EFI_NOT_FOUND - Fail to locate necessary PPI
310 Others - Fail to load file.
311
312 --*/
313 {
314 EFI_STATUS Status;
315 VOID *Pe32Data;
316 EFI_PHYSICAL_ADDRESS ImageAddress;
317 UINT64 ImageSize;
318 EFI_PHYSICAL_ADDRESS ImageEntryPoint;
319 UINT16 Machine;
320 PEI_CORE_INSTANCE *Private;
321 VOID *EntryPointArg;
322
323 *EntryPoint = 0;
324 ImageSize = 0;
325 *AuthenticationState = 0;
326
327 //
328 // Try to find a TE section.
329 //
330 Status = PeiServicesFfsFindSectionData (
331 EFI_SECTION_TE,
332 FileHandle,
333 &Pe32Data
334 );
335 //
336 // If we didn't find a TE section, try to find a PE32 section.
337 //
338 if (EFI_ERROR (Status)) {
339 Status = PeiServicesFfsFindSectionData (
340 EFI_SECTION_PE32,
341 FileHandle,
342 &Pe32Data
343 );
344 if (EFI_ERROR (Status)) {
345 //
346 // PEI core only carry the loader function fro TE and PE32 executables
347 // If this two section does not exist, just return.
348 //
349 return Status;
350 }
351 }
352
353 Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
354
355 if (Private->PeiMemoryInstalled &&
356 (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
357 //
358 // If memory is installed, perform the shadow operations
359 //
360 Status = LoadAndRelocatePeCoffImage (
361 Pe32Data,
362 &ImageAddress,
363 &ImageSize,
364 &ImageEntryPoint
365 );
366
367 if (EFI_ERROR (Status)) {
368 return Status;
369 }
370
371 //
372 // Got the entry point from the loaded Pe32Data
373 //
374 Pe32Data = (VOID *) ((UINTN) ImageAddress);
375 *EntryPoint = ImageEntryPoint;
376 } else {
377 //
378 // Retrieve the entry point from the PE/COFF or TE image header
379 //
380 ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Pe32Data;
381 Status = PeCoffLoaderGetEntryPoint (Pe32Data, &EntryPointArg);
382 if (EFI_ERROR (Status)) {
383 return Status;
384 }
385 *EntryPoint = (EFI_PHYSICAL_ADDRESS) (UINTN) EntryPointArg;
386 }
387
388 Machine = PeCoffLoaderGetMachineType (Pe32Data);
389
390 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine)) {
391 return EFI_UNSUPPORTED;
392 }
393
394 if (ImageAddressArg != NULL) {
395 *ImageAddressArg = ImageAddress;
396 }
397
398 if (ImageSizeArg != NULL) {
399 *ImageSizeArg = ImageSize;
400 }
401
402 //
403 // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi
404 //
405 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%08x EntryPoint=0x%08x ", (UINTN) ImageAddress, *EntryPoint));
406 DEBUG_CODE_BEGIN ();
407 CHAR8 *AsciiString;
408 CHAR8 AsciiBuffer[512];
409 INT32 Index;
410 INT32 Index1;
411
412 AsciiString = PeCoffLoaderGetPdbPointer (Pe32Data);
413
414 if (AsciiString != NULL) {
415 for (Index = (INT32) AsciiStrLen (AsciiString) - 1; Index >= 0; Index --) {
416 if (AsciiString[Index] == '\\') {
417 break;
418 }
419 }
420
421 if (Index != 0) {
422 for (Index1 = 0; AsciiString[Index + 1 + Index1] != '.'; Index1 ++) {
423 AsciiBuffer [Index1] = AsciiString[Index + 1 + Index1];
424 }
425 AsciiBuffer [Index1] = '\0';
426 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer));
427 }
428 }
429
430 DEBUG_CODE_END ();
431
432 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));
433
434 return EFI_SUCCESS;
435
436 }
437
438
439 EFI_STATUS
440 EFIAPI
441 PeiLoadImageLoadImageWrapper (
442 IN CONST EFI_PEI_LOAD_FILE_PPI *This,
443 IN EFI_PEI_FILE_HANDLE FileHandle,
444 OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL
445 OUT UINT64 *ImageSizeArg, OPTIONAL
446 OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
447 OUT UINT32 *AuthenticationState
448 )
449 /*++
450
451 Routine Description:
452
453 The wrapper function of PeiLoadImageLoadImage().
454
455 Arguments:
456
457 This - Pointer to EFI_PEI_LOAD_FILE_PPI.
458 PeiServices - The PEI core services table.
459 FileHandle - Pointer to the FFS file header of the image.
460 ImageAddressArg - Pointer to PE/TE image.
461 ImageSizeArg - Size of PE/TE image.
462 EntryPoint - Pointer to entry point of specified image file for output.
463 AuthenticationState - Pointer to attestation authentication state of image.
464
465 Returns:
466
467 EFI_STATUS.
468
469 --*/
470 {
471 return PeiLoadImageLoadImage (
472 GetPeiServicesTablePointer (),
473 FileHandle,
474 ImageAddressArg,
475 ImageSizeArg,
476 EntryPoint,
477 AuthenticationState
478 );
479 }
480
481 EFI_STATUS
482 PeiLoadImage (
483 IN EFI_PEI_SERVICES **PeiServices,
484 IN EFI_PEI_FILE_HANDLE FileHandle,
485 OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
486 OUT UINT32 *AuthenticationState
487 )
488 /*++
489
490 Routine Description:
491
492 Routine for load image file.
493
494 Arguments:
495
496 PeiServices - The PEI core services table.
497 FileHandle - Pointer to the FFS file header of the image.
498 EntryPoint - Pointer to entry point of specified image file for output.
499 AuthenticationState - Pointer to attestation authentication state of image.
500
501 Returns:
502
503 Status - EFI_SUCCESS - Image is successfully loaded.
504 EFI_NOT_FOUND - Fail to locate necessary PPI
505 Others - Fail to load file.
506
507 --*/
508 {
509 EFI_STATUS PpiStatus;
510 EFI_STATUS Status;
511 UINTN Index;
512 EFI_PEI_LOAD_FILE_PPI *LoadFile;
513 EFI_PHYSICAL_ADDRESS ImageAddress;
514 UINT64 ImageSize;
515
516 //
517 // If any instances of PEI_LOAD_FILE_PPI are installed, they are called.
518 // one at a time, until one reports EFI_SUCCESS.
519 //
520 Index = 0;
521 do {
522 PpiStatus = PeiServicesLocatePpi (
523 &gEfiPeiLoadFilePpiGuid,
524 Index,
525 NULL,
526 (VOID **)&LoadFile
527 );
528 if (!EFI_ERROR (PpiStatus)) {
529 Status = LoadFile->LoadFile (
530 LoadFile,
531 FileHandle,
532 &ImageAddress,
533 &ImageSize,
534 EntryPoint,
535 AuthenticationState
536 );
537 if (!EFI_ERROR (Status)) {
538 return Status;
539 }
540 }
541 Index++;
542 } while (!EFI_ERROR (PpiStatus));
543
544 //
545 // If no instances reports EFI_SUCCESS, then build-in support for
546 // the PE32+/TE XIP image format is used.
547 //
548 Status = PeiLoadImageLoadImage (
549 PeiServices,
550 FileHandle,
551 NULL,
552 NULL,
553 EntryPoint,
554 AuthenticationState
555 );
556 return Status;
557 }
558
559
560 VOID
561 InitializeImageServices (
562 IN PEI_CORE_INSTANCE *PrivateData,
563 IN PEI_CORE_INSTANCE *OldCoreData
564 )
565 /*++
566
567 Routine Description:
568
569 Install Pei Load File PPI.
570
571 Arguments:
572
573 PrivateData - Pointer to PEI_CORE_INSTANCE.
574 OldCoreData - Pointer to PEI_CORE_INSTANCE.
575
576 Returns:
577
578 NONE.
579
580 --*/
581 {
582 if (OldCoreData == NULL) {
583 //
584 // The first time we are XIP (running from FLASH). We need to remember the
585 // FLASH address so we can reinstall the memory version that runs faster
586 //
587 PrivateData->XipLoadFile = &gPpiLoadFilePpiList;
588 PeiServicesInstallPpi (PrivateData->XipLoadFile);
589 } else {
590 //
591 // 2nd time we are running from memory so replace the XIP version with the
592 // new memory version.
593 //
594 PeiServicesReInstallPpi (PrivateData->XipLoadFile, &gPpiLoadFilePpiList);
595 }
596 }
597
598
599