diff options
| author | Graeme Russ <graeme.russ@gmail.com> | 2009-11-24 20:04:21 +1100 | 
|---|---|---|
| committer | Wolfgang Denk <wd@denx.de> | 2009-12-05 01:05:39 +0100 | 
| commit | 1c409bc7101a24ecd47a13a4e851845d66dc23ce (patch) | |
| tree | 0ecc055ef81130abc919cc2123974304dfa75b9e | |
| parent | cabe5794803fbe18bedac2d9c7f2417a0fa95ec1 (diff) | |
| download | olio-uboot-2014.01-1c409bc7101a24ecd47a13a4e851845d66dc23ce.tar.xz olio-uboot-2014.01-1c409bc7101a24ecd47a13a4e851845d66dc23ce.zip | |
i386: Final Relocation
Signed-off-by: Graeme Russ <graeme.russ@gmail.com>
| -rw-r--r-- | board/eNET/config.mk | 2 | ||||
| -rw-r--r-- | board/eNET/eNET.c | 11 | ||||
| -rw-r--r-- | board/eNET/u-boot.lds | 34 | ||||
| -rw-r--r-- | cpu/i386/cpu.c | 8 | ||||
| -rw-r--r-- | cpu/i386/interrupts.c | 4 | ||||
| -rw-r--r-- | cpu/i386/start.S | 130 | ||||
| -rw-r--r-- | include/asm-i386/u-boot-i386.h | 14 | ||||
| -rw-r--r-- | include/configs/eNET.h | 2 | ||||
| -rw-r--r-- | lib_i386/board.c | 157 | ||||
| -rw-r--r-- | lib_i386/interrupts.c | 4 | ||||
| -rw-r--r-- | lib_i386/timer.c | 2 | 
11 files changed, 157 insertions, 211 deletions
| diff --git a/board/eNET/config.mk b/board/eNET/config.mk index c9703ea8e..5c64804fb 100644 --- a/board/eNET/config.mk +++ b/board/eNET/config.mk @@ -23,4 +23,6 @@  TEXT_BASE = 0x38040000  CFLAGS_dlmalloc.o += -Wa,--no-warn -fno-strict-aliasing +PLATFORM_RELFLAGS += -fvisibility=hidden  PLATFORM_CPPFLAGS += -fno-dwarf2-cfi-asm +PLATFORM_LDFLAGS += -pic --emit-relocs -Bsymbolic -Bsymbolic-functions diff --git a/board/eNET/eNET.c b/board/eNET/eNET.c index 29cf29518..6d0b15a0f 100644 --- a/board/eNET/eNET.c +++ b/board/eNET/eNET.c @@ -47,7 +47,6 @@ void init_sc520_enet (void)  {  	/* Set CPU Speed to 100MHz */  	sc520_mmcr->cpuctl = 0x01; -	gd->cpu_clk = 100000000;  	/* wait at least one millisecond */  	asm("movl	$0x2000,%%ecx\n" @@ -67,7 +66,7 @@ void init_sc520_enet (void)  /*   * Miscellaneous platform dependent initializations   */ -int board_init(void) +int board_early_init_f(void)  {  	init_sc520_enet(); @@ -117,6 +116,14 @@ int board_init(void)  	sc520_mmcr->sysarbctl = 0x06;  	sc520_mmcr->sysarbmenb = 0x0003; +	return 0; +} + +int board_early_init_r(void) +{ +	/* CPU Speed to 100MHz */ +	gd->cpu_clk = 100000000; +  	/* Crystal is 33.000MHz */  	gd->bus_clk = 33000000; diff --git a/board/eNET/u-boot.lds b/board/eNET/u-boot.lds index 4ea424d32..0d740215c 100644 --- a/board/eNET/u-boot.lds +++ b/board/eNET/u-boot.lds @@ -28,28 +28,48 @@ ENTRY(_start)  SECTIONS  {  	. = 0x38040000;		/* Location of bootcode in flash */ +	_i386boot_text_start = .;  	.text  : { *(.text); }  	. = ALIGN(4);  	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }  	_i386boot_text_size = SIZEOF(.text) + SIZEOF(.rodata); +	. = ALIGN(4); + +	.data : { *(.data) } +	. = ALIGN(4); + +	.interp : { *(.interp) } +	. = ALIGN(4); + +	.dynsym : { *(.dynsym) } +	. = ALIGN(4); -	. = 0x03FF0000;		/* Ram data segment to use */ -	_i386boot_romdata_dest = ABSOLUTE(.); -	.data : AT ( LOADADDR(.rodata) + SIZEOF(.rodata) ) { *(.data) } -	_i386boot_romdata_start = LOADADDR(.data); +	.dynstr : { *(.dynstr) } +	. = ALIGN(4); + +	.hash : { *(.hash) } +	. = ALIGN(4); +	.got : { *(.got) }  	. = ALIGN(4); -	.got : AT ( LOADADDR(.data) + SIZEOF(.data) ) { *(.got) } +	.got.plt : { *(.got.plt) }  	. = ALIGN(4); + +	.dynamic (NOLOAD) : { *(.dynamic) } +	. = ALIGN(4); +  	__u_boot_cmd_start = .;  	.u_boot_cmd : { *(.u_boot_cmd) } +	. = ALIGN(4);  	__u_boot_cmd_end = .;  	_i386boot_cmd_start = LOADADDR(.u_boot_cmd); -	_i386boot_romdata_size = SIZEOF(.data) + SIZEOF(.got) + SIZEOF(.u_boot_cmd); +	_i386boot_rel_dyn_start = .; +	.rel.dyn : { *(.rel.dyn) } +	_i386boot_rel_dyn_end = .;  	. = ALIGN(4);  	_i386boot_bss_start = ABSOLUTE(.); @@ -57,7 +77,7 @@ SECTIONS  	_i386boot_bss_size = SIZEOF(.bss);  	/* 16bit realmode trampoline code */ -	.realmode 0x7c0 : AT ( LOADADDR(.got) + SIZEOF(.got) + SIZEOF(.u_boot_cmd)) { *(.realmode) } +	.realmode 0x7c0 : AT ( LOADADDR(.rel.dyn) + SIZEOF(.rel.dyn) ) { *(.realmode) }  	_i386boot_realmode = LOADADDR(.realmode);  	_i386boot_realmode_size = SIZEOF(.realmode); diff --git a/cpu/i386/cpu.c b/cpu/i386/cpu.c index 4b681057a..3010519e7 100644 --- a/cpu/i386/cpu.c +++ b/cpu/i386/cpu.c @@ -37,7 +37,7 @@  #include <command.h>  #include <asm/interrupt.h> -int cpu_init(void) +int cpu_init_f(void)  {  	/* initialize FPU, reset EM, set MP and NE */  	asm ("fninit\n" \ @@ -46,9 +46,13 @@ int cpu_init(void)  	     "orl  $0x22, %eax\n" \  	     "movl %eax, %cr0\n" ); +	return 0; +} + +int cpu_init_r(void) +{  	/* Initialize core interrupt and exception functionality of CPU */  	cpu_init_interrupts (); -  	return 0;  } diff --git a/cpu/i386/interrupts.c b/cpu/i386/interrupts.c index cbf1c41e1..4b5743719 100644 --- a/cpu/i386/interrupts.c +++ b/cpu/i386/interrupts.c @@ -63,8 +63,8 @@ static inline void load_idt(const struct desc_ptr *dtr)  void set_vector(u8 intnum, void *routine)  { -	idt[intnum].base_high = (u16)((u32)(routine + gd->reloc_off) >> 16); -	idt[intnum].base_low = (u16)((u32)(routine + gd->reloc_off) & 0xffff); +	idt[intnum].base_high = (u16)((u32)(routine) >> 16); +	idt[intnum].base_low = (u16)((u32)(routine) & 0xffff);  }  void irq_0(void); diff --git a/cpu/i386/start.S b/cpu/i386/start.S index 59089ef59..25d32e658 100644 --- a/cpu/i386/start.S +++ b/cpu/i386/start.S @@ -63,11 +63,8 @@ early_board_init_ret:  	jmp     mem_init  mem_init_ret: -	/* check ammount of configured memory -	 * (we need atleast bss start+bss size+stack size) */ -	movl	$_i386boot_bss_start, %ecx        /* BSS start */ -	addl	$_i386boot_bss_size, %ecx         /* BSS size */ -	addl	$CONFIG_SYS_STACK_SIZE, %ecx +	/* Check we have enough memory for stack */ +	movl	$CONFIG_SYS_STACK_SIZE, %ecx  	cmpl	%ecx, %eax  	jae	mem_ok @@ -78,6 +75,8 @@ mem_init_ret:  .progress0a:  	jmp	die  mem_ok: +	/* Set stack pointer to upper memory limit*/ +	movl    %eax, %esp  	/* indicate progress */  	movw	$0x02, %ax @@ -85,12 +84,7 @@ mem_ok:  	jmp	show_boot_progress_asm  .progress1: -	/* create a stack after the bss */ -	movl    $_i386boot_bss_start, %eax -	addl	$_i386boot_bss_size, %eax -	addl	$CONFIG_SYS_STACK_SIZE, %eax -	movl    %eax, %esp - +	/* Test the stack */  	pushl	$0  	popl	%eax  	cmpl	$0, %eax @@ -116,115 +110,19 @@ stack_ok:  	jmp	show_boot_progress_asm  .progress2: -	/* copy data section to ram, size must be 4-byte aligned */ -	movl	$_i386boot_romdata_dest, %edi	  /* destination address */ -	movl	$_i386boot_romdata_start, %esi	  /* source address */ -	movl	$_i386boot_romdata_size, %ecx     /* number of bytes to copy */ -	movl	%ecx, %eax -	andl	$3, %eax -	jnz	data_fail - -	shrl	$2, %ecx	                  /* copy 4 byte each time */ -	cld -	cmpl	$0, %ecx -	je	data_ok -data_segment: -	movsl -	loop	data_segment -	jmp	data_ok -data_fail: -	/* indicate (lack of) progress */ -	movw	$0x83, %ax -	movl	$.progress2a, %ebp -	jmp	show_boot_progress_asm -.progress2a: -	jmp	die - -data_ok: - -	/* indicate progress */ -	movw	$0x04, %ax -	movl	$.progress3, %ebp -	jmp	show_boot_progress_asm -.progress3: - -	/* clear bss section in ram, size must be 4-byte aligned  */ -	movl	$_i386boot_bss_start, %edi        /* MK_CHG BSS start */ -	movl	$_i386boot_bss_size, %ecx         /* BSS size */ -	movl	%ecx, %eax -	andl	$3, %eax -	jnz	bss_fail -	shrl	$2, %ecx	                  /* clear 4 byte each time */ -	cld -	cmpl	$0, %ecx -	je	bss_ok -bss: -	movl	$0, (%edi) -	add	$4, %edi -	loop	bss -	jmp	bss_ok - -bss_fail: -	/* indicate (lack of) progress */ -	movw	$0x84, %ax -	movl	$.progress3a, %ebp -	jmp	show_boot_progress_asm -.progress3a: -	jmp	die - -bss_ok: -#ifndef CONFIG_SKIP_RELOCATE_UBOOT -	/* indicate progress */ -	movw	$0x06, %ax -	movl	$.progress6, %ebp -	jmp	show_boot_progress_asm -.progress6: - -	/* copy text section to ram, size must be 4-byte aligned */ -	movl	$CONFIG_SYS_BL_START_RAM, %edi		/* destination address */ -	movl	$TEXT_BASE, %esi		/* source address */ -	movl	$_i386boot_text_size, %ecx	/* number of bytes to copy */ -	movl	%ecx, %eax -	andl	$3, %eax -	jz	text_copy			/* Already 4-byte aligned */ -	subl    $4, %eax			/* Add extra bytes to size */ -	addl	%eax, %ecx -text_copy: -	shrl	$2, %ecx			/* copy 4 byte each time */ -	cld -	cmpl	$0, %ecx -	je	text_ok -text_segment: -	movsl -	loop	text_segment -	jmp	text_ok -text_fail: -	/* indicate (lack of) progress */ -	movw	$0x86, %ax -	movl	$.progress5a, %ebp -	jmp	show_boot_progress_asm -.progress5a: -	jmp	die - -text_ok: -#endif  	wbinvd +	/* Get upper memory limit */ +	movl %esp, %ecx +	subl $CONFIG_SYS_STACK_SIZE, %ecx -	/* indicate progress */ -	movw	$0x05, %ax -	movl	$.progress4, %ebp -	jmp	show_boot_progress_asm -.progress4: +	/* Create a Stack Frame */ +	pushl %ebp +	movl %esp, %ebp -#ifndef CONFIG_SKIP_RELOCATE_UBOOT -	/* Jump to the RAM copy of start_i386boot */ -	movl	$start_i386boot, %ebp -	addl	$(CONFIG_SYS_BL_START_RAM - TEXT_BASE), %ebp -	call	*%ebp		/* Enter, U-boot! */ -#else -	call	start_i386boot  /* Enter, U-boot! */ -#endif +	/* stack_limit parameter */ +	pushl	%ecx +	call	board_init_f	/* Enter, U-boot! */  	/* indicate (lack of) progress */  	movw	$0x85, %ax diff --git a/include/asm-i386/u-boot-i386.h b/include/asm-i386/u-boot-i386.h index 1e8def77d..7c99c8c57 100644 --- a/include/asm-i386/u-boot-i386.h +++ b/include/asm-i386/u-boot-i386.h @@ -24,19 +24,9 @@  #ifndef _U_BOOT_I386_H_  #define _U_BOOT_I386_H_	1 -/* for the following variables, see start.S */ -extern ulong i386boot_start;	    /* code start (in flash) */ -extern ulong i386boot_end;	    /* code end (in flash) */ -extern ulong i386boot_romdata_start;/* datasegment in flash (also code+rodata end) */ -extern ulong i386boot_romdata_dest; /* data location segment in ram */ -extern ulong i386boot_romdata_size; /* size of data segment */ -extern ulong i386boot_bss_start;    /* bss start */ -extern ulong i386boot_bss_size;     /* bss size */ -extern ulong i386boot_stack_end;    /* first usable RAM address after bss and stack */ -extern ulong i386boot_ram_end;      /* end of ram */ -  /* cpu/.../cpu.c */ -int cpu_init(void); +int cpu_init_r(void); +int cpu_init_f(void);  /* cpu/.../timer.c */  void timer_isr(void *); diff --git a/include/configs/eNET.h b/include/configs/eNET.h index 0a8655086..6a68bf493 100644 --- a/include/configs/eNET.h +++ b/include/configs/eNET.h @@ -28,6 +28,8 @@  #ifndef __CONFIG_H  #define __CONFIG_H +#define CONFIG_RELOC_FIXUP_WORKS +  /*   * Stuff still to be dealt with -   */ diff --git a/lib_i386/board.c b/lib_i386/board.c index 44fa0e31a..f3b634855 100644 --- a/lib_i386/board.c +++ b/lib_i386/board.c @@ -38,6 +38,7 @@  #include <net.h>  #include <ide.h>  #include <asm/u-boot-i386.h> +#include <elf.h>  #ifdef CONFIG_BITBANGMII  #include <miiphy.h> @@ -45,41 +46,16 @@  DECLARE_GLOBAL_DATA_PTR; -extern long _i386boot_start; -extern long _i386boot_end; -extern long _i386boot_romdata_start; -extern long _i386boot_romdata_dest; -extern long _i386boot_romdata_size; -extern long _i386boot_bss_start; -extern long _i386boot_bss_size; - -/* The symbols defined by the linker script becomes pointers - * which is somewhat inconveient ... */ -ulong i386boot_start         = (ulong)&_i386boot_start;         /* code start (in flash) defined in start.S */ -ulong i386boot_end           = (ulong)&_i386boot_end;	        /* code end (in flash) */ -ulong i386boot_romdata_start = (ulong)&_i386boot_romdata_start; /* datasegment in flash (also code+rodata end) */ -ulong i386boot_romdata_dest  = (ulong)&_i386boot_romdata_dest;  /* data location segment in ram */ -ulong i386boot_romdata_size  = (ulong)&_i386boot_romdata_size;  /* size of data segment */ -ulong i386boot_bss_start     = (ulong)&_i386boot_bss_start;     /* bss start */ -ulong i386boot_bss_size      = (ulong)&_i386boot_bss_size;      /* bss size */ - +/* Exports from the Linker Script */ +extern ulong _i386boot_text_start; +extern ulong _i386boot_rel_dyn_start; +extern ulong _i386boot_rel_dyn_end; +extern ulong _i386boot_bss_start; +extern ulong _i386boot_bss_size; +void ram_bootstrap (void *);  const char version_string[] =  	U_BOOT_VERSION" (" U_BOOT_DATE " - " U_BOOT_TIME ")"; -static int heap_init(void) -{ -	/* start malloc area right after the stack */ -	ulong start = i386boot_bss_start + i386boot_bss_size + -			CONFIG_SYS_STACK_SIZE; - -	/* 4-byte aligned */ -	start = (start+3)&~3; - -	mem_malloc_init(start, CONFIG_SYS_MALLOC_LEN); - -	return 0; -} -  /************************************************************************   * Init Utilities							*   ************************************************************************ @@ -103,6 +79,7 @@ static int display_banner (void)  {  	printf ("\n\n%s\n\n", version_string); +/*  	printf ("U-Boot code: %08lX -> %08lX  data: %08lX -> %08lX\n"  		"        BSS: %08lX -> %08lX stack: %08lX -> %08lX\n",  		i386boot_start, i386boot_romdata_start-1, @@ -111,6 +88,7 @@ static int display_banner (void)  		i386boot_bss_start+i386boot_bss_size,  		i386boot_bss_start+i386boot_bss_size+CONFIG_SYS_STACK_SIZE-1); +*/  	return (0);  } @@ -142,7 +120,6 @@ static void display_flash_config (ulong size)  	print_size (size, "\n");  } -  /*   * Breath some life into the board...   * @@ -154,6 +131,7 @@ static void display_flash_config (ulong size)   * can relocate the monitor code to RAM.   */ +  /*   * All attempts to come up with a "common" initialization sequence   * that works for all boards and architectures failed: some of the @@ -169,13 +147,12 @@ static void display_flash_config (ulong size)  typedef int (init_fnc_t) (void);  init_fnc_t *init_sequence[] = { -	cpu_init,		/* basic cpu dependent setup */ -	board_init,		/* basic board dependent setup */ +	serial_init, +	cpu_init_r,		/* basic cpu dependent setup */ +	board_early_init_r,	/* basic board dependent setup */  	dram_init,		/* configure available RAM banks */ -	heap_init,		/* dependant on dram_init */  	interrupt_init,		/* set up exceptions */  	timer_init, -	serial_init,  	env_init,		/* initialize environment */  	init_baudrate,		/* initialze baudrate settings */  	serial_init,		/* serial communications setup */ @@ -187,21 +164,86 @@ init_fnc_t *init_sequence[] = {  gd_t *gd; -void start_i386boot (void) +/* + * Load U-Boot into RAM, initialize BSS, perform relocation adjustments + */ +void board_init_f (ulong stack_limit) +{ +	void *text_start = &_i386boot_text_start; +	void *u_boot_cmd_end = &__u_boot_cmd_end; +	Elf32_Rel *rel_dyn_start = (Elf32_Rel *)&_i386boot_rel_dyn_start; +	Elf32_Rel *rel_dyn_end = (Elf32_Rel *)&_i386boot_rel_dyn_end; +	void *bss_start = &_i386boot_bss_start; +	void *bss_size = &_i386boot_bss_size; + +	size_t uboot_size; +	void *ram_start; +	ulong rel_offset; +	Elf32_Rel *re; + +	void (*start_func)(void *); + +	/* compiler optimization barrier needed for GCC >= 3.4 */ +	__asm__ __volatile__("": : :"memory"); + +	uboot_size = (size_t)u_boot_cmd_end - (size_t)text_start; +	ram_start  = (void *)stack_limit - (uboot_size + (ulong)bss_size); +	rel_offset = text_start - ram_start; +	start_func = ram_bootstrap - rel_offset; + +	/* First stage CPU initialization */ +	if (cpu_init_f() != 0) +		hang(); + +	/* First stage Board initialization */ +	if (board_early_init_f() != 0) +		hang(); + +	/* Copy U-Boot into RAM */ +	memcpy(ram_start, text_start, (size_t)uboot_size); + +	/* Clear BSS */ +	memset(bss_start - rel_offset,	0, (size_t)bss_size); + +	/* Perform relocation adjustments */ +	for (re = rel_dyn_start; re < rel_dyn_end; re++) +	{ +		if (re->r_offset >= TEXT_BASE) +			if (*(ulong *)re->r_offset >= TEXT_BASE) +				*(ulong *)(re->r_offset - rel_offset) -= (Elf32_Addr)rel_offset; +	} + +	start_func(ram_start); + +	/* NOTREACHED - relocate_code() does not return */ +	while(1); +} + +/* + * All attempts to jump straight from board_init_f() to board_init_r() + * have failed, hence this special 'bootstrap' function. + */ +void ram_bootstrap (void *ram_start) +{ +	static gd_t gd_data; + +	/* compiler optimization barrier needed for GCC >= 3.4 */ +	__asm__ __volatile__("": : :"memory"); + +	board_init_r(&gd_data, (ulong)ram_start); +} + +void board_init_r(gd_t *id, ulong ram_start)  {  	char *s;  	int i;  	ulong size; -	static gd_t gd_data;  	static bd_t bd_data;  	init_fnc_t **init_fnc_ptr; -#ifndef CONFIG_SKIP_RELOCATE_UBOOT -	cmd_tbl_t *p; -#endif  	show_boot_progress(0x21); -	gd = &gd_data; +	gd = id;  	/* compiler optimization barrier needed for GCC >= 3.4 */  	__asm__ __volatile__("": : :"memory"); @@ -212,10 +254,11 @@ void start_i386boot (void)  	gd->baudrate =  CONFIG_BAUDRATE; -#ifndef CONFIG_SKIP_RELOCATE_UBOOT -	/* Need to set relocation offset here for interrupt initialization */ -	gd->reloc_off =  CONFIG_SYS_BL_START_RAM - TEXT_BASE; -#endif +	gd->flags |= GD_FLG_RELOC;	/* tell others: relocation done */ + +	mem_malloc_init((((ulong)ram_start - CONFIG_SYS_MALLOC_LEN)+3)&~3, +			CONFIG_SYS_MALLOC_LEN); +  	for (init_fnc_ptr = init_sequence, i=0; *init_fnc_ptr; ++init_fnc_ptr, i++) {  		show_boot_progress(0xa130|i); @@ -225,26 +268,6 @@ void start_i386boot (void)  	}  	show_boot_progress(0x23); -#ifndef CONFIG_SKIP_RELOCATE_UBOOT -	for (p = &__u_boot_cmd_start; p != &__u_boot_cmd_end; p++) { -		ulong addr; -		addr = (ulong) (p->cmd) + gd->reloc_off; -		p->cmd = (int (*)(struct cmd_tbl_s *, int, int, char *[]))addr; -		addr = (ulong)(p->name) + gd->reloc_off; -		p->name = (char *)addr; - -		if (p->usage != NULL) { -			addr = (ulong)(p->usage) + gd->reloc_off; -			p->usage = (char *)addr; -		} -	#ifdef	CONFIG_SYS_LONGHELP -		if (p->help != NULL) { -			addr = (ulong)(p->help) + gd->reloc_off; -			p->help = (char *)addr; -		} -	#endif -	} -#endif  	/* configure available FLASH banks */  	size = flash_init();  	display_flash_config(size); diff --git a/lib_i386/interrupts.c b/lib_i386/interrupts.c index efbad7220..51def5995 100644 --- a/lib_i386/interrupts.c +++ b/lib_i386/interrupts.c @@ -70,12 +70,12 @@ void irq_install_handler(int irq, interrupt_handler_t *handler, void *arg)  	if (irq_handlers[irq].handler != NULL)  		printf("irq_install_handler: 0x%08lx replacing 0x%08lx\n", -		       (ulong) handler + gd->reloc_off, +		       (ulong) handler,  		       (ulong) irq_handlers[irq].handler);  	status = disable_interrupts (); -	irq_handlers[irq].handler = handler + gd->reloc_off; +	irq_handlers[irq].handler = handler;  	irq_handlers[irq].arg = arg;  	irq_handlers[irq].count = 0; diff --git a/lib_i386/timer.c b/lib_i386/timer.c index 58a0212ad..5cb1f54fb 100644 --- a/lib_i386/timer.c +++ b/lib_i386/timer.c @@ -51,7 +51,7 @@ int register_timer_isr (timer_fnc_t *isr_func)  	if (new_func == NULL)  		return 1; -	new_func->isr_func = isr_func + gd->reloc_off; +	new_func->isr_func = isr_func;  	new_func->next = NULL;  	/* |