Add a relocation implementation as the first thing in the generic board
library. This library is needed by SPL also.

Signed-off-by: Simon Glass <s...@chromium.org>
---
 Makefile         |    1 +
 board/Makefile   |   45 ++++++++++++++++++++++++
 board/reloc.c    |  101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/common.h |    2 +-
 include/reloc.h  |   37 ++++++++++++++++++++
 spl/Makefile     |    1 +
 6 files changed, 186 insertions(+), 1 deletions(-)
 create mode 100644 board/Makefile
 create mode 100644 board/reloc.c
 create mode 100644 include/reloc.h

diff --git a/Makefile b/Makefile
index fb658f4..d313481 100644
--- a/Makefile
+++ b/Makefile
@@ -221,6 +221,7 @@ LIBS  = lib/libgeneric.o
 LIBS += lib/lzma/liblzma.o
 LIBS += lib/lzo/liblzo.o
 LIBS += lib/zlib/libz.o
+LIBS += board/libboard.o
 LIBS += $(shell if [ -f board/$(VENDOR)/common/Makefile ]; then echo \
        "board/$(VENDOR)/common/lib$(VENDOR).o"; fi)
 LIBS += $(CPUDIR)/lib$(CPU).o
diff --git a/board/Makefile b/board/Makefile
new file mode 100644
index 0000000..e7f8b17
--- /dev/null
+++ b/board/Makefile
@@ -0,0 +1,45 @@
+#
+# (C) Copyright 2002-2006
+# Wolfgang Denk, DENX Software Engineering, w...@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program 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 2 of
+# the License, or (at your option) any later version.
+#
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB    = $(obj)libboard.o
+
+ifndef CONFIG_SYS_LEGACY_BOARD
+COBJS  += reloc.o
+endif
+
+SRCS   := $(COBJS:.o=.c)
+OBJS   := $(addprefix $(obj),$(COBJS))
+
+$(LIB):        $(obj).depend $(OBJS)
+       $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/reloc.c b/board/reloc.c
new file mode 100644
index 0000000..abd9c0b
--- /dev/null
+++ b/board/reloc.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program 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 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm-generic/link_symbols.h>
+#include <reloc.h>
+#include <nand.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int reloc_make_copy(void)
+{
+       ulong *dst_addr = (ulong *)gd->relocaddr;
+
+       /* TODO: __text_start would be better when we have it */
+       ulong *src_addr = (ulong *)_start;
+       /* TODO: switch over to __image_copy_end when we can */
+#ifdef CONFIG_SPL_BUILD
+       ulong *end_addr = (ulong *)&__image_copy_end;
+#else
+       ulong *end_addr = (ulong *)&__rel_dyn_start;
+#endif
+
+       if (dst_addr != src_addr) {
+               while (src_addr < end_addr)
+                       *dst_addr++ = *src_addr++;
+       }
+       return 0;
+}
+
+static int reloc_clear_bss(void)
+{
+       ulong *dst_addr = (ulong *)&__bss_start;
+
+       /* TODO: change to __bss_end */
+       ulong *end_addr = (ulong *)&__bss_end__;
+
+#ifndef CONFIG_SPL_BUILD
+       /* No relocation for SPL */
+       dst_addr += gd->reloc_off / sizeof(ulong);
+       end_addr += gd->reloc_off / sizeof(ulong);
+#endif
+
+       while (dst_addr < end_addr)
+               *dst_addr++ = 0;
+
+       return 0;
+}
+
+static int reloc_elf(void)
+{
+#ifndef CONFIG_SPL_BUILD
+       const Elf32_Rel *ptr;
+       Elf32_Addr *addr;
+
+       /* scan the relocation table for relevant entries */
+       for (ptr = __rel_dyn_start; ptr < __rel_dyn_end; ptr++) {
+               /* CONFIG_TEXT_BASE on x86 */
+               if (ptr->r_offset < CONFIG_SYS_TEXT_BASE)
+                       continue;
+
+               addr = (Elf32_Addr *)(ptr->r_offset + gd->reloc_off);
+               if (arch_elf_relocate_entry(addr, ptr->r_info, __dynsym_start,
+                               gd->reloc_off))
+                       return -1;
+       }
+#endif
+       return 0;
+}
+
+void relocate_code(ulong dest_addr_sp, gd_t *new_gd, ulong dest_addr)
+{
+       reloc_make_copy();
+       reloc_elf();
+       reloc_clear_bss();
+       /* TODO: tidy this up */
+#ifdef CONFIG_NAND_SPL
+       nand_boot();
+#else
+       proc_call_board_init_r(new_gd, dest_addr, board_init_r, dest_addr_sp);
+#endif
+}
diff --git a/include/common.h b/include/common.h
index 5ca8820..223bf52 100644
--- a/include/common.h
+++ b/include/common.h
@@ -469,7 +469,7 @@ int dcache_status (void);
 void   dcache_enable (void);
 void   dcache_disable(void);
 void   mmu_disable(void);
-void   relocate_code (ulong, gd_t *, ulong) __attribute__ ((noreturn));
+#include <reloc.h>
 ulong  get_endaddr   (void);
 void   trap_init     (ulong);
 #if defined (CONFIG_4xx)       || \
diff --git a/include/reloc.h b/include/reloc.h
new file mode 100644
index 0000000..7a4f7aa
--- /dev/null
+++ b/include/reloc.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program 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 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __RELOC_H
+#define __RELOC_H
+
+#include <elf.h>
+
+void proc_call_board_init_r(gd_t *new_gd, ulong dest_addr,
+               void (*board_init_r_func)(gd_t *, ulong), ulong dest_addr_sp)
+               __attribute__ ((noreturn));
+
+int arch_elf_relocate_entry(Elf32_Addr *addr, Elf32_Word info,
+                           Elf32_Sym *symtab, ulong reloc_off);
+
+void relocate_code(ulong dest_sp, gd_t *new_gd, ulong dest_addr)
+               __attribute__ ((noreturn));
+#endif
diff --git a/spl/Makefile b/spl/Makefile
index 6ac42a2..103f773 100644
--- a/spl/Makefile
+++ b/spl/Makefile
@@ -39,6 +39,7 @@ LIBS-y += $(CPUDIR)/lib$(CPU).o
 ifdef SOC
 LIBS-y += $(CPUDIR)/$(SOC)/lib$(SOC).o
 endif
+LIBS-y += board/libboard.o
 LIBS-y += board/$(BOARDDIR)/lib$(BOARD).o
 LIBS-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/lib$(VENDOR).o
 
-- 
1.7.3.1

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to