TianoCore EDK2 master
Loading...
Searching...
No Matches
BasePeCoff.c
Go to the documentation of this file.
1
27#include <Library/SafeIntLib.h>
28
36VOID
38 EFI_IMAGE_SECTION_HEADER *SectionHeader,
39 UINT32 TeStrippedOffset
40 )
41{
42 SectionHeader->VirtualAddress -= TeStrippedOffset;
43 SectionHeader->PointerToRawData -= TeStrippedOffset;
44}
45
61RETURN_STATUS
65 )
66{
67 RETURN_STATUS Status;
69 UINTN Size;
70 UINTN ReadSize;
71 UINT32 SectionHeaderOffset;
72 UINTN Index;
73 UINT32 HeaderWithoutDataDir;
74 CHAR8 BufferData;
75 UINTN NumberOfSections;
76 EFI_IMAGE_SECTION_HEADER SectionHeader;
77
78 //
79 // Read the DOS image header to check for its existence
80 //
81 Size = sizeof (EFI_IMAGE_DOS_HEADER);
82 ReadSize = Size;
83 Status = ImageContext->ImageRead (
84 ImageContext->Handle,
85 0,
86 &Size,
87 &DosHdr
88 );
89 if (RETURN_ERROR (Status) || (Size != ReadSize)) {
90 ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
91 if (Size != ReadSize) {
92 Status = RETURN_UNSUPPORTED;
93 }
94
95 return Status;
96 }
97
98 ImageContext->PeCoffHeaderOffset = 0;
99 if (DosHdr.e_magic == EFI_IMAGE_DOS_SIGNATURE) {
100 //
101 // DOS image header is present, so read the PE header after the DOS image
102 // header
103 //
104 ImageContext->PeCoffHeaderOffset = DosHdr.e_lfanew;
105 }
106
107 //
108 // Read the PE/COFF Header. For PE32 (32-bit) this will read in too much
109 // data, but that should not hurt anything. Hdr.Pe32->OptionalHeader.Magic
110 // determines if this is a PE32 or PE32+ image. The magic is in the same
111 // location in both images.
112 //
113 Size = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);
114 ReadSize = Size;
115 Status = ImageContext->ImageRead (
116 ImageContext->Handle,
117 ImageContext->PeCoffHeaderOffset,
118 &Size,
119 Hdr.Pe32
120 );
121 if (RETURN_ERROR (Status) || (Size != ReadSize)) {
122 ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
123 if (Size != ReadSize) {
124 Status = RETURN_UNSUPPORTED;
125 }
126
127 return Status;
128 }
129
130 //
131 // Use Signature to figure out if we understand the image format
132 //
133 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
134 ImageContext->IsTeImage = TRUE;
135 ImageContext->Machine = Hdr.Te->Machine;
136 ImageContext->ImageType = (UINT16)(Hdr.Te->Subsystem);
137 //
138 // For TeImage, SectionAlignment is undefined to be set to Zero
139 // ImageSize can be calculated.
140 //
141 ImageContext->ImageSize = 0;
142 ImageContext->SectionAlignment = 0;
143 ImageContext->SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN)Hdr.Te->BaseOfCode - (UINTN)Hdr.Te->StrippedSize;
144
145 //
146 // Check the StrippedSize.
147 //
148 if (sizeof (EFI_TE_IMAGE_HEADER) >= (UINT32)Hdr.Te->StrippedSize) {
149 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
150 return RETURN_UNSUPPORTED;
151 }
152
153 //
154 // Check the SizeOfHeaders field.
155 //
156 if (Hdr.Te->BaseOfCode <= Hdr.Te->StrippedSize) {
157 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
158 return RETURN_UNSUPPORTED;
159 }
160
161 //
162 // Read last byte of Hdr.Te->SizeOfHeaders from the file.
163 //
164 Size = 1;
165 ReadSize = Size;
166 Status = ImageContext->ImageRead (
167 ImageContext->Handle,
168 ImageContext->SizeOfHeaders - 1,
169 &Size,
170 &BufferData
171 );
172 if (RETURN_ERROR (Status) || (Size != ReadSize)) {
173 ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
174 if (Size != ReadSize) {
175 Status = RETURN_UNSUPPORTED;
176 }
177
178 return Status;
179 }
180
181 //
182 // TE Image Data Directory Entry size is non-zero, but the Data Directory Virtual Address is zero.
183 // This case is not a valid TE image.
184 //
185 if (((Hdr.Te->DataDirectory[0].Size != 0) && (Hdr.Te->DataDirectory[0].VirtualAddress == 0)) ||
186 ((Hdr.Te->DataDirectory[1].Size != 0) && (Hdr.Te->DataDirectory[1].VirtualAddress == 0)))
187 {
188 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
189 return RETURN_UNSUPPORTED;
190 }
191 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
192 ImageContext->IsTeImage = FALSE;
193 ImageContext->Machine = Hdr.Pe32->FileHeader.Machine;
194
195 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
196 //
197 // 1. Check OptionalHeader.NumberOfRvaAndSizes filed.
198 //
199 if (EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES < Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes) {
200 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
201 return RETURN_UNSUPPORTED;
202 }
203
204 //
205 // 2. Check the FileHeader.SizeOfOptionalHeader field.
206 // OptionalHeader.NumberOfRvaAndSizes is not bigger than 16, so
207 // OptionalHeader.NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY) will not overflow.
208 //
209 HeaderWithoutDataDir = sizeof (EFI_IMAGE_OPTIONAL_HEADER32) - sizeof (EFI_IMAGE_DATA_DIRECTORY) * EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;
210 if (((UINT32)Hdr.Pe32->FileHeader.SizeOfOptionalHeader - HeaderWithoutDataDir) !=
211 Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY))
212 {
213 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
214 return RETURN_UNSUPPORTED;
215 }
216
217 SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + sizeof (UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + Hdr.Pe32->FileHeader.SizeOfOptionalHeader;
218 //
219 // 3. Check the FileHeader.NumberOfSections field.
220 //
221 if (Hdr.Pe32->OptionalHeader.SizeOfImage <= SectionHeaderOffset) {
222 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
223 return RETURN_UNSUPPORTED;
224 }
225
226 if ((Hdr.Pe32->OptionalHeader.SizeOfImage - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER <= Hdr.Pe32->FileHeader.NumberOfSections) {
227 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
228 return RETURN_UNSUPPORTED;
229 }
230
231 //
232 // 4. Check the OptionalHeader.SizeOfHeaders field.
233 //
234 if (Hdr.Pe32->OptionalHeader.SizeOfHeaders <= SectionHeaderOffset) {
235 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
236 return RETURN_UNSUPPORTED;
237 }
238
239 if (Hdr.Pe32->OptionalHeader.SizeOfHeaders >= Hdr.Pe32->OptionalHeader.SizeOfImage) {
240 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
241 return RETURN_UNSUPPORTED;
242 }
243
244 if ((Hdr.Pe32->OptionalHeader.SizeOfHeaders - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER < (UINT32)Hdr.Pe32->FileHeader.NumberOfSections) {
245 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
246 return RETURN_UNSUPPORTED;
247 }
248
249 //
250 // 4.2 Read last byte of Hdr.Pe32.OptionalHeader.SizeOfHeaders from the file.
251 //
252 Size = 1;
253 ReadSize = Size;
254 Status = ImageContext->ImageRead (
255 ImageContext->Handle,
256 Hdr.Pe32->OptionalHeader.SizeOfHeaders - 1,
257 &Size,
258 &BufferData
259 );
260 if (RETURN_ERROR (Status) || (Size != ReadSize)) {
261 ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
262 if (Size != ReadSize) {
263 Status = RETURN_UNSUPPORTED;
264 }
265
266 return Status;
267 }
268
269 //
270 // Check the EFI_IMAGE_DIRECTORY_ENTRY_SECURITY data.
271 // Read the last byte to make sure the data is in the image region.
272 // The DataDirectory array begin with 1, not 0, so here use < to compare not <=.
273 //
274 if (EFI_IMAGE_DIRECTORY_ENTRY_SECURITY < Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes) {
275 if (Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size != 0) {
276 //
277 // Check the member data to avoid overflow.
278 //
279 if ((UINT32)(~0) - Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress <
280 Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size)
281 {
282 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
283 return RETURN_UNSUPPORTED;
284 }
285
286 //
287 // Read last byte of section header from file
288 //
289 Size = 1;
290 ReadSize = Size;
291 Status = ImageContext->ImageRead (
292 ImageContext->Handle,
293 Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress +
294 Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size - 1,
295 &Size,
296 &BufferData
297 );
298 if (RETURN_ERROR (Status) || (Size != ReadSize)) {
299 ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
300 if (Size != ReadSize) {
301 Status = RETURN_UNSUPPORTED;
302 }
303
304 return Status;
305 }
306 }
307 }
308
309 //
310 // Use PE32 offset
311 //
312 ImageContext->ImageType = Hdr.Pe32->OptionalHeader.Subsystem;
313 ImageContext->ImageSize = (UINT64)Hdr.Pe32->OptionalHeader.SizeOfImage;
314 ImageContext->SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment;
315 ImageContext->SizeOfHeaders = Hdr.Pe32->OptionalHeader.SizeOfHeaders;
316 ImageContext->DllCharacteristics = Hdr.Pe32->OptionalHeader.DllCharacteristics;
317 } else if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
318 //
319 // 1. Check FileHeader.NumberOfRvaAndSizes filed.
320 //
321 if (EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES < Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes) {
322 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
323 return RETURN_UNSUPPORTED;
324 }
325
326 //
327 // 2. Check the FileHeader.SizeOfOptionalHeader field.
328 // OptionalHeader.NumberOfRvaAndSizes is not bigger than 16, so
329 // OptionalHeader.NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY) will not overflow.
330 //
331 HeaderWithoutDataDir = sizeof (EFI_IMAGE_OPTIONAL_HEADER64) - sizeof (EFI_IMAGE_DATA_DIRECTORY) * EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;
332 if (((UINT32)Hdr.Pe32Plus->FileHeader.SizeOfOptionalHeader - HeaderWithoutDataDir) !=
333 Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY))
334 {
335 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
336 return RETURN_UNSUPPORTED;
337 }
338
339 SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + sizeof (UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + Hdr.Pe32Plus->FileHeader.SizeOfOptionalHeader;
340 //
341 // 3. Check the FileHeader.NumberOfSections field.
342 //
343 if (Hdr.Pe32Plus->OptionalHeader.SizeOfImage <= SectionHeaderOffset) {
344 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
345 return RETURN_UNSUPPORTED;
346 }
347
348 if ((Hdr.Pe32Plus->OptionalHeader.SizeOfImage - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER <= Hdr.Pe32Plus->FileHeader.NumberOfSections) {
349 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
350 return RETURN_UNSUPPORTED;
351 }
352
353 //
354 // 4. Check the OptionalHeader.SizeOfHeaders field.
355 //
356 if (Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders <= SectionHeaderOffset) {
357 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
358 return RETURN_UNSUPPORTED;
359 }
360
361 if (Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders >= Hdr.Pe32Plus->OptionalHeader.SizeOfImage) {
362 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
363 return RETURN_UNSUPPORTED;
364 }
365
366 if ((Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER < (UINT32)Hdr.Pe32Plus->FileHeader.NumberOfSections) {
367 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
368 return RETURN_UNSUPPORTED;
369 }
370
371 //
372 // 4.2 Read last byte of Hdr.Pe32Plus.OptionalHeader.SizeOfHeaders from the file.
373 //
374 Size = 1;
375 ReadSize = Size;
376 Status = ImageContext->ImageRead (
377 ImageContext->Handle,
378 Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - 1,
379 &Size,
380 &BufferData
381 );
382 if (RETURN_ERROR (Status) || (Size != ReadSize)) {
383 ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
384 if (Size != ReadSize) {
385 Status = RETURN_UNSUPPORTED;
386 }
387
388 return Status;
389 }
390
391 //
392 // Check the EFI_IMAGE_DIRECTORY_ENTRY_SECURITY data.
393 // Read the last byte to make sure the data is in the image region.
394 // The DataDirectory array begin with 1, not 0, so here use < to compare not <=.
395 //
396 if (EFI_IMAGE_DIRECTORY_ENTRY_SECURITY < Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes) {
397 if (Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size != 0) {
398 //
399 // Check the member data to avoid overflow.
400 //
401 if ((UINT32)(~0) - Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress <
402 Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size)
403 {
404 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
405 return RETURN_UNSUPPORTED;
406 }
407
408 //
409 // Read last byte of section header from file
410 //
411 Size = 1;
412 ReadSize = Size;
413 Status = ImageContext->ImageRead (
414 ImageContext->Handle,
415 Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress +
416 Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size - 1,
417 &Size,
418 &BufferData
419 );
420 if (RETURN_ERROR (Status) || (Size != ReadSize)) {
421 ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
422 if (Size != ReadSize) {
423 Status = RETURN_UNSUPPORTED;
424 }
425
426 return Status;
427 }
428 }
429 }
430
431 //
432 // Use PE32+ offset
433 //
434 ImageContext->ImageType = Hdr.Pe32Plus->OptionalHeader.Subsystem;
435 ImageContext->ImageSize = (UINT64)Hdr.Pe32Plus->OptionalHeader.SizeOfImage;
436 ImageContext->SectionAlignment = Hdr.Pe32Plus->OptionalHeader.SectionAlignment;
437 ImageContext->SizeOfHeaders = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders;
438 ImageContext->DllCharacteristics = Hdr.Pe32Plus->OptionalHeader.DllCharacteristics;
439 } else {
440 ImageContext->ImageError = IMAGE_ERROR_INVALID_MACHINE_TYPE;
441 return RETURN_UNSUPPORTED;
442 }
443 } else {
444 ImageContext->ImageError = IMAGE_ERROR_INVALID_MACHINE_TYPE;
445 return RETURN_UNSUPPORTED;
446 }
447
448 if (!PeCoffLoaderImageFormatSupported (ImageContext->Machine)) {
449 //
450 // If the PE/COFF loader does not support the image type return
451 // unsupported. This library can support lots of types of images
452 // this does not mean the user of this library can call the entry
453 // point of the image.
454 //
455 return RETURN_UNSUPPORTED;
456 }
457
458 //
459 // Check each section field.
460 //
461 if (ImageContext->IsTeImage) {
462 SectionHeaderOffset = sizeof (EFI_TE_IMAGE_HEADER);
463 NumberOfSections = (UINTN)(Hdr.Te->NumberOfSections);
464 } else {
465 SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + sizeof (UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + Hdr.Pe32->FileHeader.SizeOfOptionalHeader;
466 NumberOfSections = (UINTN)(Hdr.Pe32->FileHeader.NumberOfSections);
467 }
468
469 for (Index = 0; Index < NumberOfSections; Index++) {
470 //
471 // Read section header from file
472 //
473 Size = sizeof (EFI_IMAGE_SECTION_HEADER);
474 ReadSize = Size;
475 Status = ImageContext->ImageRead (
476 ImageContext->Handle,
477 SectionHeaderOffset,
478 &Size,
479 &SectionHeader
480 );
481 if (RETURN_ERROR (Status) || (Size != ReadSize)) {
482 ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
483 if (Size != ReadSize) {
484 Status = RETURN_UNSUPPORTED;
485 }
486
487 return Status;
488 }
489
490 //
491 // Adjust some field in Section Header for TE image.
492 //
493 if (ImageContext->IsTeImage) {
494 PeCoffLoaderAdjustOffsetForTeImage (&SectionHeader, (UINT32)Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));
495 }
496
497 if (SectionHeader.SizeOfRawData > 0) {
498 //
499 // Section data should bigger than the Pe header.
500 //
501 if ((SectionHeader.VirtualAddress < ImageContext->SizeOfHeaders) ||
502 (SectionHeader.PointerToRawData < ImageContext->SizeOfHeaders))
503 {
504 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
505 return RETURN_UNSUPPORTED;
506 }
507
508 //
509 // Check the member data to avoid overflow.
510 //
511 if ((UINT32)(~0) - SectionHeader.PointerToRawData < SectionHeader.SizeOfRawData) {
512 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
513 return RETURN_UNSUPPORTED;
514 }
515
516 //
517 // Base on the ImageRead function to check the section data field.
518 // Read the last byte to make sure the data is in the image region.
519 //
520 Size = 1;
521 ReadSize = Size;
522 Status = ImageContext->ImageRead (
523 ImageContext->Handle,
524 SectionHeader.PointerToRawData + SectionHeader.SizeOfRawData - 1,
525 &Size,
526 &BufferData
527 );
528 if (RETURN_ERROR (Status) || (Size != ReadSize)) {
529 ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
530 if (Size != ReadSize) {
531 Status = RETURN_UNSUPPORTED;
532 }
533
534 return Status;
535 }
536 }
537
538 //
539 // Check next section.
540 //
541 SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
542 }
543
544 return RETURN_SUCCESS;
545}
546
576RETURN_STATUS
577EFIAPI
580 )
581{
582 RETURN_STATUS Status;
585 EFI_IMAGE_DATA_DIRECTORY *DebugDirectoryEntry;
586 UINTN Size;
587 UINTN ReadSize;
588 UINTN Index;
589 UINTN NextIndex;
590 UINTN DebugDirectoryEntryRva;
591 UINTN DebugDirectoryEntryFileOffset;
592 UINTN SectionHeaderOffset;
593 EFI_IMAGE_SECTION_HEADER SectionHeader;
595 UINT32 NumberOfRvaAndSizes;
596 UINT32 TeStrippedOffset;
597
598 if (ImageContext == NULL) {
600 }
601
602 //
603 // Assume success
604 //
605 ImageContext->ImageError = IMAGE_ERROR_SUCCESS;
606
607 Hdr.Union = &HdrData;
608 Status = PeCoffLoaderGetPeHeader (ImageContext, Hdr);
609 if (RETURN_ERROR (Status)) {
610 return Status;
611 }
612
613 //
614 // Retrieve the base address of the image
615 //
616 if (!(ImageContext->IsTeImage)) {
617 TeStrippedOffset = 0;
618 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
619 //
620 // Use PE32 offset
621 //
622 ImageContext->ImageAddress = Hdr.Pe32->OptionalHeader.ImageBase;
623 } else {
624 //
625 // Use PE32+ offset
626 //
627 ImageContext->ImageAddress = Hdr.Pe32Plus->OptionalHeader.ImageBase;
628 }
629 } else {
630 TeStrippedOffset = (UINT32)Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);
631 ImageContext->ImageAddress = (PHYSICAL_ADDRESS)(Hdr.Te->ImageBase + TeStrippedOffset);
632 }
633
634 //
635 // Initialize the alternate destination address to 0 indicating that it
636 // should not be used.
637 //
638 ImageContext->DestinationAddress = 0;
639
640 //
641 // Initialize the debug codeview pointer.
642 //
643 ImageContext->DebugDirectoryEntryRva = 0;
644 ImageContext->CodeView = NULL;
645 ImageContext->PdbPointer = NULL;
646
647 //
648 // Three cases with regards to relocations:
649 // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable
650 // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable
651 // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but
652 // has no base relocs to apply
653 // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid.
654 //
655 // Look at the file header to determine if relocations have been stripped, and
656 // save this information in the image context for later use.
657 //
658 if ((!(ImageContext->IsTeImage)) && ((Hdr.Pe32->FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0)) {
659 ImageContext->RelocationsStripped = TRUE;
660 } else if ((ImageContext->IsTeImage) && (Hdr.Te->DataDirectory[0].Size == 0) && (Hdr.Te->DataDirectory[0].VirtualAddress == 0)) {
661 ImageContext->RelocationsStripped = TRUE;
662 } else {
663 ImageContext->RelocationsStripped = FALSE;
664 }
665
666 if (!(ImageContext->IsTeImage)) {
667 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
668 //
669 // Use PE32 offset
670 //
671 NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
672 DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
673 } else {
674 //
675 // Use PE32+ offset
676 //
677 NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
678 DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
679 }
680
681 if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
682 DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress;
683
684 //
685 // Determine the file offset of the debug directory... This means we walk
686 // the sections to find which section contains the RVA of the debug
687 // directory
688 //
689 DebugDirectoryEntryFileOffset = 0;
690
691 SectionHeaderOffset = ImageContext->PeCoffHeaderOffset +
692 sizeof (UINT32) +
693 sizeof (EFI_IMAGE_FILE_HEADER) +
694 Hdr.Pe32->FileHeader.SizeOfOptionalHeader;
695
696 for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
697 //
698 // Read section header from file
699 //
700 Size = sizeof (EFI_IMAGE_SECTION_HEADER);
701 ReadSize = Size;
702 Status = ImageContext->ImageRead (
703 ImageContext->Handle,
704 SectionHeaderOffset,
705 &Size,
706 &SectionHeader
707 );
708 if (RETURN_ERROR (Status) || (Size != ReadSize)) {
709 ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
710 if (Size != ReadSize) {
711 Status = RETURN_UNSUPPORTED;
712 }
713
714 return Status;
715 }
716
717 if ((DebugDirectoryEntryRva >= SectionHeader.VirtualAddress) &&
718 (DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize))
719 {
720 DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData;
721 break;
722 }
723
724 SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
725 }
726
727 if (DebugDirectoryEntryFileOffset != 0) {
728 for (Index = 0; Index < DebugDirectoryEntry->Size; Index += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) {
729 //
730 // Read next debug directory entry
731 //
732 Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
733 ReadSize = Size;
734 Status = ImageContext->ImageRead (
735 ImageContext->Handle,
736 DebugDirectoryEntryFileOffset + Index,
737 &Size,
738 &DebugEntry
739 );
740 if (RETURN_ERROR (Status) || (Size != ReadSize)) {
741 ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
742 if (Size != ReadSize) {
743 Status = RETURN_UNSUPPORTED;
744 }
745
746 return Status;
747 }
748
749 //
750 // From PeCoff spec, when DebugEntry.RVA == 0 means this debug info will not load into memory.
751 // Here we will always load EFI_IMAGE_DEBUG_TYPE_CODEVIEW type debug info. so need adjust the
752 // ImageContext->ImageSize when DebugEntry.RVA == 0.
753 //
754 if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
755 ImageContext->DebugDirectoryEntryRva = (UINT32)(DebugDirectoryEntryRva + Index);
756 if ((DebugEntry.RVA == 0) && (DebugEntry.FileOffset != 0)) {
757 ImageContext->ImageSize += DebugEntry.SizeOfData;
758 }
759
760 //
761 // Implementations of GenFw before commit 60e85a39fe49071 will
762 // concatenate the debug directory entry and the codeview entry,
763 // and erroneously put the combined size into the debug directory's
764 // size field. If this is the case, no other relevant directory
765 // entries can exist, and we can terminate here.
766 //
767 NextIndex = Index + sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
768 if ((NextIndex < DebugDirectoryEntry->Size) &&
769 (DebugEntry.FileOffset == (DebugDirectoryEntryFileOffset + NextIndex)))
770 {
771 break;
772 }
773
774 continue;
775 }
776
777 if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS) {
780 Status = ImageContext->ImageRead (
781 ImageContext->Handle,
782 DebugEntry.FileOffset,
783 &Size,
784 &ImageContext->DllCharacteristicsEx
785 );
786 if (RETURN_ERROR (Status) || (Size != ReadSize)) {
787 ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
788 if (Size != ReadSize) {
789 Status = RETURN_UNSUPPORTED;
790 }
791
792 return Status;
793 }
794
795 continue;
796 }
797 }
798 }
799 }
800 } else {
801 DebugDirectoryEntry = &Hdr.Te->DataDirectory[1];
802 DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress;
803 SectionHeaderOffset = (UINTN)(sizeof (EFI_TE_IMAGE_HEADER));
804
805 DebugDirectoryEntryFileOffset = 0;
806
807 for (Index = 0; Index < Hdr.Te->NumberOfSections;) {
808 //
809 // Read section header from file
810 //
811 Size = sizeof (EFI_IMAGE_SECTION_HEADER);
812 ReadSize = Size;
813 Status = ImageContext->ImageRead (
814 ImageContext->Handle,
815 SectionHeaderOffset,
816 &Size,
817 &SectionHeader
818 );
819 if (RETURN_ERROR (Status) || (Size != ReadSize)) {
820 ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
821 if (Size != ReadSize) {
822 Status = RETURN_UNSUPPORTED;
823 }
824
825 return Status;
826 }
827
828 if ((DebugDirectoryEntryRva >= SectionHeader.VirtualAddress) &&
829 (DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize))
830 {
831 DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva -
832 SectionHeader.VirtualAddress +
833 SectionHeader.PointerToRawData -
834 TeStrippedOffset;
835
836 //
837 // File offset of the debug directory was found, if this is not the last
838 // section, then skip to the last section for calculating the image size.
839 //
840 if (Index < (UINTN)Hdr.Te->NumberOfSections - 1) {
841 SectionHeaderOffset += (Hdr.Te->NumberOfSections - 1 - Index) * sizeof (EFI_IMAGE_SECTION_HEADER);
842 Index = Hdr.Te->NumberOfSections - 1;
843 continue;
844 }
845 }
846
847 //
848 // In Te image header there is not a field to describe the ImageSize.
849 // Actually, the ImageSize equals the RVA plus the VirtualSize of
850 // the last section mapped into memory (Must be rounded up to
851 // a multiple of Section Alignment). Per the PE/COFF specification, the
852 // section headers in the Section Table must appear in order of the RVA
853 // values for the corresponding sections. So the ImageSize can be determined
854 // by the RVA and the VirtualSize of the last section header in the
855 // Section Table.
856 //
857 if ((++Index) == (UINTN)Hdr.Te->NumberOfSections) {
858 ImageContext->ImageSize = (SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) - TeStrippedOffset;
859 }
860
861 SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
862 }
863
864 if (DebugDirectoryEntryFileOffset != 0) {
865 for (Index = 0; Index < DebugDirectoryEntry->Size; Index += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) {
866 //
867 // Read next debug directory entry
868 //
869 Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
870 ReadSize = Size;
871 Status = ImageContext->ImageRead (
872 ImageContext->Handle,
873 DebugDirectoryEntryFileOffset + Index,
874 &Size,
875 &DebugEntry
876 );
877 if (RETURN_ERROR (Status) || (Size != ReadSize)) {
878 ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
879 if (Size != ReadSize) {
880 Status = RETURN_UNSUPPORTED;
881 }
882
883 return Status;
884 }
885
886 if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
887 ImageContext->DebugDirectoryEntryRva = (UINT32)(DebugDirectoryEntryRva + Index);
888 return RETURN_SUCCESS;
889 }
890 }
891 }
892 }
893
894 return RETURN_SUCCESS;
895}
896
907VOID *
909 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
910 IN UINTN Address,
911 IN UINTN TeStrippedOffset
912 )
913{
914 //
915 // Make sure that Address and ImageSize is correct for the loaded image.
916 //
917 if (Address >= ImageContext->ImageSize + TeStrippedOffset) {
918 ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;
919 return NULL;
920 }
921
922 return (CHAR8 *)((UINTN)ImageContext->ImageAddress + Address - TeStrippedOffset);
923}
924
955RETURN_STATUS
956EFIAPI
959 )
960{
961 RETURN_STATUS Status;
963 EFI_IMAGE_DATA_DIRECTORY *RelocDir;
964 UINT64 Adjust;
965 EFI_IMAGE_BASE_RELOCATION *RelocBaseOrg;
966 EFI_IMAGE_BASE_RELOCATION *RelocBase;
967 EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd;
968 UINT16 *Reloc;
969 UINT16 *RelocEnd;
970 CHAR8 *Fixup;
971 CHAR8 *FixupBase;
972 UINT16 *Fixup16;
973 UINT32 *Fixup32;
974 UINT64 *Fixup64;
975 CHAR8 *FixupData;
976 PHYSICAL_ADDRESS BaseAddress;
977 UINT32 NumberOfRvaAndSizes;
978 UINT32 TeStrippedOffset;
979 UINT32 EndAddress;
980
981 ASSERT (ImageContext != NULL);
982
983 //
984 // Assume success
985 //
986 ImageContext->ImageError = IMAGE_ERROR_SUCCESS;
987
988 //
989 // If there are no relocation entries, then we are done
990 //
991 if (ImageContext->RelocationsStripped) {
992 // Applies additional environment specific actions to relocate fixups
993 // to a PE/COFF image if needed
995 return RETURN_SUCCESS;
996 }
997
998 //
999 // If the destination address is not 0, use that rather than the
1000 // image address as the relocation target.
1001 //
1002 if (ImageContext->DestinationAddress != 0) {
1003 BaseAddress = ImageContext->DestinationAddress;
1004 } else {
1005 BaseAddress = ImageContext->ImageAddress;
1006 }
1007
1008 if (!(ImageContext->IsTeImage)) {
1009 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset);
1010 TeStrippedOffset = 0;
1011
1012 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1013 //
1014 // Use PE32 offset
1015 //
1016 Adjust = (UINT64)BaseAddress - Hdr.Pe32->OptionalHeader.ImageBase;
1017 if (Adjust != 0) {
1018 Hdr.Pe32->OptionalHeader.ImageBase = (UINT32)BaseAddress;
1019 }
1020
1021 NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
1022 RelocDir = &Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
1023 } else {
1024 //
1025 // Use PE32+ offset
1026 //
1027 Adjust = (UINT64)BaseAddress - Hdr.Pe32Plus->OptionalHeader.ImageBase;
1028 if (Adjust != 0) {
1029 Hdr.Pe32Plus->OptionalHeader.ImageBase = (UINT64)BaseAddress;
1030 }
1031
1032 NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
1033 RelocDir = &Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
1034 }
1035
1036 //
1037 // Find the relocation block
1038 // Per the PE/COFF spec, you can't assume that a given data directory
1039 // is present in the image. You have to check the NumberOfRvaAndSizes in
1040 // the optional header to verify a desired directory entry is there.
1041 //
1042 if ((NumberOfRvaAndSizes < EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC)) {
1043 RelocDir = NULL;
1044 }
1045 } else {
1046 Hdr.Te = (EFI_TE_IMAGE_HEADER *)(UINTN)(ImageContext->ImageAddress);
1047 TeStrippedOffset = (UINT32)Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);
1048 Adjust = (UINT64)(BaseAddress - (Hdr.Te->ImageBase + TeStrippedOffset));
1049 if (Adjust != 0) {
1050 Hdr.Te->ImageBase = (UINT64)(BaseAddress - TeStrippedOffset);
1051 }
1052
1053 //
1054 // Find the relocation block
1055 //
1056 RelocDir = &Hdr.Te->DataDirectory[0];
1057 }
1058
1059 RelocBase = NULL;
1060 RelocBaseEnd = NULL;
1061 if ((RelocDir != NULL) && (RelocDir->Size > 0)) {
1062 Status = SafeUint32Add (RelocDir->VirtualAddress, (RelocDir->Size - 1), &EndAddress);
1063 if (!RETURN_ERROR (Status)) {
1064 RelocBase = (EFI_IMAGE_BASE_RELOCATION *)PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress, TeStrippedOffset);
1066 ImageContext,
1067 EndAddress,
1068 TeStrippedOffset
1069 );
1070 }
1071
1072 if ((RelocBase == NULL) || (RelocBaseEnd == NULL) || ((UINTN)RelocBaseEnd < (UINTN)RelocBase)) {
1073 ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
1074 DEBUG ((DEBUG_ERROR, "Relocation block is not valid\n"));
1075 return RETURN_LOAD_ERROR;
1076 }
1077 }
1078
1079 RelocBaseOrg = RelocBase;
1080
1081 //
1082 // If Adjust is not zero, then apply fix ups to the image
1083 //
1084 if (Adjust != 0) {
1085 //
1086 // Run the relocation information and apply the fixups
1087 //
1088 FixupData = ImageContext->FixupData;
1089 while ((UINTN)RelocBase < (UINTN)RelocBaseEnd) {
1090 Reloc = (UINT16 *)((CHAR8 *)RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));
1091 //
1092 // Add check for RelocBase->SizeOfBlock field.
1093 //
1094 if (RelocBase->SizeOfBlock == 0) {
1095 ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
1096 return RETURN_LOAD_ERROR;
1097 }
1098
1099 if ((UINTN)RelocBase > MAX_ADDRESS - RelocBase->SizeOfBlock) {
1100 ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
1101 return RETURN_LOAD_ERROR;
1102 }
1103
1104 RelocEnd = (UINT16 *)((CHAR8 *)RelocBase + RelocBase->SizeOfBlock);
1105 if ((UINTN)RelocEnd > (UINTN)RelocBaseOrg + RelocDir->Size) {
1106 ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
1107 return RETURN_LOAD_ERROR;
1108 }
1109
1110 FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress, TeStrippedOffset);
1111 if (FixupBase == NULL) {
1112 ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
1113 return RETURN_LOAD_ERROR;
1114 }
1115
1116 //
1117 // Run this relocation record
1118 //
1119 while ((UINTN)Reloc < (UINTN)RelocEnd) {
1120 Fixup = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress + (*Reloc & 0xFFF), TeStrippedOffset);
1121 if (Fixup == NULL) {
1122 ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
1123 return RETURN_LOAD_ERROR;
1124 }
1125
1126 switch ((*Reloc) >> 12) {
1127 case EFI_IMAGE_REL_BASED_ABSOLUTE:
1128 break;
1129
1130 case EFI_IMAGE_REL_BASED_HIGH:
1131 Fixup16 = (UINT16 *)Fixup;
1132 *Fixup16 = (UINT16)(*Fixup16 + ((UINT16)((UINT32)Adjust >> 16)));
1133 if (FixupData != NULL) {
1134 *(UINT16 *)FixupData = *Fixup16;
1135 FixupData = FixupData + sizeof (UINT16);
1136 }
1137
1138 break;
1139
1140 case EFI_IMAGE_REL_BASED_LOW:
1141 Fixup16 = (UINT16 *)Fixup;
1142 *Fixup16 = (UINT16)(*Fixup16 + (UINT16)Adjust);
1143 if (FixupData != NULL) {
1144 *(UINT16 *)FixupData = *Fixup16;
1145 FixupData = FixupData + sizeof (UINT16);
1146 }
1147
1148 break;
1149
1150 case EFI_IMAGE_REL_BASED_HIGHLOW:
1151 Fixup32 = (UINT32 *)Fixup;
1152 *Fixup32 = *Fixup32 + (UINT32)Adjust;
1153 if (FixupData != NULL) {
1154 FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));
1155 *(UINT32 *)FixupData = *Fixup32;
1156 FixupData = FixupData + sizeof (UINT32);
1157 }
1158
1159 break;
1160
1161 case EFI_IMAGE_REL_BASED_DIR64:
1162 Fixup64 = (UINT64 *)Fixup;
1163 *Fixup64 = *Fixup64 + (UINT64)Adjust;
1164 if (FixupData != NULL) {
1165 FixupData = ALIGN_POINTER (FixupData, sizeof (UINT64));
1166 *(UINT64 *)(FixupData) = *Fixup64;
1167 FixupData = FixupData + sizeof (UINT64);
1168 }
1169
1170 break;
1171
1172 default:
1173 //
1174 // The common code does not handle some of the stranger IPF relocations
1175 // PeCoffLoaderRelocateImageEx () adds support for these complex fixups
1176 // on IPF and is a No-Op on other architectures.
1177 //
1178 Status = PeCoffLoaderRelocateImageEx (Reloc, Fixup, &FixupData, Adjust);
1179 if (RETURN_ERROR (Status)) {
1180 ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
1181 return Status;
1182 }
1183 }
1184
1185 //
1186 // Next relocation record
1187 //
1188 Reloc += 1;
1189 }
1190
1191 //
1192 // Next reloc block
1193 //
1194 RelocBase = (EFI_IMAGE_BASE_RELOCATION *)RelocEnd;
1195 }
1196
1197 ASSERT ((UINTN)FixupData <= (UINTN)ImageContext->FixupData + ImageContext->FixupDataSize);
1198
1199 //
1200 // Adjust the EntryPoint to match the linked-to address
1201 //
1202 if (ImageContext->DestinationAddress != 0) {
1203 ImageContext->EntryPoint -= (UINT64)ImageContext->ImageAddress;
1204 ImageContext->EntryPoint += (UINT64)ImageContext->DestinationAddress;
1205 }
1206 }
1207
1208 // Applies additional environment specific actions to relocate fixups
1209 // to a PE/COFF image if needed
1211
1212 return RETURN_SUCCESS;
1213}
1214
1246RETURN_STATUS
1247EFIAPI
1249 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
1250 )
1251{
1252 RETURN_STATUS Status;
1254 PE_COFF_LOADER_IMAGE_CONTEXT CheckContext;
1255 EFI_IMAGE_SECTION_HEADER *FirstSection;
1256 EFI_IMAGE_SECTION_HEADER *Section;
1257 UINTN NumberOfSections;
1258 UINTN Index;
1259 CHAR8 *Base;
1260 CHAR8 *End;
1261 EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;
1263 UINTN Size;
1264 UINT32 TempDebugEntryRva;
1265 UINT32 NumberOfRvaAndSizes;
1266 EFI_IMAGE_RESOURCE_DIRECTORY *ResourceDirectory;
1267 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *ResourceDirectoryEntry;
1268 EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirectoryString;
1269 EFI_IMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry;
1270 CHAR16 *String;
1271 UINT32 Offset;
1272 UINT32 TeStrippedOffset;
1273
1274 ASSERT (ImageContext != NULL);
1275
1276 //
1277 // Assume success
1278 //
1279 ImageContext->ImageError = IMAGE_ERROR_SUCCESS;
1280
1281 //
1282 // Copy the provided context information into our local version, get what we
1283 // can from the original image, and then use that to make sure everything
1284 // is legit.
1285 //
1286 CopyMem (&CheckContext, ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
1287
1288 Status = PeCoffLoaderGetImageInfo (&CheckContext);
1289 if (RETURN_ERROR (Status)) {
1290 return Status;
1291 }
1292
1293 //
1294 // Make sure there is enough allocated space for the image being loaded
1295 //
1296 if (ImageContext->ImageSize < CheckContext.ImageSize) {
1297 ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_SIZE;
1299 }
1300
1301 if (ImageContext->ImageAddress == 0) {
1302 //
1303 // Image cannot be loaded into 0 address.
1304 //
1305 ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;
1307 }
1308
1309 //
1310 // If there's no relocations, then make sure it's not a runtime driver,
1311 // and that it's being loaded at the linked address.
1312 //
1313 if (CheckContext.RelocationsStripped) {
1314 //
1315 // If the image does not contain relocations and it is a runtime driver
1316 // then return an error.
1317 //
1318 if (CheckContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
1319 ImageContext->ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM;
1320 return RETURN_LOAD_ERROR;
1321 }
1322
1323 //
1324 // If the image does not contain relocations, and the requested load address
1325 // is not the linked address, then return an error.
1326 //
1327 if (CheckContext.ImageAddress != ImageContext->ImageAddress) {
1328 ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;
1330 }
1331 }
1332
1333 //
1334 // Make sure the allocated space has the proper section alignment
1335 //
1336 if (!(ImageContext->IsTeImage)) {
1337 if ((ImageContext->ImageAddress & (CheckContext.SectionAlignment - 1)) != 0) {
1338 ImageContext->ImageError = IMAGE_ERROR_INVALID_SECTION_ALIGNMENT;
1340 }
1341 }
1342
1343 //
1344 // Read the entire PE/COFF or TE header into memory
1345 //
1346 if (!(ImageContext->IsTeImage)) {
1347 Status = ImageContext->ImageRead (
1348 ImageContext->Handle,
1349 0,
1350 &ImageContext->SizeOfHeaders,
1351 (VOID *)(UINTN)ImageContext->ImageAddress
1352 );
1353
1354 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset);
1355
1356 FirstSection = (EFI_IMAGE_SECTION_HEADER *)(
1357 (UINTN)ImageContext->ImageAddress +
1358 ImageContext->PeCoffHeaderOffset +
1359 sizeof (UINT32) +
1360 sizeof (EFI_IMAGE_FILE_HEADER) +
1361 Hdr.Pe32->FileHeader.SizeOfOptionalHeader
1362 );
1363 NumberOfSections = (UINTN)(Hdr.Pe32->FileHeader.NumberOfSections);
1364 TeStrippedOffset = 0;
1365 } else {
1366 Status = ImageContext->ImageRead (
1367 ImageContext->Handle,
1368 0,
1369 &ImageContext->SizeOfHeaders,
1370 (void *)(UINTN)ImageContext->ImageAddress
1371 );
1372
1373 Hdr.Te = (EFI_TE_IMAGE_HEADER *)(UINTN)(ImageContext->ImageAddress);
1374 FirstSection = (EFI_IMAGE_SECTION_HEADER *)(
1375 (UINTN)ImageContext->ImageAddress +
1376 sizeof (EFI_TE_IMAGE_HEADER)
1377 );
1378 NumberOfSections = (UINTN)(Hdr.Te->NumberOfSections);
1379 TeStrippedOffset = (UINT32)Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);
1380 }
1381
1382 if (RETURN_ERROR (Status)) {
1383 ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
1384 return RETURN_LOAD_ERROR;
1385 }
1386
1387 //
1388 // Load each section of the image
1389 //
1390 Section = FirstSection;
1391 for (Index = 0; Index < NumberOfSections; Index++) {
1392 //
1393 // Read the section
1394 //
1395 Size = (UINTN)Section->Misc.VirtualSize;
1396 if ((Size == 0) || (Size > Section->SizeOfRawData)) {
1397 Size = (UINTN)Section->SizeOfRawData;
1398 }
1399
1400 //
1401 // Compute sections address
1402 //
1403 Base = PeCoffLoaderImageAddress (ImageContext, Section->VirtualAddress, TeStrippedOffset);
1404 End = PeCoffLoaderImageAddress (ImageContext, Section->VirtualAddress + Section->Misc.VirtualSize - 1, TeStrippedOffset);
1405
1406 //
1407 // If the size of the section is non-zero and the base address or end address resolved to 0, then fail.
1408 //
1409 if ((Size > 0) && ((Base == NULL) || (End == NULL))) {
1410 ImageContext->ImageError = IMAGE_ERROR_SECTION_NOT_LOADED;
1411 return RETURN_LOAD_ERROR;
1412 }
1413
1414 if ((Section->SizeOfRawData > 0) && (Base != NULL)) {
1415 Status = ImageContext->ImageRead (
1416 ImageContext->Handle,
1417 Section->PointerToRawData - TeStrippedOffset,
1418 &Size,
1419 Base
1420 );
1421 if (RETURN_ERROR (Status)) {
1422 ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
1423 return Status;
1424 }
1425 }
1426
1427 //
1428 // If raw size is less then virtual size, zero fill the remaining
1429 //
1430
1431 if ((Size < Section->Misc.VirtualSize) && (Base != NULL)) {
1432 ZeroMem (Base + Size, Section->Misc.VirtualSize - Size);
1433 }
1434
1435 //
1436 // Next Section
1437 //
1438 Section += 1;
1439 }
1440
1441 //
1442 // Get image's entry point
1443 //
1444 if (!(ImageContext->IsTeImage)) {
1445 //
1446 // Sizes of AddressOfEntryPoint are different so we need to do this safely
1447 //
1448 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1449 //
1450 // Use PE32 offset
1451 //
1452 ImageContext->EntryPoint = (PHYSICAL_ADDRESS)(UINTN)PeCoffLoaderImageAddress (
1453 ImageContext,
1454 (UINTN)Hdr.Pe32->OptionalHeader.AddressOfEntryPoint,
1455 0
1456 );
1457 } else {
1458 //
1459 // Use PE32+ offset
1460 //
1461 ImageContext->EntryPoint = (PHYSICAL_ADDRESS)(UINTN)PeCoffLoaderImageAddress (
1462 ImageContext,
1463 (UINTN)Hdr.Pe32Plus->OptionalHeader.AddressOfEntryPoint,
1464 0
1465 );
1466 }
1467 } else {
1468 ImageContext->EntryPoint = (PHYSICAL_ADDRESS)(UINTN)PeCoffLoaderImageAddress (
1469 ImageContext,
1470 (UINTN)Hdr.Te->AddressOfEntryPoint,
1471 TeStrippedOffset
1472 );
1473 }
1474
1475 //
1476 // Determine the size of the fixup data
1477 //
1478 // Per the PE/COFF spec, you can't assume that a given data directory
1479 // is present in the image. You have to check the NumberOfRvaAndSizes in
1480 // the optional header to verify a desired directory entry is there.
1481 //
1482 if (!(ImageContext->IsTeImage)) {
1483 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1484 //
1485 // Use PE32 offset
1486 //
1487 NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
1488 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
1489 } else {
1490 //
1491 // Use PE32+ offset
1492 //
1493 NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
1494 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
1495 }
1496
1497 //
1498 // Must use UINT64 here, because there might a case that 32bit loader to load 64bit image.
1499 //
1500 if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
1501 ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINT64);
1502 } else {
1503 ImageContext->FixupDataSize = 0;
1504 }
1505 } else {
1506 DirectoryEntry = &Hdr.Te->DataDirectory[0];
1507 ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINT64);
1508 }
1509
1510 //
1511 // Consumer must allocate a buffer for the relocation fixup log.
1512 // Only used for runtime drivers.
1513 //
1514 ImageContext->FixupData = NULL;
1515
1516 //
1517 // Load the Codeview information if present
1518 //
1519 if (ImageContext->DebugDirectoryEntryRva != 0) {
1520 DebugEntry = PeCoffLoaderImageAddress (
1521 ImageContext,
1522 ImageContext->DebugDirectoryEntryRva,
1523 TeStrippedOffset
1524 );
1525 if (DebugEntry == NULL) {
1526 ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
1527 return RETURN_LOAD_ERROR;
1528 }
1529
1530 TempDebugEntryRva = DebugEntry->RVA;
1531 if ((DebugEntry->RVA == 0) && (DebugEntry->FileOffset != 0)) {
1532 Section--;
1533 if ((UINTN)Section->SizeOfRawData < Section->Misc.VirtualSize) {
1534 TempDebugEntryRva = Section->VirtualAddress + Section->Misc.VirtualSize;
1535 } else {
1536 TempDebugEntryRva = Section->VirtualAddress + Section->SizeOfRawData;
1537 }
1538 }
1539
1540 if (TempDebugEntryRva != 0) {
1541 ImageContext->CodeView = PeCoffLoaderImageAddress (ImageContext, TempDebugEntryRva, TeStrippedOffset);
1542 if (ImageContext->CodeView == NULL) {
1543 ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
1544 return RETURN_LOAD_ERROR;
1545 }
1546
1547 if (DebugEntry->RVA == 0) {
1548 Size = DebugEntry->SizeOfData;
1549 Status = ImageContext->ImageRead (
1550 ImageContext->Handle,
1551 DebugEntry->FileOffset - TeStrippedOffset,
1552 &Size,
1553 ImageContext->CodeView
1554 );
1555 //
1556 // Should we apply fix up to this field according to the size difference between PE and TE?
1557 // Because now we maintain TE header fields unfixed, this field will also remain as they are
1558 // in original PE image.
1559 //
1560
1561 if (RETURN_ERROR (Status)) {
1562 ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
1563 return RETURN_LOAD_ERROR;
1564 }
1565
1566 DebugEntry->RVA = TempDebugEntryRva;
1567 }
1568
1569 switch (*(UINT32 *)ImageContext->CodeView) {
1571 if (DebugEntry->SizeOfData < sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY)) {
1572 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
1573 return RETURN_UNSUPPORTED;
1574 }
1575
1576 ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
1577 break;
1578
1580 if (DebugEntry->SizeOfData < sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY)) {
1581 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
1582 return RETURN_UNSUPPORTED;
1583 }
1584
1585 ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
1586 break;
1587
1589 if (DebugEntry->SizeOfData < sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY)) {
1590 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
1591 return RETURN_UNSUPPORTED;
1592 }
1593
1594 ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY);
1595 break;
1596
1597 default:
1598 break;
1599 }
1600 }
1601 }
1602
1603 //
1604 // Get Image's HII resource section
1605 //
1606 ImageContext->HiiResourceData = 0;
1607 if (!(ImageContext->IsTeImage)) {
1608 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1609 //
1610 // Use PE32 offset
1611 //
1612 NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
1613 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE];
1614 } else {
1615 //
1616 // Use PE32+ offset
1617 //
1618 NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
1619 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE];
1620 }
1621
1622 if ((NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE) && (DirectoryEntry->Size != 0)) {
1623 Base = PeCoffLoaderImageAddress (ImageContext, DirectoryEntry->VirtualAddress, 0);
1624 if (Base != NULL) {
1625 ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *)Base;
1627 (ResourceDirectory->NumberOfNamedEntries + ResourceDirectory->NumberOfIdEntries);
1628 if (Offset > DirectoryEntry->Size) {
1629 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
1630 return RETURN_UNSUPPORTED;
1631 }
1632
1633 ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *)(ResourceDirectory + 1);
1634
1635 for (Index = 0; Index < ResourceDirectory->NumberOfNamedEntries; Index++) {
1636 if (ResourceDirectoryEntry->u1.s.NameIsString) {
1637 //
1638 // Check the ResourceDirectoryEntry->u1.s.NameOffset before use it.
1639 //
1640 if (ResourceDirectoryEntry->u1.s.NameOffset >= DirectoryEntry->Size) {
1641 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
1642 return RETURN_UNSUPPORTED;
1643 }
1644
1645 ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *)(Base + ResourceDirectoryEntry->u1.s.NameOffset);
1646 String = &ResourceDirectoryString->String[0];
1647
1648 if ((ResourceDirectoryString->Length == 3) &&
1649 (String[0] == L'H') &&
1650 (String[1] == L'I') &&
1651 (String[2] == L'I'))
1652 {
1653 //
1654 // Resource Type "HII" found
1655 //
1656 if (ResourceDirectoryEntry->u2.s.DataIsDirectory) {
1657 //
1658 // Move to next level - resource Name
1659 //
1660 if (ResourceDirectoryEntry->u2.s.OffsetToDirectory >= DirectoryEntry->Size) {
1661 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
1662 return RETURN_UNSUPPORTED;
1663 }
1664
1665 ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *)(Base + ResourceDirectoryEntry->u2.s.OffsetToDirectory);
1666 Offset = ResourceDirectoryEntry->u2.s.OffsetToDirectory + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY) +
1667 sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY) * (ResourceDirectory->NumberOfNamedEntries + ResourceDirectory->NumberOfIdEntries);
1668 if (Offset > DirectoryEntry->Size) {
1669 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
1670 return RETURN_UNSUPPORTED;
1671 }
1672
1673 ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *)(ResourceDirectory + 1);
1674
1675 if (ResourceDirectoryEntry->u2.s.DataIsDirectory) {
1676 //
1677 // Move to next level - resource Language
1678 //
1679 if (ResourceDirectoryEntry->u2.s.OffsetToDirectory >= DirectoryEntry->Size) {
1680 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
1681 return RETURN_UNSUPPORTED;
1682 }
1683
1684 ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *)(Base + ResourceDirectoryEntry->u2.s.OffsetToDirectory);
1685 Offset = ResourceDirectoryEntry->u2.s.OffsetToDirectory + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY) +
1686 sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY) * (ResourceDirectory->NumberOfNamedEntries + ResourceDirectory->NumberOfIdEntries);
1687 if (Offset > DirectoryEntry->Size) {
1688 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
1689 return RETURN_UNSUPPORTED;
1690 }
1691
1692 ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *)(ResourceDirectory + 1);
1693 }
1694 }
1695
1696 //
1697 // Now it ought to be resource Data
1698 //
1699 if (!ResourceDirectoryEntry->u2.s.DataIsDirectory) {
1700 if (ResourceDirectoryEntry->u2.OffsetToData >= DirectoryEntry->Size) {
1701 ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;
1702 return RETURN_UNSUPPORTED;
1703 }
1704
1705 ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *)(Base + ResourceDirectoryEntry->u2.OffsetToData);
1706 ImageContext->HiiResourceData = (PHYSICAL_ADDRESS)(UINTN)PeCoffLoaderImageAddress (ImageContext, ResourceDataEntry->OffsetToData, 0);
1707 break;
1708 }
1709 }
1710 }
1711
1712 ResourceDirectoryEntry++;
1713 }
1714 }
1715 }
1716 }
1717
1718 return Status;
1719}
1720
1744VOID
1745EFIAPI
1747 IN PHYSICAL_ADDRESS ImageBase,
1748 IN PHYSICAL_ADDRESS VirtImageBase,
1749 IN UINTN ImageSize,
1750 IN VOID *RelocationData
1751 )
1752{
1753 CHAR8 *OldBase;
1754 CHAR8 *NewBase;
1755 EFI_IMAGE_DOS_HEADER *DosHdr;
1757 UINT32 NumberOfRvaAndSizes;
1758 EFI_IMAGE_DATA_DIRECTORY *DataDirectory;
1759 EFI_IMAGE_DATA_DIRECTORY *RelocDir;
1760 EFI_IMAGE_BASE_RELOCATION *RelocBase;
1761 EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd;
1762 EFI_IMAGE_BASE_RELOCATION *RelocBaseOrig;
1763 UINT16 *Reloc;
1764 UINT16 *RelocEnd;
1765 CHAR8 *Fixup;
1766 CHAR8 *FixupBase;
1767 UINT16 *Fixup16;
1768 UINT32 *Fixup32;
1769 UINT64 *Fixup64;
1770 CHAR8 *FixupData;
1771 UINTN Adjust;
1772 RETURN_STATUS Status;
1773 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
1774 UINT32 EndAddress;
1775
1776 if ((RelocationData == NULL) || (ImageBase == 0x0) || (VirtImageBase == 0x0)) {
1777 return;
1778 }
1779
1780 OldBase = (CHAR8 *)((UINTN)ImageBase);
1781 NewBase = (CHAR8 *)((UINTN)VirtImageBase);
1782 Adjust = (UINTN)NewBase - (UINTN)OldBase;
1783
1784 ImageContext.ImageAddress = ImageBase;
1785 ImageContext.ImageSize = ImageSize;
1786
1787 //
1788 // Find the image's relocate dir info
1789 //
1790 DosHdr = (EFI_IMAGE_DOS_HEADER *)OldBase;
1791 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
1792 //
1793 // Valid DOS header so get address of PE header
1794 //
1795 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(((CHAR8 *)DosHdr) + DosHdr->e_lfanew);
1796 } else {
1797 //
1798 // No Dos header so assume image starts with PE header.
1799 //
1800 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)OldBase;
1801 }
1802
1803 if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
1804 //
1805 // Not a valid PE image so Exit
1806 //
1807 return;
1808 }
1809
1810 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1811 //
1812 // Use PE32 offset
1813 //
1814 NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
1815 DataDirectory = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[0]);
1816 } else {
1817 //
1818 // Use PE32+ offset
1819 //
1820 NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
1821 DataDirectory = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[0]);
1822 }
1823
1824 //
1825 // Find the relocation block
1826 //
1827 // Per the PE/COFF spec, you can't assume that a given data directory
1828 // is present in the image. You have to check the NumberOfRvaAndSizes in
1829 // the optional header to verify a desired directory entry is there.
1830 //
1831 RelocBase = NULL;
1832 RelocBaseEnd = NULL;
1833 if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
1834 RelocDir = DataDirectory + EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC;
1835 if ((RelocDir != NULL) && (RelocDir->Size > 0)) {
1836 Status = SafeUint32Add (RelocDir->VirtualAddress, (RelocDir->Size - 1), &EndAddress);
1837 if (!RETURN_ERROR (Status)) {
1838 RelocBase = (EFI_IMAGE_BASE_RELOCATION *)PeCoffLoaderImageAddress (&ImageContext, RelocDir->VirtualAddress, 0);
1840 &ImageContext,
1841 EndAddress,
1842 0
1843 );
1844 }
1845 }
1846
1847 if ((RelocBase == NULL) || (RelocBaseEnd == NULL) || ((UINTN)RelocBaseEnd < (UINTN)RelocBase)) {
1848 //
1849 // relocation block is not valid, just return
1850 //
1851 return;
1852 }
1853 } else {
1854 //
1855 // Cannot find relocations, cannot continue to relocate the image, ASSERT for this invalid image.
1856 //
1857 ASSERT (FALSE);
1858 return;
1859 }
1860
1861 //
1862 // ASSERT for the invalid image when RelocBase and RelocBaseEnd are both NULL.
1863 //
1864 ASSERT (RelocBase != NULL && RelocBaseEnd != NULL);
1865
1866 if (Adjust != 0) {
1867 //
1868 // Run the whole relocation block. And re-fixup data that has not been
1869 // modified. The FixupData is used to see if the image has been modified
1870 // since it was relocated. This is so data sections that have been updated
1871 // by code will not be fixed up, since that would set them back to
1872 // defaults.
1873 //
1874 FixupData = RelocationData;
1875 RelocBaseOrig = RelocBase;
1876 while ((UINTN)RelocBase < (UINTN)RelocBaseEnd) {
1877 //
1878 // Add check for RelocBase->SizeOfBlock field.
1879 //
1880 if ((RelocBase->SizeOfBlock == 0) || (RelocBase->SizeOfBlock > RelocDir->Size)) {
1881 //
1882 // Data invalid, cannot continue to relocate the image, just return.
1883 //
1884 return;
1885 }
1886
1887 Reloc = (UINT16 *)((UINT8 *)RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));
1888 RelocEnd = (UINT16 *)((UINT8 *)RelocBase + RelocBase->SizeOfBlock);
1889 if ((UINTN)RelocEnd > (UINTN)RelocBaseOrig + RelocDir->Size) {
1890 return;
1891 }
1892
1893 FixupBase = PeCoffLoaderImageAddress (&ImageContext, RelocBase->VirtualAddress, 0);
1894 if (FixupBase == NULL) {
1895 return;
1896 }
1897
1898 //
1899 // Run this relocation record
1900 //
1901 while ((UINTN)Reloc < (UINTN)RelocEnd) {
1902 Fixup = PeCoffLoaderImageAddress (&ImageContext, RelocBase->VirtualAddress + (*Reloc & 0xFFF), 0);
1903 if (Fixup == NULL) {
1904 return;
1905 }
1906
1907 switch ((*Reloc) >> 12) {
1908 case EFI_IMAGE_REL_BASED_ABSOLUTE:
1909 break;
1910
1911 case EFI_IMAGE_REL_BASED_HIGH:
1912 Fixup16 = (UINT16 *)Fixup;
1913 if (*(UINT16 *)FixupData == *Fixup16) {
1914 *Fixup16 = (UINT16)(*Fixup16 + ((UINT16)((UINT32)Adjust >> 16)));
1915 }
1916
1917 FixupData = FixupData + sizeof (UINT16);
1918 break;
1919
1920 case EFI_IMAGE_REL_BASED_LOW:
1921 Fixup16 = (UINT16 *)Fixup;
1922 if (*(UINT16 *)FixupData == *Fixup16) {
1923 *Fixup16 = (UINT16)(*Fixup16 + ((UINT16)Adjust & 0xffff));
1924 }
1925
1926 FixupData = FixupData + sizeof (UINT16);
1927 break;
1928
1929 case EFI_IMAGE_REL_BASED_HIGHLOW:
1930 Fixup32 = (UINT32 *)Fixup;
1931 FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));
1932 if (*(UINT32 *)FixupData == *Fixup32) {
1933 *Fixup32 = *Fixup32 + (UINT32)Adjust;
1934 }
1935
1936 FixupData = FixupData + sizeof (UINT32);
1937 break;
1938
1939 case EFI_IMAGE_REL_BASED_DIR64:
1940 Fixup64 = (UINT64 *)Fixup;
1941 FixupData = ALIGN_POINTER (FixupData, sizeof (UINT64));
1942 if (*(UINT64 *)FixupData == *Fixup64) {
1943 *Fixup64 = *Fixup64 + (UINT64)Adjust;
1944 }
1945
1946 FixupData = FixupData + sizeof (UINT64);
1947 break;
1948
1949 default:
1950 //
1951 // Only Itanium requires ConvertPeImage_Ex
1952 //
1953 Status = PeHotRelocateImageEx (Reloc, Fixup, &FixupData, Adjust);
1954 if (RETURN_ERROR (Status)) {
1955 return;
1956 }
1957 }
1958
1959 //
1960 // Next relocation record
1961 //
1962 Reloc += 1;
1963 }
1964
1965 //
1966 // next reloc block
1967 //
1968 RelocBase = (EFI_IMAGE_BASE_RELOCATION *)RelocEnd;
1969 }
1970 }
1971}
1972
1998RETURN_STATUS
1999EFIAPI
2001 IN VOID *FileHandle,
2002 IN UINTN FileOffset,
2003 IN OUT UINTN *ReadSize,
2004 OUT VOID *Buffer
2005 )
2006{
2007 ASSERT (ReadSize != NULL);
2008 ASSERT (FileHandle != NULL);
2009 ASSERT (Buffer != NULL);
2010
2011 CopyMem (Buffer, ((UINT8 *)FileHandle) + FileOffset, *ReadSize);
2012 return RETURN_SUCCESS;
2013}
2014
2031RETURN_STATUS
2032EFIAPI
2034 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
2035 )
2036{
2037 //
2038 // Applies additional environment specific actions to unload a
2039 // PE/COFF image if needed
2040 //
2042 return RETURN_SUCCESS;
2043}
UINT64 UINTN
#define MAX_ADDRESS
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
RETURN_STATUS EFIAPI PeCoffLoaderLoadImage(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext)
Definition: BasePeCoff.c:1248
RETURN_STATUS EFIAPI PeCoffLoaderRelocateImage(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext)
Definition: BasePeCoff.c:957
VOID EFIAPI PeCoffLoaderRelocateImageForRuntime(IN PHYSICAL_ADDRESS ImageBase, IN PHYSICAL_ADDRESS VirtImageBase, IN UINTN ImageSize, IN VOID *RelocationData)
Definition: BasePeCoff.c:1746
VOID PeCoffLoaderAdjustOffsetForTeImage(EFI_IMAGE_SECTION_HEADER *SectionHeader, UINT32 TeStrippedOffset)
Definition: BasePeCoff.c:37
RETURN_STATUS EFIAPI PeCoffLoaderUnloadImage(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext)
Definition: BasePeCoff.c:2033
VOID * PeCoffLoaderImageAddress(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, IN UINTN Address, IN UINTN TeStrippedOffset)
Definition: BasePeCoff.c:908
RETURN_STATUS PeCoffLoaderGetPeHeader(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr)
Definition: BasePeCoff.c:62
RETURN_STATUS EFIAPI PeCoffLoaderGetImageInfo(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext)
Definition: BasePeCoff.c:578
RETURN_STATUS EFIAPI PeCoffLoaderImageReadFromMemory(IN VOID *FileHandle, IN UINTN FileOffset, IN OUT UINTN *ReadSize, OUT VOID *Buffer)
Definition: BasePeCoff.c:2000
RETURN_STATUS PeHotRelocateImageEx(IN UINT16 *Reloc, IN OUT CHAR8 *Fixup, IN OUT CHAR8 **FixupData, IN UINT64 Adjust)
RETURN_STATUS PeCoffLoaderRelocateImageEx(IN UINT16 *Reloc, IN OUT CHAR8 *Fixup, IN OUT CHAR8 **FixupData, IN UINT64 Adjust)
BOOLEAN PeCoffLoaderImageFormatSupported(IN UINT16 Machine)
VOID EFIAPI PeCoffLoaderUnloadImageExtraAction(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext)
VOID EFIAPI PeCoffLoaderRelocateImageExtraAction(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext)
#define NULL
Definition: Base.h:319
#define RETURN_LOAD_ERROR
Definition: Base.h:1071
#define RETURN_BUFFER_TOO_SMALL
Definition: Base.h:1093
#define RETURN_ERROR(StatusCode)
Definition: Base.h:1061
#define RETURN_UNSUPPORTED
Definition: Base.h:1081
#define ALIGN_POINTER(Pointer, Alignment)
Definition: Base.h:963
#define VOID
Definition: Base.h:269
#define RETURN_SUCCESS
Definition: Base.h:1066
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define RETURN_INVALID_PARAMETER
Definition: Base.h:1076
#define DEBUG(Expression)
Definition: DebugLib.h:435
#define CODEVIEW_SIGNATURE_NB10
Definition: PeImage.h:656
#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW
The Visual C++ debug information.
Definition: PeImage.h:650
#define CODEVIEW_SIGNATURE_RSDS
Definition: PeImage.h:670
#define EFI_IMAGE_SIZEOF_SECTION_HEADER
Definition: PeImage.h:313
#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
Definition: PeImage.h:142
#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
Definition: PeImage.h:193
#define EFI_IMAGE_FILE_RELOCS_STRIPPED
0x0001 Relocation info stripped from file.
Definition: PeImage.h:99
#define CODEVIEW_SIGNATURE_MTOC
Definition: PeImage.h:686
RETURN_STATUS EFIAPI SafeUint32Add(IN UINT32 Augend, IN UINT32 Addend, OUT UINT32 *Result)
Definition: SafeIntLib.c:2927
UINT32 FileOffset
The file pointer to the debug data.
Definition: PeImage.h:647
UINT32 RVA
The address of the debug data when loaded, relative to the image base.
Definition: PeImage.h:646
UINT32 e_lfanew
File address of new exe header.
Definition: PeImage.h:75
UINT16 e_magic
Magic number.
Definition: PeImage.h:57
UINT32 AddressOfEntryPoint
Offset to entry point – from original optional header.
Definition: PeImage.h:785
UINT64 ImageBase
From original file header.
Definition: PeImage.h:787
EFI_IMAGE_DATA_DIRECTORY DataDirectory[2]
Only base relocation and debug directory.
Definition: PeImage.h:788
UINT16 StrippedSize
Number of bytes we removed from the header.
Definition: PeImage.h:784
UINT8 NumberOfSections
From the original file header.
Definition: PeImage.h:782
PHYSICAL_ADDRESS ImageAddress
Definition: PeCoffLib.h:79