diff --git a/GRUB2/MOD_SRC/grub-2.04/configure.ac b/GRUB2/MOD_SRC/grub-2.04/configure.ac index 9ad929e0..e377a96c 100644 --- a/GRUB2/MOD_SRC/grub-2.04/configure.ac +++ b/GRUB2/MOD_SRC/grub-2.04/configure.ac @@ -833,6 +833,21 @@ if ( test "x$target_cpu" = xi386 || test "x$target_cpu" = xx86_64 ) && test "x$p TARGET_CFLAGS="$TARGET_CFLAGS -mno-mmx -mno-sse -mno-sse2 -mno-sse3 -mno-3dnow" fi +if test "x$target_cpu" = xloongarch64; then + AC_CACHE_CHECK([whether _mno_explicit_relocs works], [grub_cv_cc_mno_explicit_relocs], [ + CFLAGS="$TARGET_CFLAGS -mno-explicit-relocs -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_mno_explicit_relocs=yes], + [grub_cv_cc_mno_explicit_relocs=no]) + ]) + if test "x$grub_cv_cc_mno_explicit_relocs" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -mno-explicit-relocs -fno-plt" + TARGET_CCASFLAGS="$TARGET_CCASFLAGS -mno-explicit-relocs -fno-plt" + fi + TARGET_CFLAGS="$TARGET_CFLAGS -Wa,-mla-global-with-abs" + TARGET_CCASFLAGS="$TARGET_CCASFLAGS -Wa,-mla-global-with-abs" +fi + # GRUB doesn't use float or doubles at all. Yet some toolchains may decide # that floats are a good fit to run instead of what's written in the code. # Given that floating point unit is disabled (if present to begin with) diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/loongarch64/dl.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/loongarch64/dl.c index effb4c7b..43080e72 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/loongarch64/dl.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/loongarch64/dl.c @@ -58,7 +58,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, rel = (Elf_Rel *) ((char *) rel + s->sh_entsize)) { Elf_Sym *sym; - grub_uint64_t *place; + void *place; grub_uint64_t sym_addr; if (rel->r_offset >= seg->size) @@ -72,12 +72,19 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, if (s->sh_type == SHT_RELA) sym_addr += ((Elf_Rela *) rel)->r_addend; - place = (grub_uint64_t *) ((grub_addr_t) seg->addr + rel->r_offset); + place = (void *) ((grub_addr_t) seg->addr + rel->r_offset); switch (ELF_R_TYPE (rel->r_info)) { case R_LARCH_64: - *place = sym_addr; + { + grub_uint64_t *abs_place = place; + + grub_dprintf ("dl", "reloc_abs64 %p => 0x%016llx, %p\n", + place, (unsigned long long) sym_addr, abs_place); + + *abs_place += (grub_uint64_t) sym_addr; + } break; case R_LARCH_MARK_LA: break; @@ -85,6 +92,47 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, case R_LARCH_SOP_PUSH_PLT_PCREL: grub_loongarch64_sop_push (&stack, sym_addr - (grub_uint64_t)place); break; + case R_LARCH_B26: + { + grub_uint32_t *abs_place = place; + grub_ssize_t off = sym_addr - (grub_addr_t) place; + + grub_loongarch64_b26 (abs_place, off); + } + break; + case R_LARCH_ABS_HI20: + { + grub_uint32_t *abs_place = place; + grub_loongarch64_xxx_hi20 (abs_place, sym_addr); + } + break; + case R_LARCH_ABS64_LO20: + { + grub_uint32_t *abs_place = place; + grub_loongarch64_xxx64_lo20 (abs_place, sym_addr); + } + break; + case R_LARCH_ABS64_HI12: + { + grub_uint32_t *abs_place = place; + grub_loongarch64_xxx64_hi12 (abs_place, sym_addr); + } + break; + case R_LARCH_PCALA_HI20: + { + grub_uint32_t *abs_place = place; + grub_int32_t off = (((sym_addr + 0x800) & ~0xfffULL) - ((grub_addr_t)place & ~0xfffULL)); + + grub_loongarch64_xxx_hi20 (abs_place, off); + } + break; + case R_LARCH_ABS_LO12: + case R_LARCH_PCALA_LO12: + { + grub_uint32_t *abs_place = place; + grub_loongarch64_xxx_lo12 (abs_place, sym_addr); + } + break; GRUB_LOONGARCH64_RELOCATION (&stack, place, sym_addr) default: { diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/loongarch64/dl_helper.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/loongarch64/dl_helper.c index bfe785e6..e8ec1219 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/loongarch64/dl_helper.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/loongarch64/dl_helper.c @@ -199,3 +199,62 @@ grub_loongarch64_sop_32_s_0_10_10_16_s2 (grub_loongarch64_stack_t stack, *place =(*place) | (((a >> 2) & 0xffff) << 10); *place =(*place) | ((a >> 18) & 0x3ff); } + +void grub_loongarch64_b26 (grub_uint32_t *place, grub_int64_t offset) +{ + grub_uint32_t val; + const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfc000000); + + grub_dprintf ("dl", " reloc_xxxx64 %p %c= 0x%llx\n", + place, offset > 0 ? '+' : '-', + offset < 0 ? (long long) -(unsigned long long) offset : offset); + + val = ((offset >> 18) & 0x3ff) | (((offset >> 2) & 0xffff) << 10); + + *place &= insmask; + *place |= grub_cpu_to_le32 (val) & ~insmask; +} + +void grub_loongarch64_xxx_hi20 (grub_uint32_t *place, grub_int64_t offset) +{ + const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfe00001f); + grub_uint32_t val; + + offset >>= 12; + val = ((offset & 0xfffff) << 5); + + *place &= insmask; + *place |= grub_cpu_to_le32 (val) & ~insmask; +} + +void grub_loongarch64_xxx_lo12 (grub_uint32_t *place, grub_int64_t offset) +{ + const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xffc003ff); + + *place &= insmask; + *place |= grub_cpu_to_le32 (offset << 10) & ~insmask; +} + +void grub_loongarch64_xxx64_hi12 (grub_uint32_t *place, grub_int64_t offset) +{ + const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xffc003ff); + grub_uint32_t val; + + offset >>= 52; + val = ((offset & 0xfff) << 10); + + *place &= insmask; + *place |= grub_cpu_to_le32 (val) & ~insmask; +} + +void grub_loongarch64_xxx64_lo20 (grub_uint32_t *place, grub_int64_t offset) +{ + const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfe00001f); + grub_uint32_t val; + + offset >>= 32; + val = ((offset & 0xfffff) << 5); + + *place &= insmask; + *place |= grub_cpu_to_le32 (val) & ~insmask; +} diff --git a/GRUB2/MOD_SRC/grub-2.04/include/grub/elf.h b/GRUB2/MOD_SRC/grub-2.04/include/grub/elf.h index 134c5d22..0fb2112a 100644 --- a/GRUB2/MOD_SRC/grub-2.04/include/grub/elf.h +++ b/GRUB2/MOD_SRC/grub-2.04/include/grub/elf.h @@ -2553,6 +2553,13 @@ typedef Elf32_Addr Elf32_Conflict; #define R_LARCH_SOP_POP_32_S_5_20 43 #define R_LARCH_SOP_POP_32_S_0_5_10_16_S2 44 #define R_LARCH_SOP_POP_32_S_0_10_10_16_S2 45 +#define R_LARCH_B26 66 +#define R_LARCH_ABS_HI20 67 +#define R_LARCH_ABS_LO12 68 +#define R_LARCH_ABS64_LO20 69 +#define R_LARCH_ABS64_HI12 70 +#define R_LARCH_PCALA_HI20 71 +#define R_LARCH_PCALA_LO12 72 #ifdef GRUB_TARGET_WORDSIZE #if GRUB_TARGET_WORDSIZE == 32 diff --git a/GRUB2/MOD_SRC/grub-2.04/include/grub/loongarch64/reloc.h b/GRUB2/MOD_SRC/grub-2.04/include/grub/loongarch64/reloc.h index 5282b830..dec7a6b3 100644 --- a/GRUB2/MOD_SRC/grub-2.04/include/grub/loongarch64/reloc.h +++ b/GRUB2/MOD_SRC/grub-2.04/include/grub/loongarch64/reloc.h @@ -57,6 +57,12 @@ void grub_loongarch64_sop_32_s_0_5_10_16_s2 (grub_loongarch64_stack_t stack, void grub_loongarch64_sop_32_s_0_10_10_16_s2 (grub_loongarch64_stack_t stack, grub_uint64_t *place); +void grub_loongarch64_b26 (grub_uint32_t *place, grub_int64_t offset); +void grub_loongarch64_xxx_hi20 (grub_uint32_t *place, grub_int64_t offset); +void grub_loongarch64_xxx_lo12 (grub_uint32_t *place, grub_int64_t offset); +void grub_loongarch64_xxx64_hi12 (grub_uint32_t *place, grub_int64_t offset); +void grub_loongarch64_xxx64_lo20 (grub_uint32_t *place, grub_int64_t offset); + #define GRUB_LOONGARCH64_RELOCATION(STACK, PLACE, OFFSET) \ case R_LARCH_SOP_PUSH_ABSOLUTE: \ grub_loongarch64_sop_push (STACK, OFFSET); \ diff --git a/GRUB2/MOD_SRC/grub-2.04/util/grub-mkimagexx.c b/GRUB2/MOD_SRC/grub-2.04/util/grub-mkimagexx.c index c984332b..2d5ebdd7 100644 --- a/GRUB2/MOD_SRC/grub-2.04/util/grub-mkimagexx.c +++ b/GRUB2/MOD_SRC/grub-2.04/util/grub-mkimagexx.c @@ -1192,11 +1192,20 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, } case EM_LOONGARCH: { + grub_int64_t pc; + + grub_uint32_t *t32 = (grub_uint32_t *) target; sym_addr += addend; + + pc = offset + target_section_addr + image_target->vaddr_offset; + switch (ELF_R_TYPE (info)) { case R_LARCH_64: - *target = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr); + { + grub_uint64_t *t64 = (grub_uint64_t *) target; + *t64 = grub_host_to_target64 (grub_target_to_host64 (*t64) + sym_addr); + } break; case R_LARCH_MARK_LA: break; @@ -1207,6 +1216,37 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, +offset +image_target->vaddr_offset)); break; + case R_LARCH_B26: + { + grub_int64_t off; + + off = sym_addr - target_section_addr - offset - image_target->vaddr_offset; + + grub_loongarch64_b26 (t32, off); + } + break; + case R_LARCH_ABS_HI20: + grub_loongarch64_xxx_hi20 (t32, sym_addr); + break; + case R_LARCH_ABS64_LO20: + grub_loongarch64_xxx64_lo20 (t32, sym_addr); + break; + case R_LARCH_ABS64_HI12: + grub_loongarch64_xxx64_hi12 (t32, sym_addr); + break; + case R_LARCH_PCALA_HI20: + { + grub_int32_t hi20; + + hi20 = (((sym_addr + 0x800) & ~0xfffULL) - (pc & ~0xfffULL)); + + grub_loongarch64_xxx_hi20 (t32, hi20); + } + break; + case R_LARCH_ABS_LO12: + case R_LARCH_PCALA_LO12: + grub_loongarch64_xxx_lo12 (t32, sym_addr); + break; GRUB_LOONGARCH64_RELOCATION (&stack, target, sym_addr) default: grub_util_error (_("relocation 0x%x is not implemented yet"), @@ -1801,6 +1841,13 @@ translate_relocation_pe (struct translate_context *ctx, case R_LARCH_SOP_POP_32_S_5_20: case R_LARCH_SOP_POP_32_S_0_5_10_16_S2: case R_LARCH_SOP_POP_32_S_0_10_10_16_S2: + case R_LARCH_B26: + case R_LARCH_ABS_HI20: + case R_LARCH_ABS_LO12: + case R_LARCH_ABS64_LO20: + case R_LARCH_ABS64_HI12: + case R_LARCH_PCALA_HI20: + case R_LARCH_PCALA_LO12: grub_util_info (" %s: not adding fixup: 0x%08x : 0x%08x", __FUNCTION__, (unsigned int) addr, diff --git a/GRUB2/MOD_SRC/grub-2.04/util/grub-module-verifier.c b/GRUB2/MOD_SRC/grub-2.04/util/grub-module-verifier.c index 31d0d409..c9eb4e31 100644 --- a/GRUB2/MOD_SRC/grub-2.04/util/grub-module-verifier.c +++ b/GRUB2/MOD_SRC/grub-2.04/util/grub-module-verifier.c @@ -140,6 +140,13 @@ struct grub_module_verifier_arch archs[] = { R_LARCH_SOP_POP_32_S_5_20, R_LARCH_SOP_POP_32_S_0_5_10_16_S2, R_LARCH_SOP_POP_32_S_0_10_10_16_S2, + R_LARCH_B26, + R_LARCH_ABS_HI20, + R_LARCH_ABS_LO12, + R_LARCH_ABS64_LO20, + R_LARCH_ABS64_HI12, + R_LARCH_PCALA_HI20, + R_LARCH_PCALA_LO12, -1 }, (int[]){ -1