summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/i386/include/asm/global_data.h12
-rw-r--r--arch/i386/lib/board.c111
2 files changed, 74 insertions, 49 deletions
diff --git a/arch/i386/include/asm/global_data.h b/arch/i386/include/asm/global_data.h
index cd067f5..f8a16d6 100644
--- a/arch/i386/include/asm/global_data.h
+++ b/arch/i386/include/asm/global_data.h
@@ -46,6 +46,8 @@ typedef struct global_data {
unsigned long env_valid; /* Checksum of Environment valid? */
unsigned long cpu_clk; /* CPU clock in Hz! */
unsigned long bus_clk;
+ unsigned long relocaddr; /* Start address of U-Boot in RAM */
+ unsigned long start_addr_sp; /* start_addr_stackpointer */
phys_size_t ram_size; /* RAM size */
unsigned long reset_status; /* reset status register at boot */
void **jt; /* jump table */
@@ -67,11 +69,13 @@ extern gd_t *gd;
#define GD_ENV_VALID 7
#define GD_CPU_CLK 8
#define GD_BUS_CLK 9
-#define GD_RAM_SIZE 10
-#define GD_RESET_STATUS 11
-#define GD_JT 12
+#define GD_RELOC_ADDR 10
+#define GD_START_ADDR_SP 11
+#define GD_RAM_SIZE 12
+#define GD_RESET_STATUS 13
+#define GD_JT 14
-#define GD_SIZE 13
+#define GD_SIZE 15
/*
* Global Data Flags
diff --git a/arch/i386/lib/board.c b/arch/i386/lib/board.c
index 8ec0446..c13efc8 100644
--- a/arch/i386/lib/board.c
+++ b/arch/i386/lib/board.c
@@ -170,30 +170,71 @@ init_fnc_t *init_sequence[] = {
gd_t *gd;
-/*
- * Load U-Boot into RAM, initialize BSS, perform relocation adjustments
- */
-void board_init_f(ulong boot_flags)
+static int calculate_relocation_address(void)
{
void *text_start = &__text_start;
- void *data_end = &__data_end;
- void *rel_dyn_start = &__rel_dyn_start;
- void *rel_dyn_end = &__rel_dyn_end;
+ void *bss_end = &__bss_end;
+ void *dest_addr;
+ ulong rel_offset;
+
+ /* Calculate destination RAM Address and relocation offset */
+ dest_addr = (void *)gd->ram_size;
+ dest_addr -= CONFIG_SYS_STACK_SIZE;
+ dest_addr -= (bss_end - text_start);
+ rel_offset = dest_addr - text_start;
+
+ gd->start_addr_sp = gd->ram_size;
+ gd->relocaddr = (ulong)dest_addr;
+ gd->reloc_off = rel_offset;
+
+ return 0;
+}
+
+static int copy_uboot_to_ram(void)
+{
+ ulong *dst_addr = (ulong *)gd->relocaddr;
+ ulong *src_addr = (ulong *)&__text_start;
+ ulong *end_addr = (ulong *)&__data_end;
+
+ while (src_addr < end_addr)
+ *dst_addr++ = *src_addr++;
+
+ return 0;
+}
+
+static int clear_bss(void)
+{
void *bss_start = &__bss_start;
void *bss_end = &__bss_end;
- ulong *dst_addr;
- ulong *src_addr;
- ulong *end_addr;
+ ulong *dst_addr = (ulong *)(bss_start + gd->reloc_off);
+ ulong *end_addr = (ulong *)(bss_end + gd->reloc_off);;
- void *addr_sp;
- void *dest_addr;
- ulong rel_offset;
- Elf32_Rel *re_src;
- Elf32_Rel *re_end;
+ while (dst_addr < end_addr)
+ *dst_addr++ = 0x00000000;
+
+ return 0;
+}
- gd->flags = boot_flags;
+static int do_elf_reloc_fixups(void)
+{
+ Elf32_Rel *re_src = (Elf32_Rel *)(&__rel_dyn_start);
+ Elf32_Rel *re_end = (Elf32_Rel *)(&__rel_dyn_end);
+
+ do {
+ if (re_src->r_offset >= CONFIG_SYS_TEXT_BASE)
+ if (*(Elf32_Addr *)(re_src->r_offset + gd->reloc_off) >= CONFIG_SYS_TEXT_BASE)
+ *(Elf32_Addr *)(re_src->r_offset + gd->reloc_off) += gd->reloc_off;
+ } while (re_src++ < re_end);
+
+ return 0;
+}
+/*
+ * Load U-Boot into RAM, initialize BSS, perform relocation adjustments
+ */
+void board_init_f(ulong boot_flags)
+{
if (env_init() != 0)
hang();
@@ -209,12 +250,8 @@ void board_init_f(ulong boot_flags)
if (dram_init_f() != 0)
hang();
- /* Calculate destination RAM Address and relocation offset */
- dest_addr = (void *)gd->ram_size;
- addr_sp = dest_addr;
- dest_addr -= CONFIG_SYS_STACK_SIZE;
- dest_addr -= (bss_end - text_start);
- rel_offset = dest_addr - text_start;
+ if (calculate_relocation_address() != 0)
+ hang();
/* First stage CPU initialization */
if (cpu_init_f() != 0)
@@ -225,35 +262,19 @@ void board_init_f(ulong boot_flags)
hang();
/* Copy U-Boot into RAM */
- dst_addr = (ulong *)dest_addr;
- src_addr = (ulong *)(text_start + gd->load_off);
- end_addr = (ulong *)(data_end + gd->load_off);
-
- while (src_addr < end_addr)
- *dst_addr++ = *src_addr++;
-
- /* Clear BSS */
- dst_addr = (ulong *)(bss_start + rel_offset);
- end_addr = (ulong *)(bss_end + rel_offset);
-
- while (dst_addr < end_addr)
- *dst_addr++ = 0x00000000;
+ if (copy_uboot_to_ram() != 0)
+ hang();
- /* Perform relocation adjustments */
- re_src = (Elf32_Rel *)(rel_dyn_start + gd->load_off);
- re_end = (Elf32_Rel *)(rel_dyn_end + gd->load_off);
+ if (clear_bss() != 0)
+ hang();
- do {
- if (re_src->r_offset >= CONFIG_SYS_TEXT_BASE)
- if (*(Elf32_Addr *)(re_src->r_offset + rel_offset) >= CONFIG_SYS_TEXT_BASE)
- *(Elf32_Addr *)(re_src->r_offset + rel_offset) += rel_offset;
- } while (re_src++ < re_end);
+ if (do_elf_reloc_fixups() != 0)
+ hang();
- gd->reloc_off = rel_offset;
gd->flags |= GD_FLG_RELOC;
/* Enter the relocated U-Boot! */
- relocate_code((ulong)addr_sp, gd, (ulong)dest_addr);
+ relocate_code(gd->start_addr_sp, gd, gd->relocaddr);
/* NOTREACHED - relocate_code() does not return */
while(1);