diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/i386/include/asm/global_data.h | 12 | ||||
-rw-r--r-- | arch/i386/lib/board.c | 111 |
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); |