--- board/eNET/config.mk | 2 + board/eNET/eNET.c | 17 ++++-- board/eNET/u-boot.lds | 49 +++++++++++---- cpu/i386/cpu.c | 12 ++- cpu/i386/interrupts.c | 4 +- cpu/i386/start.S | 125 +++--------------------------------- include/asm-i386/u-boot-i386.h | 10 +++- lib_i386/Makefile | 1 + lib_i386/board.c | 108 ++++++++++++++++--------------- lib_i386/elf_reloc.c | 139 ++++++++++++++++++++++++++++++++++++++++ lib_i386/interrupts.c | 4 +- lib_i386/realmode.c | 4 +- lib_i386/timer.c | 2 +- 13 files changed, 279 insertions(+), 198 deletions(-) create mode 100644 lib_i386/elf_reloc.c
diff --git a/board/eNET/config.mk b/board/eNET/config.mk index a763841..cbec0a8 100644 --- a/board/eNET/config.mk +++ b/board/eNET/config.mk @@ -22,3 +22,5 @@ # TEXT_BASE = 0x38040000 +PLATFORM_RELFLAGS += -fpic +PLATFORM_LDFLAGS += -pic diff --git a/board/eNET/eNET.c b/board/eNET/eNET.c index 29cf295..baf7c95 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,12 +116,20 @@ int board_init(void) sc520_mmcr->sysarbctl = 0x06; sc520_mmcr->sysarbmenb = 0x0003; - /* Crystal is 33.000MHz */ - gd->bus_clk = 33000000; - return 0; } +int board_early_init_r(void) +{ + /* CPU Speed to 100MHz */ + gd->cpu_clk = 100000000; + + /* Crystal is 33.000MHz */ + gd->bus_clk = 33000000; + + return 0; +} + int dram_init(void) { init_sc520_dram(); diff --git a/board/eNET/u-boot.lds b/board/eNET/u-boot.lds index 832d101..1cd6056 100644 --- a/board/eNET/u-boot.lds +++ b/board/eNET/u-boot.lds @@ -28,39 +28,64 @@ ENTRY(_start) SECTIONS { . = 0x38040000; /* Location of bootcode in flash */ + _i386boot_rom_copy_start = .; .text : { *(.text); } . = ALIGN(4); .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + . = ALIGN(4); .eh_frame : { *(.eh_frame) } + . = ALIGN(4); - _i386boot_text_size = SIZEOF(.text) + SIZEOF(.rodata); - - . = 0x03FF0000; /* Ram data segment to use */ - _i386boot_romdata_dest = ABSOLUTE(.); - .data : AT ( LOADADDR(.eh_frame) + SIZEOF(.eh_frame) ) { *(.data) } -/* .data : { *(.data) } */ - _i386boot_romdata_start = LOADADDR(.data); + .data : { *(.data) } + . = ALIGN(4); + + .got : { *(.got) } + . = ALIGN(4); + _i386boot_got_start = LOADADDR(.got); + _i386boot_got_end = LOADADDR(.got) + SIZEOF(.got) - 1; + .got.plt : { *(.got.plt) } . = ALIGN(4); - .got : AT ( LOADADDR(.data) + SIZEOF(.data) ) { *(.got) } - + _i386boot_got_plt_start = LOADADDR(.got.plt); + _i386boot_got_plt_end = LOADADDR(.got.plt) + SIZEOF(.got.plt) - 1; + + .rel.got : { *(.rel.got) } . = ALIGN(4); + _i386boot_rel_got_start = LOADADDR(.rel.got); + _i386boot_rel_got_end = LOADADDR(.rel.got) + SIZEOF(.rel.got) - 1; + + .rel.dyn : { *(.rel.dyn) } + . = ALIGN(4); + _i386boot_rel_dyn_start = LOADADDR(.rel.dyn); + _i386boot_rel_dyn_end = LOADADDR(.rel.dyn) + SIZEOF(.rel.dyn) - 1; + + .dynsym : { *(.dynsym) } + . = ALIGN(4); + _i386boot_dynsym_start = LOADADDR(.dynsym); + _i386boot_dynsym_end = LOADADDR(.dynsym) + SIZEOF(.dynsym) - 1; + + .dynamic : { *(.dynamic) } + . = ALIGN(4); + _i386boot_dynamic_start = LOADADDR(.dynamic); + _i386boot_dynamic_end = LOADADDR(.dynamic) + SIZEOF(.dynamic) - 1; + __u_boot_cmd_start = .; .u_boot_cmd : { *(.u_boot_cmd) } __u_boot_cmd_end = .; _i386boot_cmd_start = LOADADDR(.u_boot_cmd); + . = ALIGN(4); - _i386boot_romdata_size = SIZEOF(.data) + SIZEOF(.got) + SIZEOF(.u_boot_cmd); + _i386boot_rom_copy_end = .; - . = ALIGN(4); _i386boot_bss_start = ABSOLUTE(.); .bss (NOLOAD) : { *(.bss) } + . = ALIGN(4); _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(.u_boot_cmd) + SIZEOF(.u_boot_cmd) ) { *(.realmode) } _i386boot_realmode = LOADADDR(.realmode); _i386boot_realmode_size = SIZEOF(.realmode); diff --git a/cpu/i386/cpu.c b/cpu/i386/cpu.c index 8baf37d..685f6c1 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,12 +46,16 @@ int cpu_init(void) "orl $0x22, %eax\n" \ "movl %eax, %cr0\n" ); - /* Initialize core interrupt and exception functionality of CPU */ - cpu_init_interrupts (); - return 0; } +int cpu_init_r(void) +{ + /* Initialize core interrupt and exception functionality of CPU */ + cpu_init_interrupts (); + return 0; +} + int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { printf ("resetting ...\n"); diff --git a/cpu/i386/interrupts.c b/cpu/i386/interrupts.c index f4a297f..47bbdde 100644 --- a/cpu/i386/interrupts.c +++ b/cpu/i386/interrupts.c @@ -58,8 +58,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 59089ef..320a607 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: + /* Keep a copy of the memory size (needed later) */ + movl %eax, %ecx /* indicate progress */ movw $0x02, %ax @@ -85,12 +84,11 @@ 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 + /* Create the stack at upper memory limit*/ + subl $0x100, %eax movl %eax, %esp + /* Test the stack */ pushl $0 popl %eax cmpl $0, %eax @@ -116,115 +114,10 @@ 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 - - /* indicate progress */ - movw $0x05, %ax - movl $.progress4, %ebp - jmp show_boot_progress_asm -.progress4: - -#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 + pushl %ecx /* mem_size parameter */ + 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 dfec307..823e5ce 100644 --- a/include/asm-i386/u-boot-i386.h +++ b/include/asm-i386/u-boot-i386.h @@ -24,6 +24,8 @@ #ifndef _U_BOOT_I386_H_ #define _U_BOOT_I386_H_ 1 +#include <elf.h> + /* for the following variables, see start.S */ extern ulong i386boot_start; /* code start (in flash) */ extern ulong i386boot_end; /* code end (in flash) */ @@ -42,7 +44,8 @@ extern ulong i386boot_bios_size; /* size of BIOS emulation code */ /* cpu/.../cpu.c */ -int cpu_init(void); +int cpu_init_r(void); +int cpu_init_f(void); /* cpu/.../timer.c */ void timer_isr(void *); @@ -65,6 +68,11 @@ u32 isa_map_rom(u32 bus_addr, int size); /* lib_i386/... */ int video_bios_init(void); int video_init(void); +void elf_relocate(ulong rel_offset); +void reloc_fixup_elf32_dyn (Elf32_Dyn *start, Elf32_Dyn *end, ulong offset); +void reloc_fixup_elf32_sym (Elf32_Sym *start, Elf32_Sym *end, ulong offset); +void reloc_fixup_elf32_rel (Elf32_Rel *start, Elf32_Rel *end, ulong offset); +void reloc_fixup_elf32_rela (Elf32_Rela *start, Elf32_Rela *end, ulong offset); #endif /* _U_BOOT_I386_H_ */ diff --git a/lib_i386/Makefile b/lib_i386/Makefile index 9838506..1532579 100644 --- a/lib_i386/Makefile +++ b/lib_i386/Makefile @@ -32,6 +32,7 @@ SOBJS-y += realmode_switch.o COBJS-y += bios_setup.o COBJS-y += board.o COBJS-y += bootm.o +COBJS-y += elf_reloc.o COBJS-y += interrupts.o COBJS-$(CONFIG_SYS_PCAT_INTERRUPTS) += pcat_interrupts.o COBJS-$(CONFIG_SYS_GENERIC_TIMER) += pcat_timer.o diff --git a/lib_i386/board.c b/lib_i386/board.c index 39a3099..4c77a9f 100644 --- a/lib_i386/board.c +++ b/lib_i386/board.c @@ -41,13 +41,11 @@ 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; +extern long _i386boot_rom_copy_start; +extern long _i386boot_rom_copy_end; extern long _i386boot_realmode; extern long _i386boot_realmode_size; @@ -56,11 +54,7 @@ extern long _i386boot_bios_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 */ @@ -73,19 +67,7 @@ ulong i386boot_bios_size = (ulong)&_i386boot_bios_size; /* size of BIOS 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; -} +void start_i386boot (ulong); /************************************************************************ * Init Utilities * @@ -110,6 +92,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, @@ -117,7 +100,7 @@ static int display_banner (void) i386boot_bss_start, i386boot_bss_start+i386boot_bss_size-1, i386boot_bss_start+i386boot_bss_size, i386boot_bss_start+i386boot_bss_size+CONFIG_SYS_STACK_SIZE-1); - +*/ return (0); } @@ -160,6 +143,50 @@ static void display_flash_config (ulong size) * its main purpose is to initialize the RAM so that we * can relocate the monitor code to RAM. */ +void board_init_f (ulong mem_size) +{ + ulong i386boot_rom_copy_start = (ulong)&_i386boot_rom_copy_start; + ulong i386boot_rom_copy_end = (ulong)&_i386boot_rom_copy_end; + ulong i386boot_bss_start = (ulong)&_i386boot_bss_start; + ulong i386boot_bss_size = (ulong)&_i386boot_bss_size; + + ulong uboot_rom_size = i386boot_rom_copy_end - i386boot_rom_copy_start; + + ulong ram_start = mem_size - + (CONFIG_SYS_STACK_SIZE + + uboot_rom_size + + i386boot_bss_size); + + ulong rel_offset = CONFIG_SYS_MONITOR_BASE - ram_start; + + void (*start_func)(ulong) = start_i386boot - rel_offset; + + /* compiler optimization barrier needed for GCC >= 3.4 */ + __asm__ __volatile__("": : :"memory"); + + /* First stage CPU initialization */ + if (cpu_init_f() != 0) + hang(); + + /* First stage Board initialization */ + if (board_early_init_f() != 0) + hang(); + + memcpy((void *)ram_start, + (void *)CONFIG_SYS_MONITOR_BASE, + uboot_rom_size); + + memset ((void *) i386boot_bss_start - rel_offset, + 0, + i386boot_bss_size); + + elf_relocate(rel_offset); + + start_func(ram_start); + + /* NOTREACHED - relocate_code() does not return */ + while(1); +} /* * All attempts to come up with a "common" initialization sequence @@ -176,10 +203,9 @@ 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 */ + 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, @@ -194,7 +220,7 @@ init_fnc_t *init_sequence[] = { gd_t *gd; -void start_i386boot (void) +void start_i386boot (ulong ram_start) { char *s; int i; @@ -203,9 +229,6 @@ void start_i386boot (void) 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; @@ -219,10 +242,9 @@ 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 + mem_malloc_init(((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); @@ -232,26 +254,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/elf_reloc.c b/lib_i386/elf_reloc.c new file mode 100644 index 0000000..ee5e589 --- /dev/null +++ b/lib_i386/elf_reloc.c @@ -0,0 +1,139 @@ +/* + * (C) Copyright 2009 + * Graeme Russ, graeme.r...@gmail.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include <elf.h> +#include <asm/u-boot-i386.h> + +extern long _i386boot_dynamic_start; +extern long _i386boot_dynamic_end; +extern long _i386boot_dynsym_start; +extern long _i386boot_dynsym_end; +extern long _i386boot_rel_dyn_start; +extern long _i386boot_rel_dyn_end; +extern long _i386boot_rel_got_start; +extern long _i386boot_rel_got_end; +extern long _i386boot_got_start; +extern long _i386boot_got_end; +extern long _i386boot_got_plt_start; +extern long _i386boot_got_plt_end; + +void elf_relocate(ulong rel_offset) +{ + ulong *reloc_ptr; + + /* + * Need to process: + * .rel.got - Array of Elf32_Rel + * .got.plt - Array of Elf32_Rela + * + * .dynsym - Array of Elf32_Sym + * .rel.dyn - Array of Elf32_Rel + */ + reloc_ptr = (ulong *)_i386boot_dynamic_start; + + reloc_fixup_elf32_rel ((Elf32_Rel *)&_i386boot_rel_got_start, + (Elf32_Rel *)&_i386boot_rel_got_end, + rel_offset); + + reloc_fixup_elf32_rela ((Elf32_Rela *)&_i386boot_got_plt_start, + (Elf32_Rela *)&_i386boot_got_plt_end, + rel_offset); + + reloc_fixup_elf32_rel ((Elf32_Rel *)&_i386boot_rel_dyn_start, + (Elf32_Rel *)&_i386boot_rel_dyn_end, + rel_offset); + + reloc_fixup_elf32_dyn ((Elf32_Dyn *)&_i386boot_dynamic_start, + (Elf32_Dyn *)&_i386boot_dynamic_end, + rel_offset); + + reloc_fixup_elf32_sym ((Elf32_Sym *)&_i386boot_dynsym_start, + (Elf32_Sym *)&_i386boot_dynsym_end, + rel_offset); +} + +void reloc_fixup_elf32_rel (Elf32_Rel *start, Elf32_Rel *end, ulong offset) +{ + Elf32_Rel *reloc_entry = (Elf32_Rel *)((ulong)start - offset); + Elf32_Rel *table_end = (Elf32_Rel *)((ulong)end - offset); + + while (reloc_entry <= table_end) { + if (reloc_entry->r_offset >= TEXT_BASE) { + ulong *ref; + reloc_entry->r_offset -= (Elf32_Addr)offset; + + ref = (ulong *)reloc_entry->r_offset; + + if (*ref >= TEXT_BASE) + *ref -= (Elf32_Addr)offset; + } + + reloc_entry++; + } +} + +void reloc_fixup_elf32_rela (Elf32_Rela *start, Elf32_Rela *end, ulong offset) +{ + Elf32_Rela *reloc_entry = (Elf32_Rela *)((ulong)start - offset); + Elf32_Rela *table_end = (Elf32_Rela *)((ulong)end - offset); + + while (reloc_entry <= table_end) { + if (reloc_entry->r_offset >= TEXT_BASE) { + ulong *ref; + reloc_entry->r_offset -= (Elf32_Addr)offset; + + ref = (ulong *)reloc_entry->r_offset; + + if (*ref >= TEXT_BASE) + *ref -= (Elf32_Addr)offset; + } + + reloc_entry++; + } +} + +void reloc_fixup_elf32_sym (Elf32_Sym *start, Elf32_Sym *end, ulong offset) +{ + Elf32_Sym *reloc_entry = (Elf32_Sym *)((ulong)start - offset); + Elf32_Sym *table_end = (Elf32_Sym *)((ulong)end - offset); + + while (reloc_entry <= table_end) { + if (reloc_entry->st_value >= TEXT_BASE) + reloc_entry->st_value -= (Elf32_Addr)offset; + + reloc_entry++; + } +} + +void reloc_fixup_elf32_dyn (Elf32_Dyn *start, Elf32_Dyn *end, ulong offset) +{ + Elf32_Dyn *reloc_entry = (Elf32_Dyn *)((ulong)start - offset); + Elf32_Dyn *table_end = (Elf32_Dyn *)((ulong)end - offset); + + while (reloc_entry <= table_end) { + if (reloc_entry->d_un.d_ptr >= TEXT_BASE) + reloc_entry->d_un.d_ptr -= (Elf32_Addr)offset; + + reloc_entry++; + } +} + diff --git a/lib_i386/interrupts.c b/lib_i386/interrupts.c index efbad72..51def59 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/realmode.c b/lib_i386/realmode.c index 6cf2738..726d1d3 100644 --- a/lib_i386/realmode.c +++ b/lib_i386/realmode.c @@ -68,10 +68,10 @@ int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out) memcpy(REALMODE_MAILBOX, in, sizeof(struct pt_regs)); asm("wbinvd\n"); - +/* TODO __asm__ volatile ( "lcall $0x20,%0\n" : : "i" (&realmode_enter) ); - +*/ asm("wbinvd\n"); memcpy(out, REALMODE_MAILBOX, sizeof(struct pt_regs)); diff --git a/lib_i386/timer.c b/lib_i386/timer.c index 58a0212..5cb1f54 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; /* -- 1.6.4.1.174.g32f4c _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot