*abs_place = (grub_uint64_t) sym_addr;
}
break;
+ case R_AARCH64_ADD_ABS_LO12_NC:
+ grub_arm64_set_abs_lo12 (place, sym_addr);
+ break;
+ case R_AARCH64_LDST64_ABS_LO12_NC:
+ grub_arm64_set_abs_lo12_ldst64 (place, sym_addr);
+ break;
case R_AARCH64_CALL26:
case R_AARCH64_JUMP26:
{
grub_arm64_set_xxxx26_offset (place, offset);
}
break;
+ case R_AARCH64_ADR_PREL_PG_HI21:
+ {
+ grub_int64_t offset = (sym_addr & ~0xfffULL) - (((grub_uint64_t) place) & ~0xfffULL);
+
+ if (!grub_arm64_check_hi21_signed (offset))
+ return grub_error (GRUB_ERR_BAD_MODULE,
+ "HI21 out of range");
+
+ grub_arm64_set_hi21 (place, offset);
+ }
+ break;
+
default:
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
N_("relocation 0x%x is not implemented yet"),
*place &= insmask;
*place |= grub_cpu_to_le32 (offset >> 2) & ~insmask;
}
+
+int
+grub_arm64_check_hi21_signed (grub_int64_t offset)
+{
+ if (offset != (grub_int64_t)(grub_int32_t)offset)
+ return 0;
+ return 1;
+}
+
+void
+grub_arm64_set_hi21 (grub_uint32_t *place, grub_int64_t offset)
+{
+ const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0x9f00001f);
+ grub_uint32_t val;
+
+ offset >>= 12;
+
+ val = ((offset & 3) << 29) | (((offset >> 2) & 0x7ffff) << 5);
+
+ *place &= insmask;
+ *place |= grub_cpu_to_le32 (val) & ~insmask;
+}
+
+void
+grub_arm64_set_abs_lo12 (grub_uint32_t *place, grub_int64_t target)
+{
+ const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xffc003ff);
+
+ *place &= insmask;
+ *place |= grub_cpu_to_le32 (target << 10) & ~insmask;
+}
+
+void
+grub_arm64_set_abs_lo12_ldst64 (grub_uint32_t *place, grub_int64_t target)
+{
+ const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfff803ff);
+
+ *place &= insmask;
+ *place |= grub_cpu_to_le32 (target << 7) & ~insmask;
+}
int grub_arm_64_check_xxxx26_offset (grub_int64_t offset);
void
grub_arm64_set_xxxx26_offset (grub_uint32_t *place, grub_int64_t offset);
+int
+grub_arm64_check_hi21_signed (grub_int64_t offset);
+void
+grub_arm64_set_hi21 (grub_uint32_t *place, grub_int64_t offset);
+void
+grub_arm64_set_abs_lo12 (grub_uint32_t *place, grub_int64_t target);
+void
+grub_arm64_set_abs_lo12_ldst64 (grub_uint32_t *place, grub_int64_t target);
#endif
#define R_AARCH64_NONE 0 /* No relocation. */
#define R_AARCH64_ABS64 257 /* Direct 64 bit. */
#define R_AARCH64_ABS32 258 /* Direct 32 bit. */
+#define R_AARCH64_ADR_PREL_PG_HI21 275
+#define R_AARCH64_ADD_ABS_LO12_NC 277
+#define R_AARCH64_LDST64_ABS_LO12_NC 286
#define R_AARCH64_JUMP26 282 /* 26-bit relative. */
#define R_AARCH64_CALL26 283 /* 26-bit relative. */
#define R_AARCH64_COPY 1024 /* Copy symbol at runtime. */
*target = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr);
}
break;
+ case R_AARCH64_ADD_ABS_LO12_NC:
+ grub_arm64_set_abs_lo12 ((grub_uint32_t *) target,
+ sym_addr);
+ break;
+ case R_AARCH64_LDST64_ABS_LO12_NC:
+ grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t *) target,
+ sym_addr);
+ break;
case R_AARCH64_JUMP26:
case R_AARCH64_CALL26:
{
sym_addr);
}
break;
+ case R_AARCH64_ADR_PREL_PG_HI21:
+ {
+ sym_addr &= ~0xfffULL;
+ sym_addr -= (offset + SUFFIX (entry_point)) & ~0xfffULL;
+ if (!grub_arm64_check_hi21_signed (sym_addr))
+ grub_util_error ("%s", "CALL26 Relocation out of range");
+
+ grub_arm64_set_hi21((grub_uint32_t *)target,
+ sym_addr);
+ }
+ break;
default:
grub_util_error (_("relocation 0x%x is not implemented yet"),
(unsigned int) ELF_R_TYPE (info));
case R_AARCH64_CALL26:
case R_AARCH64_JUMP26:
break;
+ /* Page-relative relocations do not require fixup entries. */
+ case R_AARCH64_ADR_PREL_PG_HI21:
+ /* We page-align the whole kernel, so no need
+ for fixup entries.
+ */
+ case R_AARCH64_ADD_ABS_LO12_NC:
+ case R_AARCH64_LDST64_ABS_LO12_NC:
+ break;
+
default:
grub_util_error (_("relocation 0x%x is not implemented yet"),
(unsigned int) ELF_R_TYPE (info));
Elf_Shdr *s;
*all_align = 1;
+ /* Page-aligning simplifies relocation handling. */
+ if (image_target->elf_target == EM_AARCH64)
+ *all_align = 4096;
section_addresses = xmalloc (sizeof (*section_addresses) * num_sections);
memset (section_addresses, 0, sizeof (*section_addresses) * num_sections);
R_AARCH64_CALL26,
R_AARCH64_JUMP26,
-1
- } },
+ }, (int[]){
+ R_AARCH64_ADR_PREL_PG_HI21,
+ R_AARCH64_ADD_ABS_LO12_NC,
+ R_AARCH64_LDST64_ABS_LO12_NC,
+ -1
+ }
+ },
};