diff --git a/grub-core/kern/ia64/dl.c b/grub-core/kern/ia64/dl.c index ad79eb525..082aebc3a 100644 --- a/grub-core/kern/ia64/dl.c +++ b/grub-core/kern/ia64/dl.c @@ -104,6 +104,9 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, case R_IA64_PCREL64LSB: *(grub_uint64_t *) addr += value - addr; break; + case R_IA64_GPREL64I: + grub_ia64_set_immu64 (addr, value - (grub_addr_t) mod->base); + break; case R_IA64_GPREL22: if ((value - (grub_addr_t) mod->base) & ~MASK20) return grub_error (GRUB_ERR_BAD_MODULE, diff --git a/grub-core/kern/ia64/dl_helper.c b/grub-core/kern/ia64/dl_helper.c index c7e53a679..2436b75fd 100644 --- a/grub-core/kern/ia64/dl_helper.c +++ b/grub-core/kern/ia64/dl_helper.c @@ -30,6 +30,40 @@ #define MASK20 ((1 << 20) - 1) #define MASK3 (~(grub_addr_t) 3) +void +grub_ia64_set_immu64 (grub_addr_t addr, grub_uint64_t val) +{ + /* Copied from binutils. */ + grub_uint64_t *ptr = ((grub_uint64_t *) (addr & MASK3)); + grub_uint64_t t0, t1; + + t0 = grub_le_to_cpu64 (ptr[0]); + t1 = grub_le_to_cpu64 (ptr[1]); + + /* tmpl/s: bits 0.. 5 in t0 + slot 0: bits 5..45 in t0 + slot 1: bits 46..63 in t0, bits 0..22 in t1 + slot 2: bits 23..63 in t1 */ + + /* First, clear the bits that form the 64 bit constant. */ + t0 &= ~(0x3ffffLL << 46); + t1 &= ~(0x7fffffLL + | (( (0x07fLL << 13) | (0x1ffLL << 27) + | (0x01fLL << 22) | (0x001LL << 21) + | (0x001LL << 36)) << 23)); + + t0 |= ((val >> 22) & 0x03ffffLL) << 46; /* 18 lsbs of imm41 */ + t1 |= ((val >> 40) & 0x7fffffLL) << 0; /* 23 msbs of imm41 */ + t1 |= ( (((val >> 0) & 0x07f) << 13) /* imm7b */ + | (((val >> 7) & 0x1ff) << 27) /* imm9d */ + | (((val >> 16) & 0x01f) << 22) /* imm5c */ + | (((val >> 21) & 0x001) << 21) /* ic */ + | (((val >> 63) & 0x001) << 36)) << 23; /* i */ + + ptr[0] = t0; + ptr[1] = t1; +} + void grub_ia64_add_value_to_slot_20b (grub_addr_t addr, grub_uint32_t value) { diff --git a/include/grub/ia64/reloc.h b/include/grub/ia64/reloc.h index 4c02ab2e6..45c8fba27 100644 --- a/include/grub/ia64/reloc.h +++ b/include/grub/ia64/reloc.h @@ -26,6 +26,8 @@ grub_ia64_add_value_to_slot_20b (grub_addr_t addr, grub_uint32_t value); void grub_ia64_add_value_to_slot_21 (grub_addr_t addr, grub_uint32_t value); void +grub_ia64_set_immu64 (grub_addr_t addr, grub_uint64_t value); +void grub_ia64_make_trampoline (struct grub_ia64_trampoline *tr, grub_uint64_t addr); struct grub_ia64_trampoline diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c index 353a9407a..aa20b9a87 100644 --- a/util/grub-mkimagexx.c +++ b/util/grub-mkimagexx.c @@ -920,6 +920,10 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, grub_ia64_add_value_to_slot_21 ((grub_addr_t) target, addend + sym_addr); break; + case R_IA64_GPREL64I: + grub_ia64_set_immu64 ((grub_addr_t) target, + addend + sym_addr); + break; case R_IA64_PCREL64LSB: *target = grub_host_to_target64 (grub_target_to_host64 (*target) + addend + sym_addr @@ -1286,6 +1290,7 @@ translate_relocation_pe (struct translate_context *ctx, case R_IA64_LTOFF22X: case R_IA64_LTOFF22: case R_IA64_GPREL22: + case R_IA64_GPREL64I: case R_IA64_SEGREL64LSB: break; diff --git a/util/grub-module-verifier.c b/util/grub-module-verifier.c index 4234cfdd4..dd72d7833 100644 --- a/util/grub-module-verifier.c +++ b/util/grub-module-verifier.c @@ -60,6 +60,7 @@ struct grub_module_verifier_arch archs[] = { R_IA64_PCREL64LSB, R_IA64_LTOFF22X, R_IA64_LTOFF22, + R_IA64_GPREL64I, R_IA64_LTOFF_FPTR22, R_IA64_LDXMOV, -1