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