All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/7] Initial support for ARMv7 architecture
@ 2013-03-24 17:01 Leif Lindholm
  2013-03-30 15:15 ` Francesco Lavra
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Leif Lindholm @ 2013-03-24 17:01 UTC (permalink / raw)
  To: grub-devel

[-- Attachment #1: Type: text/plain, Size: 1 bytes --]



[-- Attachment #2: 0002-arm-support.patch --]
[-- Type: application/octet-stream, Size: 27294 bytes --]

=== modified file 'Makefile.util.def'
--- Makefile.util.def	2013-02-25 21:11:06 +0000
+++ Makefile.util.def	2013-03-24 12:56:20 +0000
@@ -149,6 +149,8 @@
   common = util/resolve.c;
   common = grub-core/kern/emu/argp_common.c;
 
+  arm = grub-core/kern/arm/dl.c;
+
   extra_dist = util/grub-mkimagexx.c;
 
   ldadd = libgrubmods.a;

=== modified file 'grub-core/Makefile.core.def'
--- grub-core/Makefile.core.def	2013-03-24 12:56:06 +0000
+++ grub-core/Makefile.core.def	2013-03-24 12:56:20 +0000
@@ -198,6 +198,10 @@
   sparc64_ieee1275 = kern/sparc64/dl.c;
   sparc64_ieee1275 = kern/sparc64/ieee1275/ieee1275.c;
 
+  arm = kern/arm/dl.c;
+  arm = kern/arm/cache.S;
+  arm = kern/arm/misc.S;
+
   emu = disk/host.c;
   emu = gnulib/progname.c;
   emu = gnulib/error.c;
@@ -1378,6 +1382,7 @@
   extra_dist = lib/powerpc/setjmp.S;
   extra_dist = lib/ia64/setjmp.S;
   extra_dist = lib/ia64/longjmp.S;
+  extra_dist = lib/arm/setjmp.S;
 };
 
 module = {

=== added directory 'grub-core/kern/arm'
=== added file 'grub-core/kern/arm/cache.S'
--- grub-core/kern/arm/cache.S	1970-01-01 00:00:00 +0000
+++ grub-core/kern/arm/cache.S	2013-03-24 12:56:20 +0000
@@ -0,0 +1,251 @@
+/*
+ *  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/>.
+ */
+
+#include <grub/symbol.h>
+#include <grub/dl.h>
+
+	.file	"cache.S"
+	.text
+	.syntax	unified
+#if !defined (__thumb2__)
+	.arm
+#define ARM(x...)	x
+#define THUMB(x...)
+#else
+	.thumb
+#define THUMB(x...)	x
+#define ARM(x...)
+#endif
+
+	.align	2
+
+/*
+ * Simple cache maintenance functions
+ */
+
+@ r0 - *beg (inclusive)
+@ r1 - *end (exclusive)	
+clean_dcache_range:
+	@ Clean data cache range for range to point-of-unification
+	ldr	r2, dlinesz
+1:	cmp	r0, r1
+	bge	2f
+#ifdef DEBUG
+	push	{r0-r2, lr}
+	mov	r1, r2
+	mov	r2, r0
+	ldr	r0, =dcstr
+	bl	EXT_C(grub_printf)
+	pop	{r0-r2, lr}
+#endif
+	mcr	p15, 0, r0, c7, c11, 1	@ DCCMVAU
+	add	r0, r0, r2		@ Next line
+	b	1b
+2:	dsb
+	bx	lr
+
+@ r0 - *beg (inclusive)
+@ r1 - *end (exclusive)	
+invalidate_icache_range:
+	@ Invalidate instruction cache for range to point-of-unification
+	ldr	r2, ilinesz
+1:	cmp	r0, r1
+	bge	2f
+#ifdef DEBUG
+	push	{r0-r2, lr}
+	mov	r1, r2
+	mov	r2, r0
+	ldr	r0, =icstr
+	bl	EXT_C(grub_printf)
+	pop	{r0-r2, lr}
+#endif
+	mcr	p15, 0, r0, c7, c5, 1	@ ICIMVAU
+	add	r0, r0, r2		@ Next line
+	b	1b
+	@ Branch predictor invalidate all
+2:	mcr	p15, 0, r0, c7,	c5, 6	@ BPIALL
+	dsb
+	isb
+	bx	lr
+	
+@void __wrap___clear_cache(char *beg, char *end);
+FUNCTION(__wrap___clear_cache)
+	dmb
+	dsb
+	push	{r4-r6, lr}
+	ldr	r2, probed	@ If first call, probe cache sizes
+	cmp	r2, #0
+	bleq	probe_caches	@ This call corrupts r3
+	mov	r4, r0
+	mov	r5, r1
+	bl	clean_dcache_range
+	mov	r0, r4
+	mov	r1, r5
+	bl	invalidate_icache_range
+	pop	{r4-r6, pc}
+
+probe_caches:
+	push	{r4-r6, lr}
+	mrc 	p15, 0, r4, c0, c0, 1	@ Read Cache Type Register
+	mov	r5, #1
+	ubfx	r6, r4, #16, #4		@ Extract min D-cache num word log2
+	add	r6, r6, #2		@ words->bytes
+	lsl	r6, r5, r6		@ Convert to num bytes
+	ldr	r3, =dlinesz
+	str	r6, [r3]
+	and	r6, r4, #0xf		@ Extract min I-cache num word log2
+	add	r6, r6, #2		@ words->bytes
+	lsl	r6, r5, r6		@ Convert to num bytes
+	ldr	r3, =ilinesz
+	str	r6, [r3]
+	ldr	r3, =probed		@ Flag cache probing done
+	str	r5, [r3]
+	pop	{r4-r6, pc}
+
+#ifdef DEBUG
+dcstr:	.asciz	"cleaning %d bytes of D cache @ 0x%08x\n"
+icstr:	.asciz	"invalidating %d bytes of I cache @ 0x%08x\n"
+#endif
+	
+	.align	3
+probed:	.long	0
+dlinesz:
+	.long	0
+ilinesz:
+	.long	0
+
+@void grub_arch_sync_caches (void *address, grub_size_t len)
+FUNCTION(grub_arch_sync_caches)
+	add	r1, r0, r1
+	b	__wrap___clear_cache
+
+	@ r0  - CLIDR
+	@ r1  - LoC
+	@ r2  - current level
+	@ r3  - num sets
+	@ r4  - num ways
+	@ r5  - current set
+	@ r6  - current way
+	@ r7  - line size
+	@ r8  - scratch
+	@ r9  - scratch
+	@ r10 - scratch
+	@ r11 - scratch
+clean_invalidate_dcache:
+	push	{r4-r12, lr}
+	mrc 	p15, 1, r0, c0, c0, 1	@ Read CLIDR
+	ubfx	r1, r0, #24, #3		@ Extract LoC
+	
+	mov	r2, #0			@ First level, L1
+2:	and	r8, r0, #7		@ cache type at current level
+	cmp	r8, #2
+	blt	5f			@ instruction only, or none, skip level
+
+	@ set current cache level/type (for CSSIDR read)
+	lsl	r8, r2, #1
+	mcr	p15, 2, r8, c0, c0, 0	@ Write CSSELR (level, type: data/uni)
+
+	@ read current cache information
+	mrc	p15, 1, r8, c0, c0, 0	@ Read CSSIDR
+	ubfx	r3, r8, #13, #14	@ Number of sets -1
+	ubfx	r4, r8, #3, #9		@ Number of ways -1
+	and	r7, r8, #7		@ log2(line size in words) - 2
+	add	r7, r7, #2		@  adjust
+	mov	r8, #1
+	lsl	r7, r8, r7		@  -> line size in words
+	lsl	r7, r7, #2		@  -> bytes
+
+	@ set loop
+	mov	r5, #0			@ current set = 0
+3:	lsl	r8, r2, #1		@ insert level
+	clz	r9, r7			@ calculate set field offset
+	mov	r10, #31
+	sub	r9, r10, r9
+	lsl	r10, r5, r9
+	orr	r8, r8, r10		@ insert set field
+
+	@ way loop
+	@ calculate way field offset
+	mov	r6, #0			@ current way = 0
+	add	r10, r4, #1
+	clz	r9, r10			@ r9 = way field offset
+	add	r9, r9, #1
+4:	lsl	r10, r6, r9
+	orr	r11, r8, r10		@ insert way field	
+	
+	@ clean line by set/way
+	mcr	p15, 0, r11, c7, c14, 2	@ DCCISW
+	
+	@ next way
+	add	r6, r6, #1
+	cmp	r6, r4
+	ble	4b
+
+	@ next set
+	add	r5, r5, #1
+	cmp	r5, r3
+	ble	3b
+	
+	@ next level
+5:	lsr	r0, r0, #3		@ align next level CLIDR 'type' field
+	add	r2, r2, #1		@ increment cache level counter
+	cmp	r2, r1
+	blt	2b			@ outer loop
+
+	@ return
+6:	dsb
+	isb
+	pop	{r4-r12, pc}
+
+FUNCTION(grub_arm_disable_caches_mmu)
+	push	{r4, lr}
+
+	@ disable D-cache
+	mrc	p15, 0, r0, c1, c0, 0
+	bic	r0, r0, #(1 << 2)
+	mcr	p15, 0, r0, c1, c0, 0
+	dsb
+	isb
+
+	@ clean/invalidate D-cache
+	bl	clean_invalidate_dcache
+
+	@ disable I-cache
+	mrc	p15, 0, r0, c1, c0, 0
+	bic	r0, r0, #(1 << 12)
+	mcr	p15, 0, r0, c1, c0, 0
+	dsb
+	isb
+
+	@ invalidate I-cache (also invalidates branch predictors)
+	mcr	p15, 0, r0, c7, c5, 0
+	dsb
+	isb
+	
+	@ clear SCTLR M bit
+	mrc	p15, 0, r0, c1, c0, 0
+	bic	r0, r0, #(1 << 0)
+	mcr	p15, 0, r0, c1, c0, 0
+
+	mcr	p15, 0, r0, c8, c7, 0	@ invalidate TLB
+	mcr	p15, 0, r0, c7, c5, 6	@ invalidate branch predictor
+	dsb
+	isb
+
+	pop	{r4, pc}
+

=== added file 'grub-core/kern/arm/dl.c'
--- grub-core/kern/arm/dl.c	1970-01-01 00:00:00 +0000
+++ grub-core/kern/arm/dl.c	2013-03-24 12:56:20 +0000
@@ -0,0 +1,490 @@
+/* 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/elf.h>
+#include <grub/misc.h>
+#include <grub/err.h>
+#include <grub/mm.h>
+#include <grub/i18n.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;
+
+/*
+ * 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
+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))
+    {
+#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
+    }
+
+  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))
+    {
+#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
+    }
+
+#ifdef GRUB_UTIL
+  grub_util_info ("    relative destination = 0x%08x",
+		  (unsigned int)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<c>.W
+ */
+grub_err_t
+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;
+}
+
+
+\f
+/***********************************************************
+ * ARM (A32) relocations:                                  *
+ *                                                         *
+ * ARM instructions are 32-bit in size and 32-bit aligned. *
+ ***********************************************************/
+
+/*
+ * R_ARM_JUMP24
+ *
+ * Relocate ARM (A32) B
+ */
+grub_err_t
+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;
+}
+
+
+\f
+/*************************************************
+ * 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)
+{
+  grub_dl_segment_t seg;
+  Elf_Rel *rel;
+  Elf_Sym *sym;
+  int i, entnum;
+
+  entnum = relhdr->sh_size / sizeof (Elf_Rel);
+
+  /* Find the target segment for this relocation section. */
+  seg = find_segment (mod->segment, relhdr->sh_info);
+  if (!seg)
+    return grub_error (GRUB_ERR_EOF, N_("relocation segment not found"));
+
+  rel = (Elf_Rel *) ((grub_addr_t) e + relhdr->sh_offset);
+
+  /* Step through all relocations */
+  for (i = 0, sym = mod->symtab; i < entnum; i++)
+    {
+      Elf_Addr *target, sym_addr;
+      int relsym, reltype;
+      grub_err_t retval;
+
+      if (seg->size < rel[i].r_offset)
+	return grub_error (GRUB_ERR_BAD_MODULE,
+			   "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);
+
+      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);
+	    if (retval != GRUB_ERR_NONE)
+	      return retval;
+	  }
+	  break;
+	case R_ARM_JUMP24:
+	  {
+	    retval = reloc_jump24 (target, sym_addr);
+	    if (retval != GRUB_ERR_NONE)
+	      return retval;
+	  }
+	  break;
+	case R_ARM_THM_CALL:
+	case R_ARM_THM_JUMP24:
+	  {
+	    /* Thumb instructions can be 16-bit aligned */
+	    retval = reloc_thm_call ((grub_uint16_t *) target, sym_addr);
+	    if (retval != GRUB_ERR_NONE)
+	      return retval;
+	  }
+	  break;
+	case R_ARM_THM_JUMP19:
+	  {
+	    /* Thumb instructions can be 16-bit aligned */
+	    retval = reloc_thm_jump19 ((grub_uint16_t *) target, sym_addr);
+	    if (retval != GRUB_ERR_NONE)
+	      return retval;
+	  }
+	  break;
+	default:
+	  return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+			     N_("relocation 0x%x is not implemented yet"),
+			     reltype);
+	}
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+
+/*
+ * Check if EHDR is a valid ELF header.
+ */
+grub_err_t
+grub_arch_dl_check_header (void *ehdr)
+{
+  Elf_Ehdr *e = ehdr;
+
+  /* Check the magic numbers.  */
+  if (e->e_ident[EI_CLASS] != ELFCLASS32
+      || e->e_ident[EI_DATA] != ELFDATA2LSB || e->e_machine != EM_ARM)
+    return grub_error (GRUB_ERR_BAD_OS,
+		       N_("invalid arch-dependent ELF magic"));
+
+  return GRUB_ERR_NONE;
+}
+
+/*
+ * Verify that provided ELF header contains reference to a symbol table
+ */
+static int
+has_symtab (Elf_Ehdr * e)
+{
+  int i;
+  Elf_Shdr *s;
+
+  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_SYMTAB)
+      return 1;
+
+  return 0;
+}
+
+/*
+ * grub_arch_dl_relocate_symbols():
+ *   Only externally visible function in this file.
+ *   Locates the relocations section of the ELF object, and calls
+ *   do_relocations() to deal with it.
+ */
+grub_err_t
+grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
+{
+  Elf_Ehdr *e = ehdr;
+  Elf_Shdr *s;
+  unsigned i;
+
+  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))
+
+  for (i = 0, s = FIRST_SHDR (e); i < e->e_shnum; i++, s = NEXT_SHDR (e, s))
+    {
+      grub_err_t ret;
+
+      switch (s->sh_type)
+	{
+	case SHT_REL:
+	  {
+	    /* Relocations, no addends */
+	    ret = do_relocations (s, e, mod);
+	    if (ret != GRUB_ERR_NONE)
+	      return ret;
+	  }
+	  break;
+	case SHT_NULL:
+	case SHT_PROGBITS:
+	case SHT_SYMTAB:
+	case SHT_STRTAB:
+	case SHT_NOBITS:
+	case SHT_ARM_ATTRIBUTES:
+	  break;
+	case SHT_RELA:
+	default:
+	  {
+	    grub_printf ("unhandled section_type: %d (0x%08x)\n",
+			 s->sh_type, s->sh_type);
+	    return GRUB_ERR_NOT_IMPLEMENTED_YET;
+	  };
+	}
+    }
+
+#undef FIRST_SHDR
+#undef NEXT_SHDR
+
+  return GRUB_ERR_NONE;
+}
+#endif /* ndef GRUB_UTIL */

=== added file 'grub-core/kern/arm/misc.S'
--- grub-core/kern/arm/misc.S	1970-01-01 00:00:00 +0000
+++ grub-core/kern/arm/misc.S	2013-03-24 12:56:20 +0000
@@ -0,0 +1,44 @@
+/*
+ *  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/>.
+ */
+
+#include <grub/symbol.h>
+#include <grub/dl.h>
+
+	.file	"misc.S"
+	.text
+	.syntax	unified
+#if !defined (__thumb2__)
+	.arm
+#define ARM(x...)	x
+#define THUMB(x...)
+#else
+	.thumb
+#define THUMB(x...)	x
+#define ARM(x...)
+#endif
+
+	.align	2
+
+/*
+ * Null divide-by-zero handler
+ */
+FUNCTION(raise)
+	mov	r0, #0
+	bx	lr
+	
+	.end

=== added directory 'grub-core/lib/arm'
=== added file 'grub-core/lib/arm/setjmp.S'
--- grub-core/lib/arm/setjmp.S	1970-01-01 00:00:00 +0000
+++ grub-core/lib/arm/setjmp.S	2013-03-24 12:56:20 +0000
@@ -0,0 +1,55 @@
+/*
+ *  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/>.
+ */
+
+#include <grub/symbol.h>
+#include <grub/dl.h>
+
+	.file	"setjmp.S"
+	.syntax	unified
+#if !defined (__thumb2__)
+	.arm
+#define ARM(x...)	x
+#define THUMB(x...)
+#else
+	.thumb
+#define THUMB(x...)	x
+#define ARM(x...)
+#endif
+
+	.text
+
+/*
+ * int grub_setjmp (grub_jmp_buf env)
+ */
+FUNCTION(grub_setjmp)
+ THUMB(	mov	ip, sp			)
+ THUMB(	stm	r0, { r4-r11, ip, lr }	)
+ ARM(	stm	r0, { r4-r11, sp, lr }	)
+	mov	r0, #0
+	bx	lr
+
+/*
+ * int grub_longjmp (grub_jmp_buf env, int val)
+ */
+FUNCTION(grub_longjmp)
+ THUMB(	ldm	r0, { r4-r11, ip, lr }	)
+ THUMB(	mov	sp, ip			)
+ ARM(	ldm	r0, { r4-r11, sp, lr }	)
+	movs	r0, r1
+	moveq	r0, #1
+	bx	lr

=== modified file 'grub-core/lib/setjmp.S'
--- grub-core/lib/setjmp.S	2012-01-18 13:04:52 +0000
+++ grub-core/lib/setjmp.S	2013-03-24 12:56:20 +0000
@@ -11,6 +11,8 @@
 #elif defined(__ia64__)
 #include "./ia64/setjmp.S"
 #include "./ia64/longjmp.S"
+#elif defined(__arm__)
+#include "./arm/setjmp.S"
 #else
 #error "Unknown target cpu type"
 #endif

=== added directory 'include/grub/arm'
=== added file 'include/grub/arm/system.h'
--- include/grub/arm/system.h	1970-01-01 00:00:00 +0000
+++ include/grub/arm/system.h	2013-03-24 12:56:20 +0000
@@ -0,0 +1,7 @@
+#ifndef GRUB_SYSTEM_CPU_HEADER
+#define GRUB_SYSTEM_CPU_HEADER
+
+void grub_arm_disable_caches_mmu (void);
+
+#endif /* ! GRUB_SYSTEM_CPU_HEADER */
+

=== added file 'include/grub/arm/time.h'
--- include/grub/arm/time.h	1970-01-01 00:00:00 +0000
+++ include/grub/arm/time.h	2013-03-24 12:56:20 +0000
@@ -0,0 +1,29 @@
+/*
+ *  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 KERNEL_CPU_TIME_HEADER
+#define KERNEL_CPU_TIME_HEADER	1
+
+static __inline void
+grub_cpu_idle (void)
+{
+  /* FIXME: this can't work until we handle interrupts.  */
+/*  __asm__ __volatile__ ("wfi"); */
+}
+
+#endif /* ! KERNEL_CPU_TIME_HEADER */

=== added file 'include/grub/arm/types.h'
--- include/grub/arm/types.h	1970-01-01 00:00:00 +0000
+++ include/grub/arm/types.h	2013-03-24 12:56:20 +0000
@@ -0,0 +1,34 @@
+/*
+ *  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_TYPES_CPU_HEADER
+#define GRUB_TYPES_CPU_HEADER	1
+
+/* The size of void *.  */
+#define GRUB_TARGET_SIZEOF_VOID_P	4
+
+/* The size of long.  */
+#define GRUB_TARGET_SIZEOF_LONG		4
+
+/* currently only support little-endian.  */
+#undef GRUB_TARGET_WORDS_BIGENDIAN
+
+/* Unaligned accesses only supported if MMU enabled */
+//#define GRUB_HAVE_UNALIGNED_ACCESS 1
+
+#endif /* ! GRUB_TYPES_CPU_HEADER */

=== modified file 'include/grub/elf.h'
--- include/grub/elf.h	2013-01-20 22:01:47 +0000
+++ include/grub/elf.h	2013-03-24 12:56:20 +0000
@@ -2098,6 +2098,7 @@
 #define R_ARM_LDR_SBREL_11_0	35
 #define R_ARM_ALU_SBREL_19_12	36
 #define R_ARM_ALU_SBREL_27_20	37
+#define R_ARM_THM_JUMP19	51
 #define R_ARM_TLS_GOTDESC	90
 #define R_ARM_TLS_CALL		91
 #define R_ARM_TLS_DESCSEQ	92

=== modified file 'include/grub/libgcc.h'
--- include/grub/libgcc.h	2013-03-03 14:57:30 +0000
+++ include/grub/libgcc.h	2013-03-24 12:56:20 +0000
@@ -112,3 +112,14 @@
 void EXPORT_FUNC (_savegpr_30) (void);
 void EXPORT_FUNC (_savegpr_31) (void);
 #endif
+
+#if defined (__arm__)
+void EXPORT_FUNC (__aeabi_idiv) (void);
+void EXPORT_FUNC (__aeabi_idivmod) (void);
+void EXPORT_FUNC (__aeabi_lasr) (void);
+void EXPORT_FUNC (__aeabi_llsl) (void);
+void EXPORT_FUNC (__aeabi_llsr) (void);
+void EXPORT_FUNC (__aeabi_uidiv) (void);
+void EXPORT_FUNC (__aeabi_uidivmod) (void);
+void EXPORT_FUNC (__wrap___clear_cache) (void *, void *);
+#endif

=== modified file 'include/grub/symbol.h'
--- include/grub/symbol.h	2012-05-28 15:49:18 +0000
+++ include/grub/symbol.h	2013-03-24 12:56:20 +0000
@@ -29,7 +29,11 @@
 
 #if HAVE_ASM_USCORE
 #ifdef ASM_FILE
-# define EXT_C(sym)	_ ## sym
+# ifndef (__arm__)
+#  define EXT_C(sym)	_ ## sym
+# else
+#  define EXT_C(sym)	% ## sym
+# endif
 #else
 # define EXT_C(sym)	"_" sym
 #endif


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2013-04-09 11:37 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-03-24 17:01 [PATCH 2/7] Initial support for ARMv7 architecture Leif Lindholm
2013-03-30 15:15 ` Francesco Lavra
2013-04-03 15:36   ` Leif Lindholm
2013-04-01  1:28 ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-04-01  9:36   ` Francesco Lavra
2013-04-03 15:20   ` Leif Lindholm
2013-04-08 23:27 ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-04-09 10:34   ` Leif Lindholm
2013-04-09 11:37     ` Vladimir 'φ-coder/phcoder' Serbinenko

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.