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