diff options
| -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 cd067f548..f8a16d646 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 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); |