diff options
Diffstat (limited to 'arch/i386/lib/board.c')
| -rw-r--r-- | arch/i386/lib/board.c | 111 | 
1 files changed, 66 insertions, 45 deletions
| diff --git a/arch/i386/lib/board.c b/arch/i386/lib/board.c index 8ec04462b..c13efc83f 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); |