This patch adds a flat loader. Currently it supports the following
relocations:
 - R_LM32_32
 - R_LM32_HI16
 - R_LM32_LO16
 - R_LM32_CALL

Signed-off-by: Michael Walle <[email protected]>
---
 arch/lm32/include/asm/flat.h |   58 ++++++++++++++++++++++++++------
 arch/lm32/kernel/Makefile    |   12 ++++---
 arch/lm32/kernel/flat.c      |   74 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 128 insertions(+), 16 deletions(-)
 create mode 100644 arch/lm32/kernel/flat.c

diff --git a/arch/lm32/include/asm/flat.h b/arch/lm32/include/asm/flat.h
index ca08c80..c35c671 100644
--- a/arch/lm32/include/asm/flat.h
+++ b/arch/lm32/include/asm/flat.h
@@ -1,17 +1,53 @@
 /*
- * Based on:
- * include/asm-m68knommu/flat.h
+ * uClinux flat-format executables
+ *
+ * Copyright 2003-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2
  */
 
-#ifndef _ASM_LM32_FLAT_H__
-#define _ASM_LM32_FLAT_H__
+#ifndef __ASM_LM32_FLAT_H
+#define __ASM_LM32_FLAT_H
 
-#define        flat_stack_align(sp)                    /* nothing needed */
-#define        flat_argvp_envp_on_stack()              1
+#include <asm/unaligned.h>
+
+#define        flat_argvp_envp_on_stack()              0
 #define        flat_old_ram_flag(flags)                (flags)
-#define        flat_reloc_valid(reloc, size)           ((reloc) <= (size))
-#define        flat_get_addr_from_rp(rp, relval, flags)        
get_unaligned(rp)
-#define        flat_put_addr_at_rp(rp, val, relval)    put_unaligned(val,rp)
-#define        flat_get_relocate_addr(rel)             (rel)
 
-#endif /* _ASM_LM32_FLAT_H__ */
+extern unsigned long lm32_get_addr_from_rp (unsigned long *ptr,
+                                       unsigned long relval,
+                                       unsigned long flags,
+                                       unsigned long *persistent);
+
+extern void lm32_put_addr_at_rp(unsigned long *ptr, unsigned long addr,
+                               unsigned long relval);
+
+/* The amount by which a relocation can exceed the program image limits
+   without being regarded as an error.  */
+
+#define        flat_reloc_valid(reloc, size)   ((reloc) <= (size))
+
+#define        flat_get_addr_from_rp(rp, relval, flags, persistent)    \
+       lm32_get_addr_from_rp(rp, relval, flags, persistent)
+#define        flat_put_addr_at_rp(rp, val, relval)    \
+       lm32_put_addr_at_rp(rp, val, relval)
+
+/* Convert a relocation entry into an address.  */
+static inline unsigned long
+flat_get_relocate_addr (unsigned long relval)
+{
+       return relval & 0x1fffffff; /* Mask out top 3 bits */
+}
+
+static inline int flat_set_persistent(unsigned long relval,
+                                     unsigned long *persistent)
+{
+       int type = (relval >> 29) & 7;
+       if (type == 3) {
+               *persistent = relval << 16;
+               return 1;
+       }
+       return 0;
+}
+
+#endif /* __ASM_LM32_FLAT_H */
diff --git a/arch/lm32/kernel/Makefile b/arch/lm32/kernel/Makefile
index 43e53e2..2ace8b0 100644
--- a/arch/lm32/kernel/Makefile
+++ b/arch/lm32/kernel/Makefile
@@ -2,10 +2,12 @@
 # arch/lm32/kernel/Makefile
 #
 
-extra-y                := head.o init_task.o vmlinux.lds
+extra-y := head.o init_task.o vmlinux.lds
 
-obj-y          += sys_lm32.o setup.o traps.o signal.o \
-                  time.o ptrace.o irq.o process.o entry.o dma.o gpio.o
-obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 
+obj-y := \
+       sys_lm32.o setup.o traps.o signal.o time.o \
+       ptrace.o irq.o process.o entry.o dma.o gpio.o \
+       flat.o
 
-obj-$(CONFIG_MODULES)  += module.o
+obj-$(CONFIG_EARLY_PRINTK)  += early_printk.o 
+obj-$(CONFIG_MODULES)       += module.o
diff --git a/arch/lm32/kernel/flat.c b/arch/lm32/kernel/flat.c
new file mode 100644
index 0000000..b8752f6
--- /dev/null
+++ b/arch/lm32/kernel/flat.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2007 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/flat.h>
+
+#define FLAT_LM32_RELOC_TYPE_32_BIT   0
+#define FLAT_LM32_RELOC_TYPE_HI16_BIT 1
+#define FLAT_LM32_RELOC_TYPE_LO16_BIT 2
+
+unsigned long lm32_get_addr_from_rp(unsigned long *ptr,
+               unsigned long relval,
+               unsigned long flags,
+               unsigned long *persistent)
+{
+       unsigned short *usptr = (unsigned short *)ptr + 1;
+       int type = (relval >> 29) & 7;
+       unsigned long val;
+
+       switch (type) {
+       case FLAT_LM32_RELOC_TYPE_32_BIT:
+               pr_debug("*ptr = %lx", get_unaligned(ptr));
+               val = get_unaligned(ptr);
+               break;
+
+       case FLAT_LM32_RELOC_TYPE_LO16_BIT:
+       case FLAT_LM32_RELOC_TYPE_HI16_BIT:
+               pr_debug("*usptr = %x", get_unaligned(usptr));
+               val = get_unaligned(usptr) & 0xffff;
+               val += *persistent;
+               break;
+
+       default:
+               pr_debug("BINFMT_FLAT: Unknown relocation type %x\n", type);
+               return 0;
+       }
+
+       return val;
+}
+EXPORT_SYMBOL(lm32_get_addr_from_rp);
+
+/*
+ * Insert the address ADDR into the symbol reference at RP;
+ * RELVAL is the raw relocation-table entry from which RP is derived
+ */
+void lm32_put_addr_at_rp(unsigned long *ptr, unsigned long addr,
+               unsigned long relval)
+{
+       unsigned short *usptr = (unsigned short *)ptr + 1;
+       int type = (relval >> 29) & 7;
+
+       switch (type) {
+       case FLAT_LM32_RELOC_TYPE_32_BIT:
+               put_unaligned(addr, ptr);
+               pr_debug("new ptr =%lx", get_unaligned(ptr));
+               break;
+
+       case FLAT_LM32_RELOC_TYPE_LO16_BIT:
+               put_unaligned(addr, usptr);
+               pr_debug("new value %x at %p", get_unaligned(usptr), usptr);
+               break;
+
+       case FLAT_LM32_RELOC_TYPE_HI16_BIT:
+               put_unaligned(addr >> 16, usptr);
+               pr_debug("new value %x at %p", get_unaligned(usptr), usptr);
+               break;
+
+       }
+}
+EXPORT_SYMBOL(lm32_put_addr_at_rp);
-- 
1.7.2.3

_______________________________________________
http://lists.milkymist.org/listinfo.cgi/devel-milkymist.org
IRC: #milkymist@Freenode
Twitter: www.twitter.com/milkymistvj
Ideas? http://milkymist.uservoice.com

Reply via email to