Signed-off-by: Alexey Brodkin <abrod...@synopsys.com>

Cc: Mischa Jonker <mjon...@synopsys.com>
Cc: Francois Bedard <fbed...@synopsys.com>
---
 arch/arc/lib/Makefile   |   9 ++++
 arch/arc/lib/bootm.c    | 106 ++++++++++++++++++++++++++++++++++++++++++++++++
 arch/arc/lib/relocate.c |  74 +++++++++++++++++++++++++++++++++
 arch/arc/lib/sections.c |  21 ++++++++++
 4 files changed, 210 insertions(+)
 create mode 100644 arch/arc/lib/Makefile
 create mode 100644 arch/arc/lib/bootm.c
 create mode 100644 arch/arc/lib/relocate.c
 create mode 100644 arch/arc/lib/sections.c

diff --git a/arch/arc/lib/Makefile b/arch/arc/lib/Makefile
new file mode 100644
index 0000000..6420cf2
--- /dev/null
+++ b/arch/arc/lib/Makefile
@@ -0,0 +1,9 @@
+#
+# Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y += sections.o
+obj-y += relocate.o
+obj-$(CONFIG_CMD_BOOTM) += bootm.o
diff --git a/arch/arc/lib/bootm.c b/arch/arc/lib/bootm.c
new file mode 100644
index 0000000..d185a50
--- /dev/null
+++ b/arch/arc/lib/bootm.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static ulong get_sp(void)
+{
+       ulong ret;
+
+       asm("mov %0, sp" : "=r"(ret) : );
+       return ret;
+}
+
+void arch_lmb_reserve(struct lmb *lmb)
+{
+       ulong sp;
+
+       /*
+        * Booting a (Linux) kernel image
+        *
+        * Allocate space for command line and board info - the
+        * address should be as high as possible within the reach of
+        * the kernel (see CONFIG_SYS_BOOTMAPSZ settings), but in unused
+        * memory, which means far enough below the current stack
+        * pointer.
+        */
+       sp = get_sp();
+       debug("## Current stack ends at 0x%08lx ", sp);
+
+       /* adjust sp by 4K to be safe */
+       sp -= 4096;
+       lmb_reserve(lmb, sp, (CONFIG_SYS_SDRAM_BASE + gd->ram_size - sp));
+}
+
+static int cleanup_before_linux(void)
+{
+       disable_interrupts();
+       flush_dcache_all();
+       invalidate_icache_all();
+
+       return 0;
+}
+
+/* Subcommand: PREP */
+static void boot_prep_linux(bootm_headers_t *images)
+{
+       if (image_setup_linux(images))
+               hang();
+}
+
+/* Subcommand: GO */
+static void boot_jump_linux(bootm_headers_t *images, int flag)
+{
+       void (*kernel_entry)(int zero, int arch, uint params);
+       unsigned int r0, r2;
+       int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
+
+       kernel_entry = (void (*)(int, int, uint))images->ep;
+
+       debug("## Transferring control to Linux (at address %08lx)...\n",
+             (ulong) kernel_entry);
+       bootstage_mark(BOOTSTAGE_ID_RUN_OS);
+
+       printf("\nStarting kernel ...%s\n\n", fake ?
+              "(fake run for tracing)" : "");
+       bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
+
+       cleanup_before_linux();
+
+       if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) {
+               r0 = 2;
+               r2 = (unsigned int)images->ft_addr;
+       } else {
+               r0 = 1;
+               r2 = (unsigned int)getenv("bootargs");
+       }
+
+       if (!fake)
+               kernel_entry(r0, 0, r2);
+}
+
+int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
+{
+       /* No need for those on ARC */
+       if ((flag & BOOTM_STATE_OS_BD_T) || (flag & BOOTM_STATE_OS_CMDLINE))
+               return -1;
+
+       if (flag & BOOTM_STATE_OS_PREP) {
+               boot_prep_linux(images);
+               return 0;
+       }
+
+       if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) {
+               boot_jump_linux(images, flag);
+               return 0;
+       }
+
+       boot_prep_linux(images);
+       boot_jump_linux(images, flag);
+       return 0;
+}
diff --git a/arch/arc/lib/relocate.c b/arch/arc/lib/relocate.c
new file mode 100644
index 0000000..710b792
--- /dev/null
+++ b/arch/arc/lib/relocate.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <elf.h>
+#include <asm/sections.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+extern char __text_end[];
+
+/*
+ * Base functionality is taken from x86 version with added ARC-specifics
+ */
+int do_elf_reloc_fixups(void)
+{
+       Elf32_Rela *re_src = (Elf32_Rela *)(&__rel_dyn_start);
+       Elf32_Rela *re_end = (Elf32_Rela *)(&__rel_dyn_end);
+
+       Elf32_Addr *offset_ptr_rom, *last_offset = NULL;
+       Elf32_Addr *offset_ptr_ram;
+
+       do {
+               /* Get the location from the relocation entry */
+               offset_ptr_rom = (Elf32_Addr *)re_src->r_offset;
+
+               /* Check that the location of the relocation is in .text */
+               if (offset_ptr_rom >= (Elf32_Addr *)CONFIG_SYS_TEXT_BASE &&
+                   offset_ptr_rom > last_offset) {
+                       unsigned int val;
+                       /* Switch to the in-RAM version */
+                       offset_ptr_ram = (Elf32_Addr *)((ulong)offset_ptr_rom +
+                                                       gd->reloc_off);
+
+                       /*
+                        * Use "memcpy" because target location might be
+                        * 16-bit aligned on ARC so we may need to read
+                        * byte-by-byte. On attempt to read entire word by
+                        * CPU throws an exception
+                        */
+                       memcpy(&val, offset_ptr_ram, sizeof(int));
+
+                       /* If location in ".text" section swap value */
+                       if ((unsigned int)offset_ptr_rom <
+                           (unsigned int)&__text_end)
+                               val = (val << 16) | (val >> 16);
+
+                       /* Check that the target points into .text */
+                       if (val >= CONFIG_SYS_TEXT_BASE && val <=
+                           (unsigned int)&__bss_end) {
+                               val += gd->reloc_off;
+                               /* If location in ".text" section swap value */
+                               if ((unsigned int)offset_ptr_rom <
+                                   (unsigned int)&__text_end)
+                                       val = (val << 16) | (val >> 16);
+                               memcpy(offset_ptr_ram, &val, sizeof(int));
+                       } else {
+                               debug("   %p: rom reloc %x, ram %p, value %x, 
limit %x\n",
+                                     re_src, re_src->r_offset, offset_ptr_ram,
+                                     val, (unsigned int)&__bss_end);
+                       }
+               } else {
+                       debug("   %p: rom reloc %x, last %p\n", re_src,
+                             re_src->r_offset, last_offset);
+               }
+               last_offset = offset_ptr_rom;
+
+       } while (++re_src < re_end);
+
+       return 0;
+}
diff --git a/arch/arc/lib/sections.c b/arch/arc/lib/sections.c
new file mode 100644
index 0000000..b0b46a4
--- /dev/null
+++ b/arch/arc/lib/sections.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+/*
+ * For some reason linker sets linker-generated symbols to zero in PIE mode.
+ * A work-around is substitution of linker-generated symbols with
+ * compiler-generated symbols which are properly handled by linker in PAE mode.
+ */
+
+char __bss_start[0] __attribute__((section(".__bss_start")));
+char __bss_end[0] __attribute__((section(".__bss_end")));
+char __image_copy_start[0] __attribute__((section(".__image_copy_start")));
+char __image_copy_end[0] __attribute__((section(".__image_copy_end")));
+char __rel_dyn_start[0] __attribute__((section(".__rel_dyn_start")));
+char __rel_dyn_end[0] __attribute__((section(".__rel_dyn_end")));
+char __text_start[0] __attribute__((section(".__text_start")));
+char __text_end[0] __attribute__((section(".__text_end")));
+char __init_end[0] __attribute__((section(".__init_end")));
-- 
1.8.5.3

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

Reply via email to