#include <grub/err.h>
#include <grub/mm.h>
#include <grub/i18n.h>
+#include <grub/arm/reloc.h>
#ifdef GRUB_UTIL
# include <grub/util/misc.h>
#else
-# if !defined(__thumb2__)
-# error "Relocations not implemented for A32 ("ARM") instruction set yet!"
-# endif
-
-grub_err_t reloc_jump24 (grub_uint32_t *addr, Elf32_Addr sym_addr);
-grub_err_t reloc_thm_call (grub_uint16_t *addr, Elf32_Addr sym_addr);
-grub_err_t reloc_thm_jump19 (grub_uint16_t *addr, Elf32_Addr sym_addr);
#ifdef DL_DEBUG
static const char *symstrtab;
* B.W, BL and BLX
*/
grub_err_t
-reloc_thm_call (grub_uint16_t *target, Elf32_Addr sym_addr)
+grub_arm_reloc_thm_call (grub_uint16_t *target, Elf32_Addr sym_addr)
{
grub_int32_t offset, offset_low, offset_high;
grub_uint32_t sign, j1, j2, is_blx;
/* If BLX, target symbol must be ARM (target address LSB == 0) */
if (is_blx && (sym_addr & 1))
- {
-#ifndef GRUB_UTIL
- return grub_error
- (GRUB_ERR_BUG, N_("Relocation targeting wrong execution state"));
-#else
- grub_util_error ("Relocation targeting wrong execution state");
-#endif
- }
+ return grub_error (GRUB_ERR_BUG,
+ N_("Relocation targeting wrong execution state"));
offset_low = -16777216;
offset_high = is_blx ? 16777212 : 16777214;
#endif
if ((offset < offset_low) || (offset > offset_high))
- {
-#ifdef GRUB_UTIL
- grub_util_error ("Relocation out of range");
-#else
- return grub_error
- (GRUB_ERR_OUT_OF_RANGE, N_("THM_CALL Relocation out of range."));
-#endif
- }
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
+ N_("THM_CALL Relocation out of range."));
#ifdef GRUB_UTIL
- grub_util_info (" relative destination = 0x%08x",
- (unsigned int)target + offset);
+ grub_util_info (" relative destination = 0x%08lx",
+ (unsigned long)target + offset);
#endif
/* Reassemble instruction word */
* Relocate conditional Thumb (T32) B<c>.W
*/
grub_err_t
-reloc_thm_jump19 (grub_uint16_t *addr, Elf32_Addr sym_addr)
+grub_arm_reloc_thm_jump19 (grub_uint16_t *addr, Elf32_Addr sym_addr)
{
grub_int32_t offset;
grub_uint32_t insword, insmask;
* Relocate ARM (A32) B
*/
grub_err_t
-reloc_jump24 (grub_uint32_t *addr, Elf32_Addr sym_addr)
+grub_arm_reloc_jump24 (grub_uint32_t *addr, Elf32_Addr sym_addr)
{
grub_uint32_t insword;
grub_int32_t offset;
return retval;
}
break;
+ case R_ARM_CALL:
case R_ARM_JUMP24:
{
- retval = reloc_jump24 (target, sym_addr);
+ retval = grub_arm_reloc_jump24 (target, sym_addr);
if (retval != GRUB_ERR_NONE)
return retval;
}
case R_ARM_THM_JUMP24:
{
/* Thumb instructions can be 16-bit aligned */
- retval = reloc_thm_call ((grub_uint16_t *) target, sym_addr);
+ retval = grub_arm_reloc_thm_call ((grub_uint16_t *) target, sym_addr);
if (retval != GRUB_ERR_NONE)
return retval;
}
case R_ARM_THM_JUMP19:
{
/* Thumb instructions can be 16-bit aligned */
- retval = reloc_thm_jump19 ((grub_uint16_t *) target, sym_addr);
+ retval = grub_arm_reloc_thm_jump19 ((grub_uint16_t *) target, sym_addr);
if (retval != GRUB_ERR_NONE)
return retval;
}
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_ARM_RELOC_H
+#define GRUB_ARM_RELOC_H 1
+
+grub_err_t grub_arm_reloc_jump24 (grub_uint32_t *addr, Elf32_Addr sym_addr);
+grub_err_t grub_arm_reloc_thm_call (grub_uint16_t *addr, Elf32_Addr sym_addr);
+grub_err_t grub_arm_reloc_thm_jump19 (grub_uint16_t *addr, Elf32_Addr sym_addr);
+
+#endif
static Elf_Addr SUFFIX (entry_point);
-grub_err_t reloc_thm_call (grub_uint16_t *addr, Elf32_Addr sym_addr);
-grub_err_t reloc_thm_jump19 (grub_uint16_t *addr, Elf32_Addr sym_addr);
-
/* Relocate symbols; note that this function overwrites the symbol table.
Return the address of a start symbol. */
static Elf_Addr
case R_ARM_THM_CALL:
case R_ARM_THM_JUMP24:
{
- grub_util_info (" THM_JUMP24:\ttarget=0x%08x\toffset=(0x%08x)", (unsigned int) target, sym_addr);
+ grub_err_t err;
+ grub_util_info (" THM_JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)", (unsigned long) target, sym_addr);
sym_addr -= offset;
/* Thumb instructions can be 16-bit aligned */
- reloc_thm_call ((grub_uint16_t *) target, sym_addr);
+ err = grub_arm_reloc_thm_call ((grub_uint16_t *) target,
+ sym_addr);
+ if (err)
+ grub_util_error ("%s", grub_errmsg);
}
break;
case R_ARM_THM_JUMP19:
{
+ grub_err_t err;
grub_util_info (" THM_JUMP19:\toffset=%d\t(0x%08x)",
sym_addr, sym_addr);
sym_addr -= offset;
/* Thumb instructions can be 16-bit aligned */
- reloc_thm_jump19 ((grub_uint16_t *) target, sym_addr);
+ err = grub_arm_reloc_thm_jump19 ((grub_uint16_t *) target,
+ sym_addr);
+ if (err)
+ grub_util_error ("%s", grub_errmsg);
}
break;
default: