]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Foundation/Library/Pei/PeiLib/PeCoffLoader.c
1) Sync EdkCompatibilityPkg with EDK 1.04. The changes includes:
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / Pei / PeiLib / PeCoffLoader.c
1 /*++
2
3 Copyright (c) 2005 - 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 PeCoffLoader.c
15
16 Abstract:
17
18 Tiano PE/COFF loader
19
20 Revision History
21
22 --*/
23
24 #include "Tiano.h"
25 #include "Pei.h"
26 #include "PeiLib.h"
27 #include "PeCoffLoaderEx.h"
28
29 #ifdef EFI_NT_EMULATOR
30 #include "peilib.h"
31 #include "EfiHobLib.h"
32 #include EFI_PPI_DEFINITION (NtLoadAsDll)
33 #endif
34
35 STATIC
36 EFI_STATUS
37 PeCoffLoaderGetPeHeader (
38 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
39 OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
40 );
41
42 STATIC
43 VOID*
44 PeCoffLoaderImageAddress (
45 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
46 IN UINTN Address
47 );
48
49 EFI_STATUS
50 EFIAPI
51 PeCoffLoaderGetImageInfo (
52 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
53 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
54 );
55
56 EFI_STATUS
57 EFIAPI
58 PeCoffLoaderRelocateImage (
59 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
60 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
61 );
62
63 EFI_STATUS
64 EFIAPI
65 PeCoffLoaderLoadImage (
66 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
67 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
68 );
69
70 EFI_STATUS
71 EFIAPI
72 PeCoffLoaderUnloadImage (
73 IN EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
74 );
75
76 #if defined (EFI_DEBUG_ITP_BREAK) && !defined (_CONSOLE)
77 VOID
78 AsmEfiSetBreakSupport (
79 IN UINTN LoadAddr
80 );
81 #endif
82
83 EFI_PEI_PE_COFF_LOADER_PROTOCOL mPeCoffLoader = {
84 PeCoffLoaderGetImageInfo,
85 PeCoffLoaderLoadImage,
86 PeCoffLoaderRelocateImage,
87 PeCoffLoaderUnloadImage
88 };
89
90 #ifdef EFI_NT_EMULATOR
91 EFI_NT_LOAD_AS_DLL_PPI *mPeCoffLoaderWinNtLoadAsDll = NULL;
92 #endif
93
94 EFI_STATUS
95 InstallEfiPeiPeCoffLoader (
96 IN EFI_PEI_SERVICES **PeiServices,
97 IN OUT EFI_PEI_PE_COFF_LOADER_PROTOCOL **This,
98 IN EFI_PEI_PPI_DESCRIPTOR *ThisPpi
99 )
100 /*++
101
102 Routine Description:
103
104 Install PE/COFF loader PPI
105
106 Arguments:
107
108 PeiServices - General purpose services available to every PEIM
109
110 This - Pointer to get Pei PE coff loader protocol as output
111
112 ThisPpi - Passed in as EFI_NT_LOAD_AS_DLL_PPI on NT_EMULATOR platform
113
114 Returns:
115
116 EFI_SUCCESS
117
118 --*/
119 {
120 EFI_STATUS Status;
121
122 Status = EFI_SUCCESS;
123
124 #ifdef EFI_NT_EMULATOR
125 //
126 // For use by PEI Core and Modules
127 //
128 if (NULL != PeiServices) {
129 Status = (**PeiServices).LocatePpi (
130 PeiServices,
131 &gEfiNtLoadAsDllPpiGuid,
132 0,
133 NULL,
134 &mPeCoffLoaderWinNtLoadAsDll
135 );
136 } else {
137 //
138 // Now in SecMain or ERM usage, bind appropriately
139 //
140 PEI_ASSERT (PeiServices, (NULL != ThisPpi));
141
142 mPeCoffLoaderWinNtLoadAsDll = (EFI_NT_LOAD_AS_DLL_PPI *) ThisPpi;
143 PEI_ASSERT (PeiServices, (NULL != mPeCoffLoaderWinNtLoadAsDll));
144 }
145 #endif
146
147 if (NULL != This) {
148 *This = &mPeCoffLoader;
149 }
150
151 return Status;
152 }
153
154 STATIC
155 EFI_STATUS
156 PeCoffLoaderGetPeHeader (
157 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
158 OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
159 )
160 /*++
161
162 Routine Description:
163
164 Retrieves the PE or TE Header from a PE/COFF or TE image
165
166 Arguments:
167
168 ImageContext - The context of the image being loaded
169
170 PeHdr - The buffer in which to return the PE32, PE32+, or TE header
171
172 Returns:
173
174 EFI_SUCCESS if the PE or TE Header is read,
175 Otherwise, the error status from reading the PE/COFF or TE image using the ImageRead function.
176
177 --*/
178 {
179 EFI_STATUS Status;
180 EFI_IMAGE_DOS_HEADER DosHdr;
181 UINTN Size;
182 UINT16 Magic;
183
184 //
185 // Read the DOS image header to check for it's existance
186 //
187 Size = sizeof (EFI_IMAGE_DOS_HEADER);
188 Status = ImageContext->ImageRead (
189 ImageContext->Handle,
190 0,
191 &Size,
192 &DosHdr
193 );
194 if (EFI_ERROR (Status)) {
195 ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ;
196 return Status;
197 }
198
199 ImageContext->PeCoffHeaderOffset = 0;
200 if (DosHdr.e_magic == EFI_IMAGE_DOS_SIGNATURE) {
201 //
202 // DOS image header is present, so read the PE header after the DOS image
203 // header
204 //
205 ImageContext->PeCoffHeaderOffset = DosHdr.e_lfanew;
206 }
207
208 //
209 // Read the PE/COFF Header. For PE32 (32-bit) this will read in too much
210 // data, but that should not hurt anythine. Hdr.Pe32->OptionalHeader.Magic
211 // determins if this is a PE32 or PE32+ image. The magic is in the same
212 // location in both images.
213 //
214 Size = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);
215 Status = ImageContext->ImageRead (
216 ImageContext->Handle,
217 ImageContext->PeCoffHeaderOffset,
218 &Size,
219 Hdr.Pe32
220 );
221 if (EFI_ERROR (Status)) {
222 ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ;
223 return Status;
224 }
225
226 //
227 // Use Signature to figure out if we understand the image format
228 //
229 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
230 ImageContext->IsTeImage = TRUE;
231 ImageContext->Machine = Hdr.Te->Machine;
232 ImageContext->ImageType = (UINT16)(Hdr.Te->Subsystem);
233 ImageContext->ImageSize = 0;
234 ImageContext->SectionAlignment = 4096;
235 ImageContext->SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN)Hdr.Te->BaseOfCode - (UINTN)Hdr.Te->StrippedSize;
236
237 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
238 ImageContext->IsTeImage = FALSE;
239 ImageContext->Machine = Hdr.Pe32->FileHeader.Machine;
240
241 //
242 // NOTE: We use Machine to identify PE32/PE32+, instead of Magic.
243 // It is for backward-compatibility consideration, because
244 // some system will generate PE32+ image with PE32 Magic.
245 //
246 if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {
247 Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
248 } else if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {
249 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
250 } else if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) {
251 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
252 } else {
253 Magic = Hdr.Pe32->OptionalHeader.Magic;
254 }
255
256 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC ||
257 Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
258 //
259 // PE32 and PE32+ have the same offset for these fields.
260 // We use PE32 for both PE32 and PE32+ headers here.
261 //
262 ImageContext->ImageType = Hdr.Pe32->OptionalHeader.Subsystem;
263 ImageContext->ImageSize = (UINT64)Hdr.Pe32->OptionalHeader.SizeOfImage;
264 ImageContext->SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment;
265 ImageContext->SizeOfHeaders = Hdr.Pe32->OptionalHeader.SizeOfHeaders;
266
267 } else {
268 ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_MACHINE_TYPE;
269 return EFI_UNSUPPORTED;
270 }
271 } else {
272 ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_MACHINE_TYPE;
273 return EFI_UNSUPPORTED;
274 }
275
276 if (!PeCoffLoaderImageFormatSupported (ImageContext->Machine)) {
277 //
278 // If the PE/COFF loader does not support the image type return
279 // unsupported. This library can suport lots of types of images
280 // this does not mean the user of this library can call the entry
281 // point of the image.
282 //
283 return EFI_UNSUPPORTED;
284 }
285
286 return EFI_SUCCESS;
287 }
288
289 STATIC
290 EFI_STATUS
291 PeCoffLoaderCheckImageType (
292 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
293 )
294 /*++
295
296 Routine Description:
297
298 Checks the PE or TE header of a PE/COFF or TE image to determine if it supported
299
300 Arguments:
301
302 ImageContext - The context of the image being loaded
303
304 Returns:
305
306 EFI_SUCCESS if the PE/COFF or TE image is supported
307 EFI_UNSUPPORTED of the PE/COFF or TE image is not supported.
308
309 --*/
310 {
311 switch (ImageContext->ImageType) {
312
313 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:
314 ImageContext->ImageCodeMemoryType = EfiLoaderCode;
315 ImageContext->ImageDataMemoryType = EfiLoaderData;
316 break;
317
318 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
319 ImageContext->ImageCodeMemoryType = EfiBootServicesCode;
320 ImageContext->ImageDataMemoryType = EfiBootServicesData;
321 break;
322
323 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
324 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER:
325 ImageContext->ImageCodeMemoryType = EfiRuntimeServicesCode;
326 ImageContext->ImageDataMemoryType = EfiRuntimeServicesData;
327 break;
328
329 default:
330 ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_SUBSYSTEM;
331 return EFI_UNSUPPORTED;
332 }
333
334 return EFI_SUCCESS;
335 }
336
337 EFI_STATUS
338 EFIAPI
339 PeCoffLoaderGetImageInfo (
340 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
341 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
342 )
343 /*++
344
345 Routine Description:
346
347 Retrieves information on a PE/COFF image
348
349 Arguments:
350
351 This - Calling context
352
353 ImageContext - The context of the image being loaded
354
355 Returns:
356
357 EFI_SUCCESS if the information on the PE/COFF image was collected.
358 EFI_UNSUPPORTED of the PE/COFF image is not supported.
359 Otherwise, the error status from reading the PE/COFF image using the
360 ImageContext->ImageRead() function
361
362 EFI_INVALID_PARAMETER - ImageContext is NULL.
363
364 --*/
365 {
366 EFI_STATUS Status;
367 EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData;
368 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
369 EFI_IMAGE_DATA_DIRECTORY *DebugDirectoryEntry;
370 UINTN Size;
371 UINTN Index;
372 UINTN DebugDirectoryEntryRva;
373 UINTN DebugDirectoryEntryFileOffset;
374 UINTN SectionHeaderOffset;
375 EFI_IMAGE_SECTION_HEADER SectionHeader;
376 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY DebugEntry;
377 UINT32 NumberOfRvaAndSizes;
378 UINT16 Magic;
379
380 if (NULL == ImageContext) {
381 return EFI_INVALID_PARAMETER;
382 }
383
384 //
385 // Assume success
386 //
387 ImageContext->ImageError = EFI_IMAGE_ERROR_SUCCESS;
388
389 Hdr.Union = &HdrData;
390 Status = PeCoffLoaderGetPeHeader (ImageContext, Hdr);
391 if (EFI_ERROR (Status)) {
392 return Status;
393 }
394
395 //
396 // Verify machine type
397 //
398 Status = PeCoffLoaderCheckImageType (ImageContext);
399 if (EFI_ERROR (Status)) {
400 return Status;
401 }
402
403 Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
404
405 //
406 // Retrieve the base address of the image
407 //
408 if (!(ImageContext->IsTeImage)) {
409
410 //
411 // NOTE: We use Machine to identify PE32/PE32+, instead of Magic.
412 // It is for backward-compatibility consideration, because
413 // some system will generate PE32+ image with PE32 Magic.
414 //
415 if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {
416 Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
417 } else if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {
418 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
419 } else if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) {
420 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
421 } else {
422 Magic = Hdr.Pe32->OptionalHeader.Magic;
423 }
424
425 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
426 //
427 // Use PE32 offset
428 //
429 ImageContext->ImageAddress = Hdr.Pe32->OptionalHeader.ImageBase;
430 } else {
431 //
432 // Use PE32+ offset
433 //
434 ImageContext->ImageAddress = Hdr.Pe32Plus->OptionalHeader.ImageBase;
435 }
436 } else {
437 ImageContext->ImageAddress = (EFI_PHYSICAL_ADDRESS)(Hdr.Te->ImageBase + Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));
438 }
439
440 //
441 // Initialize the alternate destination address to 0 indicating that it
442 // should not be used.
443 //
444 ImageContext->DestinationAddress = 0;
445
446 //
447 // Initialize the codeview pointer.
448 //
449 ImageContext->CodeView = NULL;
450 ImageContext->PdbPointer = NULL;
451
452 //
453 // Three cases with regards to relocations:
454 // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable
455 // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable
456 // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but
457 // has no base relocs to apply
458 // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid.
459 //
460 // Look at the file header to determine if relocations have been stripped, and
461 // save this info in the image context for later use.
462 //
463 if ((!(ImageContext->IsTeImage)) && ((Hdr.Pe32->FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0)) {
464 ImageContext->RelocationsStripped = TRUE;
465 } else {
466 ImageContext->RelocationsStripped = FALSE;
467 }
468
469 if (!(ImageContext->IsTeImage)) {
470 //
471 // Use PE32 to access fields that have same offset in PE32 and PE32+
472 //
473 ImageContext->ImageSize = (UINT64) Hdr.Pe32->OptionalHeader.SizeOfImage;
474 ImageContext->SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment;
475 ImageContext->SizeOfHeaders = Hdr.Pe32->OptionalHeader.SizeOfHeaders;
476 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
477 //
478 // Use PE32 offset
479 //
480 NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
481 DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
482 } else {
483 //
484 // Use PE32+ offset
485 //
486 NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
487 DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
488 }
489
490 if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
491
492 DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress;
493
494 //
495 // Determine the file offset of the debug directory... This means we walk
496 // the sections to find which section contains the RVA of the debug
497 // directory
498 //
499 DebugDirectoryEntryFileOffset = 0;
500
501 SectionHeaderOffset = (UINTN)(
502 ImageContext->PeCoffHeaderOffset +
503 sizeof (UINT32) +
504 sizeof (EFI_IMAGE_FILE_HEADER) +
505 Hdr.Pe32->FileHeader.SizeOfOptionalHeader
506 );
507
508 for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
509 //
510 // Read section header from file
511 //
512 Size = sizeof (EFI_IMAGE_SECTION_HEADER);
513 Status = ImageContext->ImageRead (
514 ImageContext->Handle,
515 SectionHeaderOffset,
516 &Size,
517 &SectionHeader
518 );
519 if (EFI_ERROR (Status)) {
520 ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ;
521 return Status;
522 }
523
524 if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress &&
525 DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) {
526
527 DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData;
528 break;
529 }
530
531 SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
532 }
533
534 if (DebugDirectoryEntryFileOffset != 0) {
535 for (Index = 0; Index < DebugDirectoryEntry->Size; Index++) {
536 //
537 // Read next debug directory entry
538 //
539 Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
540 Status = ImageContext->ImageRead (
541 ImageContext->Handle,
542 DebugDirectoryEntryFileOffset,
543 &Size,
544 &DebugEntry
545 );
546 if (EFI_ERROR (Status)) {
547 ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ;
548 return Status;
549 }
550
551 if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
552 ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));
553 if (DebugEntry.RVA == 0 && DebugEntry.FileOffset != 0) {
554 ImageContext->ImageSize += DebugEntry.SizeOfData;
555 }
556
557 return EFI_SUCCESS;
558 }
559 }
560 }
561 }
562 } else {
563 //
564 // Because Te image only extracts base relocations and debug directory entries from
565 // Pe image and in Te image header there is not a field to describe the imagesize,
566 // we use the largest VirtualAddress plus Size in each directory entry to describe the imagesize
567 //
568 ImageContext->ImageSize = (UINT64) (Hdr.Te->DataDirectory[0].VirtualAddress + Hdr.Te->DataDirectory[0].Size);
569 ImageContext->SectionAlignment = 4096;
570 ImageContext->SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN) Hdr.Te->BaseOfCode - (UINTN) Hdr.Te->StrippedSize;
571
572 DebugDirectoryEntry = &Hdr.Te->DataDirectory[1];
573 DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress;
574 SectionHeaderOffset = (UINTN)(sizeof (EFI_TE_IMAGE_HEADER));
575
576 DebugDirectoryEntryFileOffset = 0;
577
578 for (Index = 0; Index < Hdr.Te->NumberOfSections; Index++) {
579 //
580 // Read section header from file
581 //
582 Size = sizeof (EFI_IMAGE_SECTION_HEADER);
583 Status = ImageContext->ImageRead (
584 ImageContext->Handle,
585 SectionHeaderOffset,
586 &Size,
587 &SectionHeader
588 );
589 if (EFI_ERROR (Status)) {
590 ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ;
591 return Status;
592 }
593
594 if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress &&
595 DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) {
596 DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva -
597 SectionHeader.VirtualAddress +
598 SectionHeader.PointerToRawData +
599 sizeof (EFI_TE_IMAGE_HEADER) -
600 Hdr.Te->StrippedSize;
601 break;
602 }
603
604 SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
605 }
606
607 if (DebugDirectoryEntryFileOffset != 0) {
608 for (Index = 0; Index < DebugDirectoryEntry->Size; Index++) {
609 //
610 // Read next debug directory entry
611 //
612 Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
613 Status = ImageContext->ImageRead (
614 ImageContext->Handle,
615 DebugDirectoryEntryFileOffset,
616 &Size,
617 &DebugEntry
618 );
619 if (EFI_ERROR (Status)) {
620 ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ;
621 return Status;
622 }
623
624 if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
625 ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));
626 return EFI_SUCCESS;
627 }
628 }
629 }
630 }
631
632 return EFI_SUCCESS;
633 }
634
635 STATIC
636 VOID *
637 PeCoffLoaderImageAddress (
638 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
639 IN UINTN Address
640 )
641 /*++
642
643 Routine Description:
644
645 Converts an image address to the loaded address
646
647 Arguments:
648
649 ImageContext - The context of the image being loaded
650
651 Address - The address to be converted to the loaded address
652
653 Returns:
654
655 NULL if the address can not be converted, otherwise, the converted address
656
657 --*/
658 {
659 if (Address >= ImageContext->ImageSize) {
660 ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_IMAGE_ADDRESS;
661 return NULL;
662 }
663
664 return (CHAR8 *) ((UINTN) ImageContext->ImageAddress + Address);
665 }
666
667 EFI_STATUS
668 EFIAPI
669 PeCoffLoaderRelocateImage (
670 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
671 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
672 )
673 /*++
674
675 Routine Description:
676
677 Relocates a PE/COFF image in memory
678
679 Arguments:
680
681 This - Calling context
682
683 ImageContext - Contains information on the loaded image to relocate
684
685 Returns:
686
687 EFI_SUCCESS if the PE/COFF image was relocated
688 EFI_LOAD_ERROR if the image is not a valid PE/COFF image
689 EFI_UNSUPPORTED not support
690
691 --*/
692 {
693 EFI_STATUS Status;
694 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
695 EFI_IMAGE_DATA_DIRECTORY *RelocDir;
696 UINT64 Adjust;
697 EFI_IMAGE_BASE_RELOCATION *RelocBase;
698 EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd;
699 UINT16 *Reloc;
700 UINT16 *RelocEnd;
701 CHAR8 *Fixup;
702 CHAR8 *FixupBase;
703 UINT16 *F16;
704 UINT32 *F32;
705 UINT64 *F64;
706 CHAR8 *FixupData;
707 EFI_PHYSICAL_ADDRESS BaseAddress;
708 UINT32 NumberOfRvaAndSizes;
709 UINT16 Magic;
710 #ifdef EFI_NT_EMULATOR
711 VOID *DllEntryPoint;
712 VOID *ModHandle;
713
714 ModHandle = NULL;
715 #endif
716
717 if (NULL == ImageContext) {
718 return EFI_INVALID_PARAMETER;
719 }
720
721 //
722 // Assume success
723 //
724 ImageContext->ImageError = EFI_IMAGE_ERROR_SUCCESS;
725
726 //
727 // If there are no relocation entries, then we are done
728 //
729 if (ImageContext->RelocationsStripped) {
730 return EFI_SUCCESS;
731 }
732
733 //
734 // If the destination address is not 0, use that rather than the
735 // image address as the relocation target.
736 //
737 if (ImageContext->DestinationAddress != 0) {
738 BaseAddress = ImageContext->DestinationAddress;
739 } else {
740 BaseAddress = ImageContext->ImageAddress;
741 }
742
743 if (!(ImageContext->IsTeImage)) {
744 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset);
745
746 //
747 // NOTE: We use Machine to identify PE32/PE32+, instead of Magic.
748 // It is for backward-compatibility consideration, because
749 // some system will generate PE32+ image with PE32 Magic.
750 //
751 if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {
752 Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
753 } else if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {
754 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
755 } else if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) {
756 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
757 } else {
758 Magic = Hdr.Pe32->OptionalHeader.Magic;
759 }
760
761 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
762 //
763 // Use PE32 offset
764 //
765 Adjust = (UINT64)BaseAddress - Hdr.Pe32->OptionalHeader.ImageBase;
766 Hdr.Pe32->OptionalHeader.ImageBase = (UINT32)BaseAddress;
767
768 NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
769 RelocDir = &Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
770 } else {
771 //
772 // Use PE32+ offset
773 //
774 Adjust = (UINT64) BaseAddress - Hdr.Pe32Plus->OptionalHeader.ImageBase;
775 Hdr.Pe32Plus->OptionalHeader.ImageBase = (UINT64)BaseAddress;
776
777 NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
778 RelocDir = &Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
779 }
780
781 //
782 // Find the relocation block
783 // Per the PE/COFF spec, you can't assume that a given data directory
784 // is present in the image. You have to check the NumberOfRvaAndSizes in
785 // the optional header to verify a desired directory entry is there.
786 //
787
788 if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
789 RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress);
790 RelocBaseEnd = PeCoffLoaderImageAddress (
791 ImageContext,
792 RelocDir->VirtualAddress + RelocDir->Size - 1
793 );
794 } else {
795 //
796 // Set base and end to bypass processing below.
797 //
798 RelocBase = RelocBaseEnd = 0;
799 }
800 } else {
801 Hdr.Te = (EFI_TE_IMAGE_HEADER *)(UINTN)(ImageContext->ImageAddress);
802 Adjust = (UINT64) (BaseAddress - Hdr.Te->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->ImageBase);
803 Hdr.Te->ImageBase = (UINT64) (BaseAddress - Hdr.Te->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER));
804
805 //
806 // Find the relocation block
807 //
808 RelocDir = &Hdr.Te->DataDirectory[0];
809 RelocBase = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)(
810 ImageContext->ImageAddress +
811 RelocDir->VirtualAddress +
812 sizeof(EFI_TE_IMAGE_HEADER) -
813 Hdr.Te->StrippedSize
814 );
815 RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) ((UINTN) RelocBase + (UINTN) RelocDir->Size - 1);
816 }
817
818 //
819 // Run the relocation information and apply the fixups
820 //
821 FixupData = ImageContext->FixupData;
822 while (RelocBase < RelocBaseEnd) {
823
824 Reloc = (UINT16 *) ((CHAR8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));
825 RelocEnd = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock);
826 if (!(ImageContext->IsTeImage)) {
827 FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress);
828 } else {
829 FixupBase = (CHAR8 *)(UINTN)(ImageContext->ImageAddress +
830 RelocBase->VirtualAddress +
831 sizeof(EFI_TE_IMAGE_HEADER) -
832 Hdr.Te->StrippedSize
833 );
834 }
835
836 if ((CHAR8 *) RelocEnd < (CHAR8 *) ((UINTN) ImageContext->ImageAddress) ||
837 (CHAR8 *) RelocEnd > (CHAR8 *)((UINTN)ImageContext->ImageAddress +
838 (UINTN)ImageContext->ImageSize)) {
839 ImageContext->ImageError = EFI_IMAGE_ERROR_FAILED_RELOCATION;
840 return EFI_LOAD_ERROR;
841 }
842
843 //
844 // Run this relocation record
845 //
846 while (Reloc < RelocEnd) {
847
848 Fixup = FixupBase + (*Reloc & 0xFFF);
849 switch ((*Reloc) >> 12) {
850 case EFI_IMAGE_REL_BASED_ABSOLUTE:
851 break;
852
853 case EFI_IMAGE_REL_BASED_HIGH:
854 F16 = (UINT16 *) Fixup;
855 *F16 = (UINT16) (*F16 + (UINT16)(((UINT32)Adjust) >> 16));
856 if (FixupData != NULL) {
857 *(UINT16 *) FixupData = *F16;
858 FixupData = FixupData + sizeof (UINT16);
859 }
860 break;
861
862 case EFI_IMAGE_REL_BASED_LOW:
863 F16 = (UINT16 *) Fixup;
864 *F16 = (UINT16) (*F16 + (UINT16) Adjust);
865 if (FixupData != NULL) {
866 *(UINT16 *) FixupData = *F16;
867 FixupData = FixupData + sizeof (UINT16);
868 }
869 break;
870
871 case EFI_IMAGE_REL_BASED_HIGHLOW:
872 F32 = (UINT32 *) Fixup;
873 *F32 = *F32 + (UINT32) Adjust;
874 if (FixupData != NULL) {
875 FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));
876 *(UINT32 *) FixupData = *F32;
877 FixupData = FixupData + sizeof (UINT32);
878 }
879 break;
880
881 case EFI_IMAGE_REL_BASED_DIR64:
882 //
883 // For X64 and IPF
884 //
885 F64 = (UINT64 *) Fixup;
886 *F64 = *F64 + (UINT64) Adjust;
887 if (FixupData != NULL) {
888 FixupData = ALIGN_POINTER (FixupData, sizeof(UINT64));
889 *(UINT64 *)(FixupData) = *F64;
890 FixupData = FixupData + sizeof(UINT64);
891 }
892 break;
893
894 case EFI_IMAGE_REL_BASED_HIGHADJ:
895 //
896 // Return the same EFI_UNSUPPORTED return code as
897 // PeCoffLoaderRelocateImageEx() returns if it does not recognize
898 // the relocation type.
899 //
900 ImageContext->ImageError = EFI_IMAGE_ERROR_FAILED_RELOCATION;
901 return EFI_UNSUPPORTED;
902
903 default:
904 //
905 // The common code does not handle some of the stranger IPF relocations
906 // PeCoffLoaderRelocateImageEx () addes support for these complex fixups
907 // on IPF and is a No-Op on other archtiectures.
908 //
909 Status = PeCoffLoaderRelocateImageEx (Reloc, Fixup, &FixupData, Adjust);
910 if (EFI_ERROR (Status)) {
911 ImageContext->ImageError = EFI_IMAGE_ERROR_FAILED_RELOCATION;
912 return Status;
913 }
914 }
915
916 //
917 // Next relocation record
918 //
919 Reloc += 1;
920 }
921
922 //
923 // Next reloc block
924 //
925 RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;
926 }
927
928 #ifdef EFI_NT_EMULATOR
929 DllEntryPoint = NULL;
930 ImageContext->ModHandle = NULL;
931 //
932 // Load the DLL if it's not an EBC image.
933 //
934 if ((ImageContext->PdbPointer != NULL) &&
935 (ImageContext->Machine != EFI_IMAGE_MACHINE_EBC)) {
936 Status = mPeCoffLoaderWinNtLoadAsDll->Entry (
937 ImageContext->PdbPointer,
938 &DllEntryPoint,
939 &ModHandle
940 );
941
942 if (!EFI_ERROR (Status) && DllEntryPoint != NULL) {
943 ImageContext->EntryPoint = (EFI_PHYSICAL_ADDRESS) (UINTN) DllEntryPoint;
944 ImageContext->ModHandle = ModHandle;
945 }
946 }
947 #endif
948
949 return EFI_SUCCESS;
950 }
951
952 EFI_STATUS
953 EFIAPI
954 PeCoffLoaderLoadImage (
955 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
956 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
957 )
958 /*++
959
960 Routine Description:
961
962 Loads a PE/COFF image into memory
963
964 Arguments:
965
966 This - Calling context
967
968 ImageContext - Contains information on image to load into memory
969
970 Returns:
971
972 EFI_SUCCESS if the PE/COFF image was loaded
973 EFI_BUFFER_TOO_SMALL if the caller did not provide a large enough buffer
974 EFI_LOAD_ERROR if the image is a runtime driver with no relocations
975 EFI_INVALID_PARAMETER if the image address is invalid
976
977 --*/
978 {
979 EFI_STATUS Status;
980 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
981 EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT CheckContext;
982 EFI_IMAGE_SECTION_HEADER *FirstSection;
983 EFI_IMAGE_SECTION_HEADER *Section;
984 UINTN NumberOfSections;
985 UINTN Index;
986 CHAR8 *Base;
987 CHAR8 *End;
988 CHAR8 *MaxEnd;
989 EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;
990 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
991 UINTN Size;
992 UINT32 TempDebugEntryRva;
993 UINT32 NumberOfRvaAndSizes;
994 UINT16 Magic;
995
996 if (NULL == ImageContext) {
997 return EFI_INVALID_PARAMETER;
998 }
999
1000 //
1001 // Assume success
1002 //
1003 ImageContext->ImageError = EFI_IMAGE_ERROR_SUCCESS;
1004
1005 //
1006 // Copy the provided context info into our local version, get what we
1007 // can from the original image, and then use that to make sure everything
1008 // is legit.
1009 //
1010 CopyMem (&CheckContext, ImageContext, sizeof (EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT));
1011
1012 Status = PeCoffLoaderGetImageInfo (This, &CheckContext);
1013 if (EFI_ERROR (Status)) {
1014 return Status;
1015 }
1016
1017 //
1018 // Make sure there is enough allocated space for the image being loaded
1019 //
1020 if (ImageContext->ImageSize < CheckContext.ImageSize) {
1021 ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_IMAGE_SIZE;
1022 return EFI_BUFFER_TOO_SMALL;
1023 }
1024 if (ImageContext->ImageAddress == 0) {
1025 //
1026 // Image cannot be loaded into 0 address.
1027 //
1028 ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_IMAGE_ADDRESS;
1029 return EFI_INVALID_PARAMETER;
1030 }
1031 //
1032 // If there's no relocations, then make sure it's not a runtime driver,
1033 // and that it's being loaded at the linked address.
1034 //
1035 if (CheckContext.RelocationsStripped) {
1036 //
1037 // If the image does not contain relocations and it is a runtime driver
1038 // then return an error.
1039 //
1040 if (CheckContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
1041 ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_SUBSYSTEM;
1042 return EFI_LOAD_ERROR;
1043 }
1044 //
1045 // If the image does not contain relocations, and the requested load address
1046 // is not the linked address, then return an error.
1047 //
1048 if (CheckContext.ImageAddress != ImageContext->ImageAddress) {
1049 ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_IMAGE_ADDRESS;
1050 return EFI_INVALID_PARAMETER;
1051 }
1052 }
1053 //
1054 // Make sure the allocated space has the proper section alignment
1055 //
1056 if (!(ImageContext->IsTeImage)) {
1057 if ((ImageContext->ImageAddress & (CheckContext.SectionAlignment - 1)) != 0) {
1058 ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_SECTION_ALIGNMENT;
1059 return EFI_INVALID_PARAMETER;
1060 }
1061 }
1062 //
1063 // Read the entire PE/COFF or TE header into memory
1064 //
1065 if (!(ImageContext->IsTeImage)) {
1066 Status = ImageContext->ImageRead (
1067 ImageContext->Handle,
1068 0,
1069 &ImageContext->SizeOfHeaders,
1070 (VOID *) (UINTN) ImageContext->ImageAddress
1071 );
1072
1073 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset);
1074
1075 FirstSection = (EFI_IMAGE_SECTION_HEADER *) (
1076 (UINTN)ImageContext->ImageAddress +
1077 ImageContext->PeCoffHeaderOffset +
1078 sizeof(UINT32) +
1079 sizeof(EFI_IMAGE_FILE_HEADER) +
1080 Hdr.Pe32->FileHeader.SizeOfOptionalHeader
1081 );
1082 NumberOfSections = (UINTN) (Hdr.Pe32->FileHeader.NumberOfSections);
1083 } else {
1084 Status = ImageContext->ImageRead (
1085 ImageContext->Handle,
1086 0,
1087 &ImageContext->SizeOfHeaders,
1088 (VOID *)(UINTN)ImageContext->ImageAddress
1089 );
1090
1091 Hdr.Te = (EFI_TE_IMAGE_HEADER *)(UINTN)(ImageContext->ImageAddress);
1092
1093 FirstSection = (EFI_IMAGE_SECTION_HEADER *) (
1094 (UINTN)ImageContext->ImageAddress +
1095 sizeof(EFI_TE_IMAGE_HEADER)
1096 );
1097 NumberOfSections = (UINTN) (Hdr.Te->NumberOfSections);
1098
1099 }
1100
1101 if (EFI_ERROR (Status)) {
1102 ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ;
1103 return EFI_LOAD_ERROR;
1104 }
1105
1106 //
1107 // Load each section of the image
1108 //
1109 Section = FirstSection;
1110 for (Index = 0, MaxEnd = NULL; Index < NumberOfSections; Index++) {
1111
1112 //
1113 // Compute sections address
1114 //
1115 Base = PeCoffLoaderImageAddress (ImageContext, Section->VirtualAddress);
1116 End = PeCoffLoaderImageAddress (
1117 ImageContext,
1118 Section->VirtualAddress + Section->Misc.VirtualSize - 1
1119 );
1120 if (ImageContext->IsTeImage) {
1121 Base = (CHAR8 *)((UINTN) Base + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN)Hdr.Te->StrippedSize);
1122 End = (CHAR8 *)((UINTN) End + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN)Hdr.Te->StrippedSize);
1123 }
1124
1125 if (End > MaxEnd) {
1126 MaxEnd = End;
1127 }
1128 //
1129 // If the base start or end address resolved to 0, then fail.
1130 //
1131 if ((Base == NULL) || (End == NULL)) {
1132 ImageContext->ImageError = EFI_IMAGE_ERROR_SECTION_NOT_LOADED;
1133 return EFI_LOAD_ERROR;
1134 }
1135
1136 //
1137 // Read the section
1138 //
1139 Size = (UINTN) Section->Misc.VirtualSize;
1140 if ((Size == 0) || (Size > Section->SizeOfRawData)) {
1141 Size = (UINTN) Section->SizeOfRawData;
1142 }
1143
1144 if (Section->SizeOfRawData) {
1145 if (!(ImageContext->IsTeImage)) {
1146 Status = ImageContext->ImageRead (
1147 ImageContext->Handle,
1148 Section->PointerToRawData,
1149 &Size,
1150 Base
1151 );
1152 } else {
1153 Status = ImageContext->ImageRead (
1154 ImageContext->Handle,
1155 Section->PointerToRawData + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN)Hdr.Te->StrippedSize,
1156 &Size,
1157 Base
1158 );
1159 }
1160
1161 if (EFI_ERROR (Status)) {
1162 ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ;
1163 return Status;
1164 }
1165 }
1166
1167 //
1168 // If raw size is less then virt size, zero fill the remaining
1169 //
1170
1171 if (Size < Section->Misc.VirtualSize) {
1172 ZeroMem (Base + Size, Section->Misc.VirtualSize - Size);
1173 }
1174
1175 //
1176 // Next Section
1177 //
1178 Section += 1;
1179 }
1180
1181 Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
1182
1183 //
1184 // Get image's entry point
1185 //
1186 if (!(ImageContext->IsTeImage)) {
1187
1188 //
1189 // NOTE: We use Machine to identify PE32/PE32+, instead of Magic.
1190 // It is for backward-compatibility consideration, because
1191 // some system will generate PE32+ image with PE32 Magic.
1192 //
1193 if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {
1194 Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
1195 } else if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {
1196 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
1197 } else if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) {
1198 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
1199 } else {
1200 Magic = Hdr.Pe32->OptionalHeader.Magic;
1201 }
1202
1203 //
1204 // Sizes of AddressOfEntryPoint are different so we need to do this safely
1205 //
1206 ImageContext->EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)PeCoffLoaderImageAddress (
1207 ImageContext,
1208 (UINTN)Hdr.Pe32->OptionalHeader.AddressOfEntryPoint
1209 );
1210
1211 } else {
1212 ImageContext->EntryPoint = (EFI_PHYSICAL_ADDRESS) (
1213 (UINTN)ImageContext->ImageAddress +
1214 (UINTN)Hdr.Te->AddressOfEntryPoint +
1215 (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -
1216 (UINTN)Hdr.Te->StrippedSize
1217 );
1218 }
1219
1220 //
1221 // Determine the size of the fixup data
1222 //
1223 // Per the PE/COFF spec, you can't assume that a given data directory
1224 // is present in the image. You have to check the NumberOfRvaAndSizes in
1225 // the optional header to verify a desired directory entry is there.
1226 //
1227 if (!(ImageContext->IsTeImage)) {
1228 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1229 //
1230 // Use PE32 offset
1231 //
1232 NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
1233 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
1234 } else {
1235 //
1236 // Use PE32+ offset
1237 //
1238 NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
1239 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
1240 }
1241
1242 if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
1243 ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN);
1244 } else {
1245 ImageContext->FixupDataSize = 0;
1246 }
1247 } else {
1248 DirectoryEntry = &Hdr.Te->DataDirectory[0];
1249 ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN);
1250 }
1251 //
1252 // Consumer must allocate a buffer for the relocation fixup log.
1253 // Only used for runtime drivers.
1254 //
1255 ImageContext->FixupData = NULL;
1256
1257 //
1258 // Load the Codeview info if present
1259 //
1260 if (ImageContext->DebugDirectoryEntryRva != 0) {
1261 if (!(ImageContext->IsTeImage)) {
1262 DebugEntry = PeCoffLoaderImageAddress (
1263 ImageContext,
1264 ImageContext->DebugDirectoryEntryRva
1265 );
1266 } else {
1267 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(UINTN)(
1268 ImageContext->ImageAddress +
1269 ImageContext->DebugDirectoryEntryRva +
1270 sizeof(EFI_TE_IMAGE_HEADER) -
1271 Hdr.Te->StrippedSize
1272 );
1273 }
1274
1275 if (DebugEntry != NULL) {
1276 TempDebugEntryRva = DebugEntry->RVA;
1277 if (DebugEntry->RVA == 0 && DebugEntry->FileOffset != 0) {
1278 Section--;
1279 if ((UINTN)Section->SizeOfRawData < Section->Misc.VirtualSize) {
1280 TempDebugEntryRva = Section->VirtualAddress + Section->Misc.VirtualSize;
1281 } else {
1282 TempDebugEntryRva = Section->VirtualAddress + Section->SizeOfRawData;
1283 }
1284 }
1285
1286 if (TempDebugEntryRva != 0) {
1287 if (!(ImageContext->IsTeImage)) {
1288 ImageContext->CodeView = PeCoffLoaderImageAddress (ImageContext, TempDebugEntryRva);
1289 } else {
1290 ImageContext->CodeView = (VOID *)(
1291 (UINTN)ImageContext->ImageAddress +
1292 (UINTN)TempDebugEntryRva +
1293 (UINTN)sizeof (EFI_TE_IMAGE_HEADER) -
1294 (UINTN) Hdr.Te->StrippedSize
1295 );
1296 }
1297
1298 if (ImageContext->CodeView == NULL) {
1299 ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ;
1300 return EFI_LOAD_ERROR;
1301 }
1302
1303 if (DebugEntry->RVA == 0) {
1304 Size = DebugEntry->SizeOfData;
1305 if (!(ImageContext->IsTeImage)) {
1306 Status = ImageContext->ImageRead (
1307 ImageContext->Handle,
1308 DebugEntry->FileOffset,
1309 &Size,
1310 ImageContext->CodeView
1311 );
1312 } else {
1313 Status = ImageContext->ImageRead (
1314 ImageContext->Handle,
1315 DebugEntry->FileOffset + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize,
1316 &Size,
1317 ImageContext->CodeView
1318 );
1319 //
1320 // Should we apply fix up to this field according to the size difference between PE and TE?
1321 // Because now we maintain TE header fields unfixed, this field will also remain as they are
1322 // in original PE image.
1323 //
1324 }
1325
1326 if (EFI_ERROR (Status)) {
1327 ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ;
1328 return EFI_LOAD_ERROR;
1329 }
1330
1331 DebugEntry->RVA = TempDebugEntryRva;
1332 }
1333
1334 switch (*(UINT32 *) ImageContext->CodeView) {
1335 case CODEVIEW_SIGNATURE_NB10:
1336 ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
1337 break;
1338
1339 case CODEVIEW_SIGNATURE_RSDS:
1340 ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
1341 break;
1342
1343 default:
1344 break;
1345 }
1346 }
1347 }
1348 }
1349
1350 #if defined (EFI_DEBUG_ITP_BREAK) && !defined (_CONSOLE)
1351 AsmEfiSetBreakSupport ((UINTN)(ImageContext->ImageAddress));
1352 #endif
1353
1354 return Status;
1355 }
1356
1357 EFI_STATUS
1358 EFIAPI
1359 PeCoffLoaderUnloadImage (
1360 IN EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
1361 )
1362 /*++
1363
1364 Routine Description:
1365
1366 Unload a PE/COFF image from memory
1367
1368 Arguments:
1369
1370 ImageContext - Contains information on image to load into memory
1371
1372 Returns:
1373
1374 EFI_SUCCESS
1375
1376 --*/
1377 {
1378 #ifdef EFI_NT_EMULATOR
1379 //
1380 // Calling Win32 API free library
1381 //
1382 mPeCoffLoaderWinNtLoadAsDll->FreeLibrary (ImageContext->ModHandle);
1383
1384 #endif
1385
1386 return EFI_SUCCESS;
1387 }