62 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context,
65 IN BOOLEAN InMemoryFixup
71 UINT32 PreFixupVirtualAddress;
72 UINT32 PostFixupVirtualAddress;
73 UINT32 PreFixupVirtualSize;
74 UINT32 PostFixupVirtualSize;
75 CHAR8 SectionName[EFI_IMAGE_SIZEOF_SHORT_NAME + 1];
78 EFI_IMAGE_SECTION_HEADER *Sections;
81 ASSERT (IS_POW2 (Context->SectionAlignment));
86 if (Context->NumberOfSections == 0) {
88 return RETURN_VOLUME_CORRUPTED;
91 Sections = (EFI_IMAGE_SECTION_HEADER *)(VOID *)(
92 (CHAR8 *)Context->FileBuffer + Context->SectionsOffset
98 if (Sections[0].VirtualAddress == 0) {
106 if ((PcdGet32 (PcdImageLoaderAlignmentPolicy) & PCD_ALIGNMENT_POLICY_CONTIGUOUS_SECTIONS) == 0) {
107 Overflow = BaseOverflowAlignUpU32 (
108 Context->SizeOfHeaders,
109 Context->SectionAlignment,
114 return RETURN_VOLUME_CORRUPTED;
117 NextSectRva = Context->SizeOfHeaders;
121 SectionName[
L_STR_LEN (SectionName)] =
'\0';
126 for (SectionIndex = 0; SectionIndex < Context->NumberOfSections; ++SectionIndex) {
127 AsciiStrnCpyS (SectionName,
L_STR_SIZE (SectionName), (CHAR8 *)Sections[SectionIndex].Name, EFI_IMAGE_SIZEOF_SHORT_NAME);
131 if ((Sections[SectionIndex].Characteristics & (EFI_IMAGE_SCN_MEM_EXECUTE | EFI_IMAGE_SCN_MEM_WRITE)) == (EFI_IMAGE_SCN_MEM_EXECUTE | EFI_IMAGE_SCN_MEM_WRITE)) {
133 Sections[SectionIndex].Characteristics &= ~EFI_IMAGE_SCN_MEM_EXECUTE;
136 DEBUG ((DEBUG_INFO,
"OCPE: %u fixup W^X for %a\n", InMemoryFixup, SectionName));
145 PreFixupVirtualAddress = Sections[SectionIndex].VirtualAddress;
146 PostFixupVirtualAddress = PreFixupVirtualAddress;
147 PreFixupVirtualSize = Sections[SectionIndex].VirtualSize;
148 PostFixupVirtualSize = PreFixupVirtualSize;
149 if ((PcdGet32 (PcdImageLoaderAlignmentPolicy) & PCD_ALIGNMENT_POLICY_CONTIGUOUS_SECTIONS) == 0) {
150 if (Sections[SectionIndex].VirtualAddress != NextSectRva) {
152 return RETURN_VOLUME_CORRUPTED;
155 if (Sections[SectionIndex].VirtualAddress < NextSectRva) {
159 if (Sections[SectionIndex].SizeOfRawData > 0) {
161 return RETURN_VOLUME_CORRUPTED;
167 FixupOffset = NextSectRva - Sections[SectionIndex].VirtualAddress;
168 if (FixupOffset > Sections[SectionIndex].VirtualSize) {
169 PostFixupVirtualSize = 0;
171 PostFixupVirtualSize -= FixupOffset;
174 PostFixupVirtualAddress = NextSectRva;
176 Sections[SectionIndex].VirtualAddress = PostFixupVirtualAddress;
177 Sections[SectionIndex].VirtualSize = PostFixupVirtualSize;
182 "OCPE: %u fixup section overlap for %a 0x%X(0x%X)->0x%X(0x%X)\n",
185 PreFixupVirtualAddress,
187 PostFixupVirtualAddress,
198 if (!IS_ALIGNED (PostFixupVirtualAddress, Context->SectionAlignment)) {
200 DEFAULT_PAGE_ALLOCATION_GRANULARITY <= RUNTIME_PAGE_ALLOCATION_GRANULARITY,
201 "This code must be adapted to consider the reversed order."
204 if (IS_ALIGNED (PostFixupVirtualAddress, RUNTIME_PAGE_ALLOCATION_GRANULARITY)) {
205 Context->SectionAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
206 }
else if ( (DEFAULT_PAGE_ALLOCATION_GRANULARITY < RUNTIME_PAGE_ALLOCATION_GRANULARITY)
207 && IS_ALIGNED (PostFixupVirtualAddress, DEFAULT_PAGE_ALLOCATION_GRANULARITY))
209 Context->SectionAlignment = DEFAULT_PAGE_ALLOCATION_GRANULARITY;
211 Context->SectionAlignment = 1;
219 if (Sections[SectionIndex].SizeOfRawData > 0) {
220 Overflow = BaseOverflowAddU32 (
221 Sections[SectionIndex].PointerToRawData,
222 Sections[SectionIndex].SizeOfRawData,
227 return RETURN_VOLUME_CORRUPTED;
230 if (SectRawEnd > FileSize) {
232 return RETURN_VOLUME_CORRUPTED;
239 Overflow = BaseOverflowAddU32 (
240 PostFixupVirtualAddress,
241 PostFixupVirtualSize,
246 return RETURN_VOLUME_CORRUPTED;
252 if ((PcdGet32 (PcdImageLoaderAlignmentPolicy) & PCD_ALIGNMENT_POLICY_CONTIGUOUS_SECTIONS) == 0) {
253 Overflow = BaseOverflowAlignUpU32 (
255 Context->SectionAlignment,
260 return RETURN_VOLUME_CORRUPTED;
268 if ((PcdGet32 (PcdImageLoaderAlignmentPolicy) & PCD_ALIGNMENT_POLICY_CONTIGUOUS_SECTIONS) == 0) {
269 Context->SizeOfImage = NextSectRva;
279 Overflow = BaseOverflowAlignUpU32 (
281 Context->SectionAlignment,
282 &Context->SizeOfImage
285 Context->SectionAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
286 Overflow = BaseOverflowAlignUpU32 (
288 Context->SectionAlignment,
289 &Context->SizeOfImage
291 if ( (DEFAULT_PAGE_ALLOCATION_GRANULARITY < RUNTIME_PAGE_ALLOCATION_GRANULARITY)
294 Context->SectionAlignment = DEFAULT_PAGE_ALLOCATION_GRANULARITY;
295 Overflow = BaseOverflowAlignUpU32 (
297 Context->SectionAlignment,
298 &Context->SizeOfImage
303 Context->SectionAlignment = 1;
308 return RETURN_SUCCESS;
410 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context,
412 IN BOOLEAN InMemoryFixup
416 CONST EFI_IMAGE_NT_HEADERS_COMMON_HDR *PeCommon;
417 CONST EFI_IMAGE_NT_HEADERS32 *Pe32;
418 CONST EFI_IMAGE_NT_HEADERS64 *Pe32Plus;
419 CONST CHAR8 *OptHdrPtr;
420 UINT32 HdrSizeWithoutDataDir;
421 UINT32 MinSizeOfOptionalHeader;
422 UINT32 MinSizeOfHeaders;
423 CONST EFI_IMAGE_DATA_DIRECTORY *RelocDir;
424 CONST EFI_IMAGE_DATA_DIRECTORY *SecDir;
426 UINT32 NumberOfRvaAndSizes;
427 RETURN_STATUS Status;
431 ASSERT (
sizeof (EFI_IMAGE_NT_HEADERS_COMMON_HDR) +
sizeof (UINT16) <= FileSize - Context->ExeHdrOffset);
432 if (!PcdGetBool (PcdImageLoaderAllowMisalignedOffset)) {
433 ASSERT (IS_ALIGNED (Context->ExeHdrOffset, ALIGNOF (EFI_IMAGE_NT_HEADERS_COMMON_HDR)));
439 OptHdrPtr = (CONST CHAR8 *)Context->FileBuffer + Context->ExeHdrOffset;
440 OptHdrPtr +=
sizeof (EFI_IMAGE_NT_HEADERS_COMMON_HDR);
443 IS_ALIGNED (ALIGNOF (EFI_IMAGE_NT_HEADERS_COMMON_HDR), ALIGNOF (UINT16))
444 && IS_ALIGNED (
sizeof (EFI_IMAGE_NT_HEADERS_COMMON_HDR), ALIGNOF (UINT16)),
445 "The following operation might be an unaligned access."
454 switch (*(CONST UINT16 *)(CONST VOID *)OptHdrPtr) {
455 case EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC:
459 if (
sizeof (*Pe32) > FileSize - Context->ExeHdrOffset) {
461 return RETURN_VOLUME_CORRUPTED;
468 ALIGNOF (EFI_IMAGE_NT_HEADERS32) <= ALIGNOF (EFI_IMAGE_NT_HEADERS_COMMON_HDR),
469 "The following operations may be unaligned."
474 Pe32 = (CONST EFI_IMAGE_NT_HEADERS32 *)(CONST VOID *)(
475 (CONST CHAR8 *)Context->FileBuffer + Context->ExeHdrOffset
478 Context->ImageType = PeCoffLoaderTypePe32;
479 Context->Subsystem = Pe32->Subsystem;
480 Context->SizeOfHeaders = Pe32->SizeOfHeaders;
481 Context->ImageBase = Pe32->ImageBase;
482 Context->AddressOfEntryPoint = Pe32->AddressOfEntryPoint;
483 Context->SectionAlignment = Pe32->SectionAlignment;
485 RelocDir = Pe32->DataDirectory + EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC;
486 SecDir = Pe32->DataDirectory + EFI_IMAGE_DIRECTORY_ENTRY_SECURITY;
488 PeCommon = &Pe32->CommonHeader;
489 NumberOfRvaAndSizes = Pe32->NumberOfRvaAndSizes;
490 HdrSizeWithoutDataDir =
sizeof (EFI_IMAGE_NT_HEADERS32) -
sizeof (EFI_IMAGE_NT_HEADERS_COMMON_HDR);
494 case EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC:
498 if (
sizeof (*Pe32Plus) > FileSize - Context->ExeHdrOffset) {
500 return RETURN_VOLUME_CORRUPTED;
506 if ( !PcdGetBool (PcdImageLoaderAllowMisalignedOffset)
507 && !IS_ALIGNED (Context->ExeHdrOffset, ALIGNOF (EFI_IMAGE_NT_HEADERS64)))
510 return RETURN_VOLUME_CORRUPTED;
516 Pe32Plus = (CONST EFI_IMAGE_NT_HEADERS64 *)(CONST VOID *)(
517 (CONST CHAR8 *)Context->FileBuffer + Context->ExeHdrOffset
520 Context->ImageType = PeCoffLoaderTypePe32Plus;
521 Context->Subsystem = Pe32Plus->Subsystem;
522 Context->SizeOfHeaders = Pe32Plus->SizeOfHeaders;
523 Context->ImageBase = Pe32Plus->ImageBase;
524 Context->AddressOfEntryPoint = Pe32Plus->AddressOfEntryPoint;
525 Context->SectionAlignment = Pe32Plus->SectionAlignment;
527 RelocDir = Pe32Plus->DataDirectory + EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC;
528 SecDir = Pe32Plus->DataDirectory + EFI_IMAGE_DIRECTORY_ENTRY_SECURITY;
530 PeCommon = &Pe32Plus->CommonHeader;
531 NumberOfRvaAndSizes = Pe32Plus->NumberOfRvaAndSizes;
532 HdrSizeWithoutDataDir =
sizeof (EFI_IMAGE_NT_HEADERS64) -
sizeof (EFI_IMAGE_NT_HEADERS_COMMON_HDR);
541 return RETURN_UNSUPPORTED;
547 if (NumberOfRvaAndSizes > EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES) {
549 return RETURN_VOLUME_CORRUPTED;
555 if (!IS_POW2 (Context->SectionAlignment)) {
557 return RETURN_VOLUME_CORRUPTED;
561 sizeof (EFI_IMAGE_DATA_DIRECTORY) <= MAX_UINT32 / EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES,
562 "The following arithmetic may overflow."
571 Overflow = BaseOverflowAddU32 (
572 Context->ExeHdrOffset + sizeof (*PeCommon),
573 PeCommon->FileHeader.SizeOfOptionalHeader,
574 &Context->SectionsOffset
578 return RETURN_VOLUME_CORRUPTED;
584 if ( !PcdGetBool (PcdImageLoaderAllowMisalignedOffset)
585 && !IS_ALIGNED (Context->SectionsOffset, ALIGNOF (EFI_IMAGE_SECTION_HEADER)))
588 return RETURN_VOLUME_CORRUPTED;
595 MinSizeOfOptionalHeader = HdrSizeWithoutDataDir +
596 NumberOfRvaAndSizes *
sizeof (EFI_IMAGE_DATA_DIRECTORY);
598 ASSERT (MinSizeOfOptionalHeader >= HdrSizeWithoutDataDir);
601 sizeof (EFI_IMAGE_SECTION_HEADER) <= (MAX_UINT32 + 1ULL) / (MAX_UINT16 + 1ULL),
602 "The following arithmetic may overflow."
607 Overflow = BaseOverflowAddU32 (
608 Context->SectionsOffset,
609 (UINT32)PeCommon->FileHeader.NumberOfSections * sizeof (EFI_IMAGE_SECTION_HEADER),
614 return RETURN_VOLUME_CORRUPTED;
621 if (MinSizeOfOptionalHeader > PeCommon->FileHeader.SizeOfOptionalHeader) {
623 return RETURN_VOLUME_CORRUPTED;
626 if (MinSizeOfHeaders > Context->SizeOfHeaders) {
628 return RETURN_VOLUME_CORRUPTED;
634 if (Context->SizeOfHeaders > FileSize) {
636 return RETURN_VOLUME_CORRUPTED;
642 Context->NumberOfSections = PeCommon->FileHeader.NumberOfSections;
643 Context->Machine = PeCommon->FileHeader.Machine;
644 Context->RelocsStripped =
646 PeCommon->FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED
649 if (EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC < NumberOfRvaAndSizes) {
650 Context->RelocDirRva = RelocDir->VirtualAddress;
651 Context->RelocDirSize = RelocDir->Size;
653 if (Context->RelocsStripped && (Context->RelocDirSize != 0)) {
655 return RETURN_VOLUME_CORRUPTED;
658 ASSERT (Context->RelocDirRva == 0);
659 ASSERT (Context->RelocDirSize == 0);
662 if (EFI_IMAGE_DIRECTORY_ENTRY_SECURITY < NumberOfRvaAndSizes) {
663 Context->SecDirOffset = SecDir->VirtualAddress;
664 Context->SecDirSize = SecDir->Size;
668 Overflow = BaseOverflowAddU32 (
669 Context->SecDirOffset,
673 if (Overflow || (SecDirEnd > FileSize)) {
675 return RETURN_VOLUME_CORRUPTED;
683 return RETURN_VOLUME_CORRUPTED;
690 if ( (Context->SecDirSize != 0)
692 || (Context->SecDirSize < sizeof (WIN_CERTIFICATE))))
695 return RETURN_VOLUME_CORRUPTED;
701 ASSERT (Context->SecDirOffset == 0);
702 ASSERT (Context->SecDirSize == 0);
714 if (Status != RETURN_SUCCESS) {
722 if (Context->AddressOfEntryPoint >= Context->SizeOfImage) {
724 return RETURN_VOLUME_CORRUPTED;
731 if (Status != RETURN_SUCCESS) {
740 OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context,
741 IN CONST VOID *FileBuffer,
743 IN BOOLEAN InMemoryFixup
746 RETURN_STATUS Status;
747 CONST EFI_IMAGE_DOS_HEADER *DosHdr;
760 if ((PcdGet32 (PcdImageLoaderAlignmentPolicy) & PCD_ALIGNMENT_POLICY_CONTIGUOUS_SECTIONS) == 0) {
764 if (PcdGetBool (PcdImageLoaderAllowMisalignedOffset)) {
769 ASSERT (FileBuffer != NULL || FileSize == 0);
773 ZeroMem (Context,
sizeof (*Context));
775 Context->FileBuffer = FileBuffer;
776 Context->FileSize = FileSize;
780 if ( (
sizeof (*DosHdr) <= FileSize)
781 && (*(CONST UINT16 *)(CONST VOID *)FileBuffer == EFI_IMAGE_DOS_SIGNATURE))
783 DosHdr = (CONST EFI_IMAGE_DOS_HEADER *)(CONST VOID *)(
784 (CONST CHAR8 *)FileBuffer
790 if ( (
sizeof (EFI_IMAGE_DOS_HEADER) > DosHdr->e_lfanew)
791 || (DosHdr->e_lfanew > FileSize))
794 return RETURN_VOLUME_CORRUPTED;
797 Context->ExeHdrOffset = DosHdr->e_lfanew;
801 if ( !PcdGetBool (PcdImageLoaderAllowMisalignedOffset)
802 && !IS_ALIGNED (Context->ExeHdrOffset, ALIGNOF (EFI_IMAGE_NT_HEADERS_COMMON_HDR)))
804 return RETURN_UNSUPPORTED;
811 if (FileSize - Context->ExeHdrOffset < sizeof (EFI_IMAGE_NT_HEADERS_COMMON_HDR) +
sizeof (UINT16)) {
812 return RETURN_UNSUPPORTED;
816 ALIGNOF (UINT32) <= ALIGNOF (EFI_IMAGE_NT_HEADERS_COMMON_HDR),
817 "The following access may be performed unaligned"
822 if (*(CONST UINT32 *)(CONST VOID *)((CONST CHAR8 *)FileBuffer + Context->ExeHdrOffset) != EFI_IMAGE_NT_SIGNATURE) {
823 return RETURN_UNSUPPORTED;
830 if (Status != RETURN_SUCCESS) {
834 return RETURN_SUCCESS;