diff --git a/ArmVirtPkg/ArmVirtQemuKernel.dsc b/ArmVirtPkg/ArmVirtQemuKernel.dsc index 2a6fd6bc06..9449a01d6e 100644 --- a/ArmVirtPkg/ArmVirtQemuKernel.dsc +++ b/ArmVirtPkg/ArmVirtQemuKernel.dsc @@ -83,14 +83,12 @@ [LibraryClasses.common.UEFI_DRIVER] UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf -[BuildOptions.common.EDKII.SEC, BuildOptions.common.EDKII.BASE] +[BuildOptions] # - # CLANG38 with LTO support enabled uses the GNU GOLD linker, which insists - # on emitting GOT based symbol references when running in shared mode, unless - # we override visibility to 'hidden' in all modules that make up the PrePi - # build. + # We need to avoid jump tables in SEC modules, so that the PE/COFF + # self-relocation code itself is guaranteed to be position independent. # - GCC:*_CLANG38_*_CC_FLAGS = -include $(WORKSPACE)/ArmVirtPkg/Include/Platform/Hidden.h + GCC:*_*_*_CC_FLAGS = -fno-jump-tables ################################################################################ # diff --git a/ArmVirtPkg/ArmVirtXen.dsc b/ArmVirtPkg/ArmVirtXen.dsc index 8a489b2536..278f5d3828 100644 --- a/ArmVirtPkg/ArmVirtXen.dsc +++ b/ArmVirtPkg/ArmVirtXen.dsc @@ -52,14 +52,12 @@ [LibraryClasses.common.UEFI_DRIVER] UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf -[BuildOptions.common.EDKII.SEC, BuildOptions.common.EDKII.BASE] +[BuildOptions] # - # CLANG38 with LTO support enabled uses the GNU GOLD linker, which insists - # on emitting GOT based symbol references when running in shared mode, unless - # we override visibility to 'hidden' in all modules that make up the PrePi - # build. + # We need to avoid jump tables in SEC modules, so that the PE/COFF + # self-relocation code itself is guaranteed to be position independent. # - GCC:*_CLANG38_*_CC_FLAGS = -include $(WORKSPACE)/ArmVirtPkg/Include/Platform/Hidden.h + GCC:*_*_*_CC_FLAGS = -fno-jump-tables ################################################################################ # diff --git a/ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S b/ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S index 34d6abecb0..01623b6b35 100644 --- a/ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S +++ b/ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S @@ -9,40 +9,6 @@ #include ASM_FUNC(_ModuleEntryPoint) - // - // We are built as a ET_DYN PIE executable, so we need to process all - // relative relocations regardless of whether or not we are executing from - // the same offset we were linked at. This is only possible if we are - // running from RAM. - // - adr x8, __reloc_base - adr x9, __reloc_start - adr x10, __reloc_end - -.Lreloc_loop: - cmp x9, x10 - bhs .Lreloc_done - - // - // AArch64 uses the ELF64 RELA format, which means each entry in the - // relocation table consists of - // - // UINT64 offset : the relative offset of the value that needs to - // be relocated - // UINT64 info : relocation type and symbol index (the latter is - // not used for R_AARCH64_RELATIVE relocations) - // UINT64 addend : value to be added to the value being relocated - // - ldp x11, x12, [x9], #24 // read offset into x11 and info into x12 - cmp x12, #0x403 // check info == R_AARCH64_RELATIVE? - bne .Lreloc_loop // not a relative relocation? then skip - - ldr x12, [x9, #-8] // read addend into x12 - add x12, x12, x8 // add reloc base to addend to get relocated value - str x12, [x11, x8] // write relocated value at offset - b .Lreloc_loop -.Lreloc_done: - bl ASM_PFX(DiscoverDramFromDt) // Get ID of this CPU in Multicore system @@ -170,15 +136,24 @@ ASM_PFX(DiscoverDramFromDt): str x1, [x8] str x7, [x9] + // + // The runtime address may be different from the link time address so fix + // up the PE/COFF relocations. Since we are calling a C function, use the + // window at the beginning of the FD image as a temp stack. + // + mov x0, x7 + adr x1, PeCoffLoaderImageReadFromMemory + mov sp, x7 + bl RelocatePeCoffImage + // // Discover the memory size and offset from the DTB, and record in the // respective PCDs. This will also return false if a corrupt DTB is - // encountered. Since we are calling a C function, use the window at the - // beginning of the FD image as a temp stack. + // encountered. // + mov x0, x28 adr x1, PcdGet64 (PcdSystemMemoryBase) adr x2, PcdGet64 (PcdSystemMemorySize) - mov sp, x7 bl FindMemnode cbz x0, .Lout diff --git a/ArmVirtPkg/PrePi/Arm/ModuleEntryPoint.S b/ArmVirtPkg/PrePi/Arm/ModuleEntryPoint.S index 72d756fdb5..f0536c65eb 100644 --- a/ArmVirtPkg/PrePi/Arm/ModuleEntryPoint.S +++ b/ArmVirtPkg/PrePi/Arm/ModuleEntryPoint.S @@ -9,38 +9,6 @@ #include ASM_FUNC(_ModuleEntryPoint) - // - // We are built as a ET_DYN PIE executable, so we need to process all - // relative relocations if we are executing from a different offset than we - // were linked at. This is only possible if we are running from RAM. - // - ADRL (r4, __reloc_base) - ADRL (r5, __reloc_start) - ADRL (r6, __reloc_end) - -.Lreloc_loop: - cmp r5, r6 - bhs .Lreloc_done - - // - // AArch32 uses the ELF32 REL format, which means each entry in the - // relocation table consists of - // - // UINT32 offset : the relative offset of the value that needs to - // be relocated - // UINT32 info : relocation type and symbol index (the latter is - // not used for R_ARM_RELATIVE relocations) - // - ldrd r8, r9, [r5], #8 // read offset into r8 and info into r9 - cmp r9, #23 // check info == R_ARM_RELATIVE? - bne .Lreloc_loop // not a relative relocation? then skip - - ldr r9, [r8, r4] // read addend into r9 - add r9, r9, r1 // add image base to addend to get relocated value - str r9, [r8, r4] // write relocated value at offset - b .Lreloc_loop -.Lreloc_done: - // Do early platform specific actions bl ASM_PFX(ArmPlatformPeiBootAction) @@ -172,15 +140,24 @@ ASM_PFX(ArmPlatformPeiBootAction): str r1, [r8] str r5, [r7] + // + // The runtime address may be different from the link time address so fix + // up the PE/COFF relocations. Since we are calling a C function, use the + // window at the beginning of the FD image as a temp stack. + // + mov r0, r5 + ADRL (r1, PeCoffLoaderImageReadFromMemory) + mov sp, r5 + bl RelocatePeCoffImage + // // Discover the memory size and offset from the DTB, and record in the // respective PCDs. This will also return false if a corrupt DTB is - // encountered. Since we are calling a C function, use the window at the - // beginning of the FD image as a temp stack. + // encountered. // + mov r0, r10 ADRL (r1, PcdGet64 (PcdSystemMemoryBase)) ADRL (r2, PcdGet64 (PcdSystemMemorySize)) - mov sp, r5 bl FindMemnode teq r0, #0 beq .Lout diff --git a/ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf b/ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf index 9e58e56fce..7edf501808 100755 --- a/ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf +++ b/ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf @@ -46,6 +46,7 @@ SerialPortLib ExtractGuidedSectionLib LzmaDecompressLib + PeCoffLib PrePiLib MemoryAllocationLib HobLib @@ -95,6 +96,3 @@ gArmVirtTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress gArmTokenSpaceGuid.PcdFdBaseAddress gArmTokenSpaceGuid.PcdFvBaseAddress - -[BuildOptions] - GCC:*_*_*_DLINK_FLAGS = -Wl,-Bsymbolic,-pie,-T,$(MODULE_DIR)/Scripts/PrePi-PIE.lds diff --git a/ArmVirtPkg/PrePi/PrePi.c b/ArmVirtPkg/PrePi/PrePi.c index 72e35028c5..4f0c3f98ba 100755 --- a/ArmVirtPkg/PrePi/PrePi.c +++ b/ArmVirtPkg/PrePi/PrePi.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -128,3 +129,37 @@ CEntryPoint ( // DXE Core should always load and never return ASSERT (FALSE); } + +VOID +RelocatePeCoffImage ( + IN EFI_PEI_FV_HANDLE FwVolHeader, + IN PE_COFF_LOADER_READ_FILE ImageRead + ) +{ + EFI_PEI_FILE_HANDLE FileHandle; + VOID *SectionData; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + EFI_STATUS Status; + + FileHandle = NULL; + Status = FfsFindNextFile (EFI_FV_FILETYPE_SECURITY_CORE, FwVolHeader, + &FileHandle); + ASSERT_EFI_ERROR (Status); + + Status = FfsFindSectionData (EFI_SECTION_PE32, FileHandle, &SectionData); + if (EFI_ERROR (Status)) { + Status = FfsFindSectionData (EFI_SECTION_TE, FileHandle, &SectionData); + } + ASSERT_EFI_ERROR (Status); + + ZeroMem (&ImageContext, sizeof ImageContext); + + ImageContext.Handle = (EFI_HANDLE)SectionData; + ImageContext.ImageRead = ImageRead; + PeCoffLoaderGetImageInfo (&ImageContext); + + if (ImageContext.ImageAddress != (UINTN)SectionData) { + ImageContext.ImageAddress = (UINTN)SectionData; + PeCoffLoaderRelocateImage (&ImageContext); + } +}