=== modified file 'Makefile.util.def' --- Makefile.util.def 2013-04-12 14:54:54 +0000 +++ Makefile.util.def 2013-05-09 16:38:09 +0000 @@ -150,7 +150,7 @@ common = util/resolve.c; common = grub-core/kern/emu/argp_common.c; - common = grub-core/kern/arm/dl.c; + common = grub-core/kern/arm/dl_helper.c; extra_dist = util/grub-mkimagexx.c; === modified file 'grub-core/Makefile.core.def' --- grub-core/Makefile.core.def 2013-04-12 14:55:38 +0000 +++ grub-core/Makefile.core.def 2013-05-09 14:43:56 +0000 @@ -209,6 +209,7 @@ sparc64_ieee1275 = kern/sparc64/ieee1275/ieee1275.c; arm = kern/arm/dl.c; + arm = kern/arm/dl_helper.c; arm = kern/arm/cache.S; arm = kern/arm/misc.S; === modified file 'grub-core/kern/arm/dl.c' --- grub-core/kern/arm/dl.c 2013-04-12 14:53:58 +0000 +++ grub-core/kern/arm/dl.c 2013-05-09 16:44:58 +0000 @@ -25,272 +25,9 @@ #include #include -#ifdef GRUB_UTIL -# include -#else - -#ifdef DL_DEBUG -static const char *symstrtab; - -/* - * This is a bit of a hack, setting the symstrtab pointer to the last STRTAB - * section in the module (which is where symbol names are in the objects I've - * inspected manually). - */ -static void -set_symstrtab (Elf_Ehdr * e) -{ - int i; - Elf_Shdr *s; - - symstrtab = NULL; - - for (i = 0, s = (Elf_Shdr *) ((grub_uint32_t) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((grub_uint32_t) s + e->e_shentsize)) - if (s->sh_type == SHT_STRTAB) - symstrtab = (void *) ((grub_addr_t) e + s->sh_offset); -} - -static const char * -get_symbolname (Elf_Sym * sym) -{ - const char *symbolname = symstrtab + sym->st_name; - - return (*symbolname ? symbolname : NULL); -} -#endif /* DL_DEBUG */ - -/* - * R_ARM_ABS32 - * - * Simple relocation of 32-bit value (in literal pool) - */ -static grub_err_t -reloc_abs32 (Elf_Word *target, Elf_Addr sym_addr) -{ - Elf_Addr tmp; - - tmp = *target; - tmp += sym_addr; - *target = tmp; -#if 0 //def GRUB_UTIL - grub_util_info (" %s: reloc_abs32 0x%08x => 0x%08x", __FUNCTION__, - (unsigned int) sym_addr, (unsigned int) tmp); -#endif - - return GRUB_ERR_NONE; -} -#endif /* ndef GRUB_UTIL */ - - -/******************************************************************** - * Thumb (T32) relocations: * - * * - * 32-bit Thumb instructions can be 16-bit aligned, and are fetched * - * little-endian, requiring some additional fiddling. * - ********************************************************************/ - -/* - * R_ARM_THM_CALL/THM_JUMP24 - * - * Relocate Thumb (T32) instruction set relative branches: - * B.W, BL and BLX - */ -grub_err_t -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; - grub_uint32_t insword, insmask; - - /* Extract instruction word in alignment-safe manner */ - insword = (*target << 16) | (*(target + 1)); - insmask = 0xf800d000; - - /* B.W/BL or BLX? Affects range and expected target state */ - if (((insword >> 12) & 0xd) == 0xc) - is_blx = 1; - else - is_blx = 0; - - /* If BLX, target symbol must be ARM (target address LSB == 0) */ - if (is_blx && (sym_addr & 1)) - return grub_error (GRUB_ERR_BUG, - N_("Relocation targeting wrong execution state")); - - offset_low = -16777216; - offset_high = is_blx ? 16777212 : 16777214; - - /* Extract bitfields from instruction words */ - sign = (insword >> 26) & 1; - j1 = (insword >> 13) & 1; - j2 = (insword >> 11) & 1; - offset = (sign << 24) | ((~(j1 ^ sign) & 1) << 23) | - ((~(j2 ^ sign) & 1) << 22) | - ((insword & 0x03ff0000) >> 4) | ((insword & 0x000007ff) << 1); - - /* Sign adjust and calculate offset */ - if (offset & (1 << 24)) - offset -= (1 << 25); -#ifdef GRUB_UTIL - grub_util_info (" sym_addr = 0x%08x", sym_addr); -#endif -#ifdef GRUB_UTIL - offset += sym_addr; -#else - offset += sym_addr - (grub_uint32_t) target; -#endif -#ifdef DEBUG - grub_printf(" %s: target=0x%08x, sym_addr=0x%08x, offset=%d\n", - is_blx ? "BLX" : "BL", (unsigned int) target, sym_addr, offset); -#endif - - if ((offset < offset_low) || (offset > offset_high)) - return grub_error (GRUB_ERR_OUT_OF_RANGE, - N_("THM_CALL Relocation out of range.")); - -#ifdef GRUB_UTIL - grub_util_info (" relative destination = 0x%08lx", - (unsigned long)target + offset); -#endif - - /* Reassemble instruction word */ - sign = (offset >> 24) & 1; - j1 = sign ^ (~(offset >> 23) & 1); - j2 = sign ^ (~(offset >> 22) & 1); - insword = (insword & insmask) | - (sign << 26) | - (((offset >> 12) & 0x03ff) << 16) | - (j1 << 13) | (j2 << 11) | ((offset >> 1) & 0x07ff); - - /* Write instruction word back in alignment-safe manner */ - *target = (insword >> 16) & 0xffff; - *(target + 1) = insword & 0xffff; - -#ifdef GRUB_UTIL -#pragma GCC diagnostic ignored "-Wcast-align" - grub_util_info (" *target = 0x%08x", *((unsigned int *)target)); -#endif - - return GRUB_ERR_NONE; -} - -/* - * R_ARM_THM_JUMP19 - * - * Relocate conditional Thumb (T32) B.W - */ -grub_err_t -grub_arm_reloc_thm_jump19 (grub_uint16_t *addr, Elf32_Addr sym_addr) -{ - grub_int32_t offset; - grub_uint32_t insword, insmask; - - /* Extract instruction word in alignment-safe manner */ - insword = (*addr) << 16 | *(addr + 1); - insmask = 0xfbc0d800; - - /* Extract and sign extend offset */ - offset = ((insword >> 26) & 1) << 18 - | ((insword >> 11) & 1) << 17 - | ((insword >> 13) & 1) << 16 - | ((insword >> 16) & 0x3f) << 11 - | (insword & 0x7ff); - offset <<= 1; - if (offset & (1 << 19)) - offset -= (1 << 20); - - /* Adjust and re-truncate offset */ -#ifdef GRUB_UTIL - offset += sym_addr; -#else - offset += sym_addr - (grub_uint32_t) addr; -#endif - if ((offset > 1048574) || (offset < -1048576)) - { - return grub_error - (GRUB_ERR_OUT_OF_RANGE, N_("THM_JUMP19 Relocation out of range.")); - } - - offset >>= 1; - offset &= 0x7ffff; - - /* Reassemble instruction word and write back */ - insword &= insmask; - insword |= ((offset >> 18) & 1) << 26 - | ((offset >> 17) & 1) << 11 - | ((offset >> 16) & 1) << 13 - | ((offset >> 11) & 0x3f) << 16 - | (offset & 0x7ff); - *addr = insword >> 16; - *(addr + 1) = insword & 0xffff; - return GRUB_ERR_NONE; -} - - - -/*********************************************************** - * ARM (A32) relocations: * - * * - * ARM instructions are 32-bit in size and 32-bit aligned. * - ***********************************************************/ - -/* - * R_ARM_JUMP24 - * - * Relocate ARM (A32) B - */ -grub_err_t -grub_arm_reloc_jump24 (grub_uint32_t *addr, Elf32_Addr sym_addr) -{ - grub_uint32_t insword; - grub_int32_t offset; - - insword = *addr; - - offset = (insword & 0x00ffffff) << 2; - if (offset & 0x02000000) - offset -= 0x04000000; -#ifdef GRUB_UTIL - offset += sym_addr; -#else - offset += sym_addr - (grub_uint32_t) addr; -#endif - - insword &= 0xff000000; - insword |= (offset >> 2) & 0x00ffffff; - - *addr = insword; - - return GRUB_ERR_NONE; -} - - - /************************************************* * Runtime dynamic linker with helper functions. * *************************************************/ -#ifndef GRUB_UTIL -/* - * find_segment(): finds a module segment matching sh_info - */ -static grub_dl_segment_t -find_segment (grub_dl_segment_t seg, Elf32_Word sh_info) -{ - for (; seg; seg = seg->next) - if (seg->section == sh_info) - return seg; - - return NULL; -} - - -/* - * do_relocations(): - * Iterate over all relocations in section, calling appropriate functions - * for patching. - */ static grub_err_t do_relocations (Elf_Shdr * relhdr, Elf_Ehdr * e, grub_dl_t mod) { @@ -302,7 +39,9 @@ entnum = relhdr->sh_size / sizeof (Elf_Rel); /* Find the target segment for this relocation section. */ - seg = find_segment (mod->segment, relhdr->sh_info); + for (seg = mod->segment ; seg ; seg = seg->next) + if (seg->section == relhdr->sh_info) + break; if (!seg) return grub_error (GRUB_ERR_EOF, N_("relocation segment not found")); @@ -320,22 +59,16 @@ "reloc offset is out of the segment"); relsym = ELF_R_SYM (rel[i].r_info); reltype = ELF_R_TYPE (rel[i].r_info); - target = (Elf_Word *) ((grub_addr_t) seg->addr + rel[i].r_offset); + target = (void *) ((grub_addr_t) seg->addr + rel[i].r_offset); sym_addr = sym[relsym].st_value; -#ifdef DL_DEBUG - - grub_printf ("%s: 0x%08x -> %s @ 0x%08x\n", __FUNCTION__, - (grub_addr_t) sym_addr, get_symbolname (sym), sym->st_value); -#endif - switch (reltype) { case R_ARM_ABS32: { /* Data will be naturally aligned */ - retval = reloc_abs32 (target, sym_addr); + retval = grub_arm_reloc_abs32 (target, sym_addr); if (retval != GRUB_ERR_NONE) return retval; } @@ -427,10 +160,6 @@ if (!has_symtab (e)) return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table")); -#ifdef DL_DEBUG - set_symstrtab (e); -#endif - #define FIRST_SHDR(x) ((Elf_Shdr *) ((grub_addr_t)(x) + (x)->e_shoff)) #define NEXT_SHDR(x, y) ((Elf_Shdr *) ((grub_addr_t)(y) + (x)->e_shentsize)) @@ -458,7 +187,7 @@ case SHT_RELA: default: { - grub_printf ("unhandled section_type: %d (0x%08x)\n", + grub_dprintf ("dl", "unhandled section_type: %d (0x%08x)\n", s->sh_type, s->sh_type); return GRUB_ERR_NOT_IMPLEMENTED_YET; }; @@ -470,4 +199,3 @@ return GRUB_ERR_NONE; } -#endif /* ndef GRUB_UTIL */ === added file 'grub-core/kern/arm/dl_helper.c' --- grub-core/kern/arm/dl_helper.c 1970-01-01 00:00:00 +0000 +++ grub-core/kern/arm/dl_helper.c 2013-05-09 17:12:32 +0000 @@ -0,0 +1,222 @@ +/* dl.c - arch-dependent part of loadable module support */ +/* + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * R_ARM_ABS32 + * + * Simple relocation of 32-bit value (in literal pool) + */ +grub_err_t +grub_arm_reloc_abs32 (Elf32_Word *target, Elf32_Addr sym_addr) +{ + Elf32_Addr tmp; + + tmp = grub_le_to_cpu32 (*target); + tmp += sym_addr; + *target = grub_cpu_to_le32 (tmp); + grub_dprintf ("dl", " %s: reloc_abs32 0x%08x => 0x%08x", __FUNCTION__, + (unsigned int) sym_addr, (unsigned int) tmp); + + return GRUB_ERR_NONE; +} + +/******************************************************************** + * Thumb (T32) relocations: * + * * + * 32-bit Thumb instructions can be 16-bit aligned, and are fetched * + * little-endian, requiring some additional fiddling. * + ********************************************************************/ + +/* + * R_ARM_THM_CALL/THM_JUMP24 + * + * Relocate Thumb (T32) instruction set relative branches: + * B.W, BL and BLX + */ +grub_err_t +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; + grub_uint32_t insword, insmask; + + /* Extract instruction word in alignment-safe manner */ + insword = (grub_le_to_cpu16 (*target) << 16) + | (grub_le_to_cpu16(*(target + 1))); + insmask = 0xf800d000; + + /* B.W/BL or BLX? Affects range and expected target state */ + if (((insword >> 12) & 0xd) == 0xc) + is_blx = 1; + else + is_blx = 0; + + /* If BLX, target symbol must be ARM (target address LSB == 0) */ + if (is_blx && (sym_addr & 1)) + return grub_error (GRUB_ERR_BAD_MODULE, + N_("Relocation targeting wrong execution state")); + + offset_low = -16777216; + offset_high = is_blx ? 16777212 : 16777214; + + /* Extract bitfields from instruction words */ + sign = (insword >> 26) & 1; + j1 = (insword >> 13) & 1; + j2 = (insword >> 11) & 1; + offset = (sign << 24) | ((~(j1 ^ sign) & 1) << 23) | + ((~(j2 ^ sign) & 1) << 22) | + ((insword & 0x03ff0000) >> 4) | ((insword & 0x000007ff) << 1); + + /* Sign adjust and calculate offset */ + if (offset & (1 << 24)) + offset -= (1 << 25); + + grub_dprintf ("dl", " sym_addr = 0x%08x", sym_addr); + + offset += sym_addr; +#ifndef GRUB_UTIL + offset -= (grub_uint32_t) target; +#endif + + grub_dprintf("dl", " %s: target=0x%08x, sym_addr=0x%08x, offset=%d\n", + is_blx ? "BLX" : "BL", (unsigned int) target, sym_addr, offset); + + if ((offset < offset_low) || (offset > offset_high)) + return grub_error (GRUB_ERR_BAD_MODULE, + N_("THM_CALL Relocation out of range.")); + + grub_dprintf ("dl", " relative destination = 0x%08lx", + (unsigned long)target + offset); + + /* Reassemble instruction word */ + sign = (offset >> 24) & 1; + j1 = sign ^ (~(offset >> 23) & 1); + j2 = sign ^ (~(offset >> 22) & 1); + insword = (insword & insmask) | + (sign << 26) | + (((offset >> 12) & 0x03ff) << 16) | + (j1 << 13) | (j2 << 11) | ((offset >> 1) & 0x07ff); + + /* Write instruction word back in alignment-safe manner */ + *target = grub_cpu_to_le16 ((insword >> 16) & 0xffff); + *(target + 1) = grub_cpu_to_le16 (insword & 0xffff); + + grub_dprintf ("dl", " *insword = 0x%08x", insword); + + return GRUB_ERR_NONE; +} + +/* + * R_ARM_THM_JUMP19 + * + * Relocate conditional Thumb (T32) B.W + */ +grub_err_t +grub_arm_reloc_thm_jump19 (grub_uint16_t *target, Elf32_Addr sym_addr) +{ + grub_int32_t offset; + grub_uint32_t insword, insmask; + + /* Extract instruction word in alignment-safe manner */ + insword = grub_le_to_cpu16 ((*target)) << 16 + | grub_le_to_cpu16 (*(target + 1)); + insmask = 0xfbc0d000; + + /* Extract and sign extend offset */ + offset = ((insword >> 26) & 1) << 19 + | ((insword >> 11) & 1) << 18 + | ((insword >> 13) & 1) << 17 + | ((insword >> 16) & 0x3f) << 11 + | (insword & 0x7ff); + offset <<= 1; + if (offset & (1 << 20)) + offset -= (1 << 21); + + /* Adjust and re-truncate offset */ + offset += sym_addr; +#ifndef GRUB_UTIL + offset -= (grub_uint32_t) target; +#endif + if ((offset > 1048574) || (offset < -1048576)) + return grub_error (GRUB_ERR_BAD_MODULE, + N_("THM_JUMP19 Relocation out of range.")); + + offset >>= 1; + offset &= 0xfffff; + + /* Reassemble instruction word and write back */ + insword &= insmask; + insword |= ((offset >> 19) & 1) << 26 + | ((offset >> 18) & 1) << 11 + | ((offset >> 17) & 1) << 13 + | ((offset >> 11) & 0x3f) << 16 + | (offset & 0x7ff); + *target = grub_cpu_to_le16 (insword >> 16); + *(target + 1) = grub_cpu_to_le16 (insword & 0xffff); + return GRUB_ERR_NONE; +} + + + +/*********************************************************** + * ARM (A32) relocations: * + * * + * ARM instructions are 32-bit in size and 32-bit aligned. * + ***********************************************************/ + +/* + * R_ARM_JUMP24 + * + * Relocate ARM (A32) B + */ +grub_err_t +grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr sym_addr) +{ + grub_uint32_t insword; + grub_int32_t offset; + + if (sym_addr & 1) + return grub_error (GRUB_ERR_BAD_MODULE, + N_("Relocation targeting wrong execution state")); + + insword = grub_le_to_cpu32 (*target); + + offset = (insword & 0x00ffffff) << 2; + if (offset & 0x02000000) + offset -= 0x04000000; + offset += sym_addr; +#ifdef GRUB_UTIL + offset -= (grub_uint32_t) target; +#endif + + insword &= 0xff000000; + insword |= (offset >> 2) & 0x00ffffff; + + *target = grub_cpu_to_le32 (insword); + + return GRUB_ERR_NONE; +} === modified file 'include/grub/arm/reloc.h' --- include/grub/arm/reloc.h 2013-04-12 14:53:58 +0000 +++ include/grub/arm/reloc.h 2013-05-09 14:48:08 +0000 @@ -19,6 +19,7 @@ #ifndef GRUB_ARM_RELOC_H #define GRUB_ARM_RELOC_H 1 +grub_err_t grub_arm_reloc_abs32 (grub_uint32_t *addr, Elf32_Addr sym_addr); 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); === modified file 'util/grub-install.in' --- util/grub-install.in 2013-04-12 14:46:51 +0000 +++ util/grub-install.in 2013-05-09 15:17:30 +0000 @@ -803,7 +803,7 @@ fi # Try to make this image bootable using the EFI Boot Manager, if available. - efibootmgr="`which efibootmgr`" + efibootmgr="`which efibootmgr`" || true if test "$removable" = no && test -n "$efi_distributor" && \ test -n "$efibootmgr"; then # On Linux, we need the efivars kernel modules. === modified file 'util/grub-mkimagexx.c' --- util/grub-mkimagexx.c 2013-04-12 14:53:58 +0000 +++ util/grub-mkimagexx.c 2013-05-09 16:34:59 +0000 @@ -542,7 +542,6 @@ grub_util_info (" ABS32:\toffset=%d\t(0x%08x)", (int) sym_addr, (int) sym_addr); /* Data will be naturally aligned */ - // sym_addr -= offset; sym_addr += 0x400; *target = grub_host_to_target32 (grub_target_to_host32 (*target) + sym_addr); } @@ -566,9 +565,9 @@ grub_util_info (" THM_JUMP19:\toffset=%d\t(0x%08x)", sym_addr, sym_addr); sym_addr -= offset; + /* Thumb instructions can be 16-bit aligned */ - err = grub_arm_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); } @@ -825,15 +824,10 @@ break; /* Create fixup entry for PE/COFF loader */ case R_ARM_ABS32: - { + { Elf_Addr addr; addr = section_address + offset; -#if 0 - grub_util_info (" %s: add_fixup: 0x%08x : 0x%08x", - __FUNCTION__, (unsigned int) addr, - (unsigned int) current_address); -#endif current_address = SUFFIX (add_fixup_entry) (&lst, GRUB_PE32_REL_BASED_HIGHLOW, @@ -842,7 +836,7 @@ } break; default: - grub_util_error (_("relocation 0x%x is not implemented yet2"), ELF_R_TYPE (info)); + grub_util_error (_("fixup for relocation 0x%x not implemented"), ELF_R_TYPE (info)); break; } break;