From patchwork Thu May 9 18:08:54 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Leif Lindholm X-Patchwork-Id: 16809 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-qe0-f72.google.com (mail-qe0-f72.google.com [209.85.128.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 82C9F238F7 for ; Thu, 9 May 2013 18:08:49 +0000 (UTC) Received: by mail-qe0-f72.google.com with SMTP id 1sf4237894qee.3 for ; Thu, 09 May 2013 11:08:25 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:x-beenthere:x-received:received-spf:x-received :x-forwarded-to:x-forwarded-for:delivered-to:x-received:received-spf :x-received:date:from:to:cc:subject:message-id:references :mime-version:in-reply-to:user-agent:x-gm-message-state :x-original-sender:x-original-authentication-results:precedence :mailing-list:list-id:x-google-group-id:list-post:list-help :list-archive:list-unsubscribe:content-type:content-disposition :content-transfer-encoding; bh=0mP0Sy86cQSRui0l0O1v/c9ICAv5nMk/nUDC4lEvrNg=; b=lsFcWyPQmGldxIbLBsH7zBqbvdNski3BQY9545axdCjBNQ8GXqjGVnA8BFgxywqtGQ XmKnu+K+lzQTLxqpmn9HWviQAn2vfV/OEekyTdK/0URw6DbIatcwhPSLOywGNNSeapJD +Aloa1nQPKLsesoYKJNUrntT/rHJJnKm2GXUZnHAVQc21Ap4Jzp5+l/zbiDWkP45zg+X m6BnTKBUJv36gynbZA7EoVF53/t2OYNNuhC/of1NwodhIhTUUM/i7JWSJVAp1V07yGJu mN4Q2ABLvQgVckgSsuMKck1JDT58Do2Q/HfX+jHA9EFu1RVDisL08+x+g0vC0Qfh/9CN uejw== X-Received: by 10.224.130.195 with SMTP id u3mr10311862qas.1.1368122905407; Thu, 09 May 2013 11:08:25 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.18.168 with SMTP id x8ls1586536qed.75.gmail; Thu, 09 May 2013 11:08:25 -0700 (PDT) X-Received: by 10.220.104.68 with SMTP id n4mr8727054vco.37.1368122905093; Thu, 09 May 2013 11:08:25 -0700 (PDT) Received: from mail-ve0-x22a.google.com (mail-ve0-x22a.google.com [2607:f8b0:400c:c01::22a]) by mx.google.com with ESMTPS id ir6si2101443vdb.0.2013.05.09.11.08.25 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 09 May 2013 11:08:25 -0700 (PDT) Received-SPF: neutral (google.com: 2607:f8b0:400c:c01::22a is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=2607:f8b0:400c:c01::22a; Received: by mail-ve0-f170.google.com with SMTP id 15so3133777vea.15 for ; Thu, 09 May 2013 11:08:25 -0700 (PDT) X-Received: by 10.220.82.68 with SMTP id a4mr8579370vcl.49.1368122904947; Thu, 09 May 2013 11:08:24 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.58.170.105 with SMTP id al9csp6125vec; Thu, 9 May 2013 11:08:24 -0700 (PDT) X-Received: by 10.14.100.1 with SMTP id y1mr32006605eef.9.1368122903249; Thu, 09 May 2013 11:08:23 -0700 (PDT) Received: from mail-ea0-x22e.google.com (mail-ea0-x22e.google.com [2a00:1450:4013:c01::22e]) by mx.google.com with ESMTPS id i3si5808695eev.173.2013.05.09.11.08.22 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 09 May 2013 11:08:23 -0700 (PDT) Received-SPF: neutral (google.com: 2a00:1450:4013:c01::22e is neither permitted nor denied by best guess record for domain of leif.lindholm@linaro.org) client-ip=2a00:1450:4013:c01::22e; Received: by mail-ea0-f174.google.com with SMTP id z7so703667eaf.19 for ; Thu, 09 May 2013 11:08:22 -0700 (PDT) X-Received: by 10.15.24.72 with SMTP id i48mr10743637eeu.37.1368122902720; Thu, 09 May 2013 11:08:22 -0700 (PDT) Received: from rocoto.smurfnet.nu ([2001:4b98:dc0:41:216:3eff:fea7:75f3]) by mx.google.com with ESMTPSA id n7sm5721886eeo.0.2013.05.09.11.08.20 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Thu, 09 May 2013 11:08:21 -0700 (PDT) Date: Thu, 9 May 2013 18:08:54 +0000 From: Leif Lindholm To: Vladimir =?utf-8?Q?'=CF=86-coder=2Fphcoder'?= Serbinenko Cc: The development of GRUB 2 Subject: Re: [PATCH 7/7] Add support for ARM UEFI ("EFI") platforms Message-ID: <20130509180853.GH28516@rocoto.smurfnet.nu> References: <5159B4CB.2040300@gmail.com> <20130403180757.GO23069@rocoto.smurfnet.nu> <515C8AB7.7000602@gmail.com> <20130404125414.GP23069@rocoto.smurfnet.nu> <51645046.6070403@gmail.com> MIME-Version: 1.0 In-Reply-To: <51645046.6070403@gmail.com> User-Agent: Mutt/1.5.20 (2009-06-14) X-Gm-Message-State: ALoCoQkzQOnrFo8OQ/jZ5dqNl/Yj3mY9zo7o/lnV8f/eMckL+NozhXpejhH0y76vmZ1JcsBodZn6 X-Original-Sender: leif.lindholm@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 2607:f8b0:400c:c01::22a is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Content-Disposition: inline On Tue, Apr 09, 2013 at 07:30:46PM +0200, Vladimir 'φ-coder/phcoder' Serbinenko wrote: > > Since I didn't want to have to duplicate my relocation handling > > between kernel and grub-mkimage, I use kern/arm/dl.c for both. > > Could you move the common functions to dl_helper.c as in ISA64? Done in the attached patch. > > In order to do that in an endianess-safe way, I need to be able to > > export target platform information over there, as well as the > > host_to_target/target_to_host macros. This would involve moving these > > macros, as well as the struct image_target_desc definition, out of > > grub-mkimage.c. > > Is big-endian ARM of any interest at all? I was under impression that it > was limited to few devices and not supported by either u-boot or EFI. > You still have grub_le_to_cpu / grub_cpu_to_le It shouldn't be of much interest at the boot stage, but even if it is there are two things that make life easier: 1) With the endianess support introduced in ARMv6 (supported by RasPi), instructions are always little-endian. This would leave only the abs32 relocations as needing to be configured for a specific target. 2) The UEFI spec (2.3.1) states that on an ARM processor, little-endian will always be the configured state of the data interface(s). > > However, this would also make it possible to do the same for IA64, > > and get rid of some code duplication between grub-mkimagexx.c and > > kern/ia64/dl.c. > > I already did. For IA64 I simply used le_to_cpu/cpu_to_le as ia64-efi is > always little-endian I was referring more to functions like add_value_to_slot_* that are duplicated between these files. But of course, given the IA64 fixed endianess, the other part of my comment was irrelevant :) Attached is a patch that: - incoorporates Francesco's bug fixes - splits out relocation work into dl_helper.c - cleans up code slightly - makes relocations use le_to_cpu/cpu_to_le - changes all grub_util printout calls to grub_dprintf / Leif === 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;