From e17ee157ca9ff0d4cc5841d06c4b70c1603df29c Mon Sep 17 00:00:00 2001 From: Graeme Russ Date: Tue, 24 Feb 2009 21:14:56 +1100 Subject: Add basic relocation to i386 port Signed-off-by: Graeme Russ --- cpu/i386/interrupts.c | 4 ++-- cpu/i386/start.S | 41 +++++++++++++++++++++++++++++++++++++++++ include/configs/sc520_cdp.h | 2 ++ include/configs/sc520_spunk.h | 2 ++ lib_i386/board.c | 27 +++++++++++++++++++++++++++ lib_i386/interrupts.c | 4 ++-- lib_i386/timer.c | 2 +- 7 files changed, 77 insertions(+), 5 deletions(-) diff --git a/cpu/i386/interrupts.c b/cpu/i386/interrupts.c index 026a21bd2..063ea42cd 100644 --- a/cpu/i386/interrupts.c +++ b/cpu/i386/interrupts.c @@ -53,8 +53,8 @@ asm ("idt_ptr:\n" void set_vector(u8 intnum, void *routine) { - idt[intnum].base_high = (u16)((u32)(routine)>>16); - idt[intnum].base_low = (u16)((u32)(routine)&0xffff); + idt[intnum].base_high = (u16)((u32)(routine + gd->reloc_off) >> 16); + idt[intnum].base_low = (u16)((u32)(routine + gd->reloc_off) & 0xffff); } diff --git a/cpu/i386/start.S b/cpu/i386/start.S index b6175b1c1..59089ef59 100644 --- a/cpu/i386/start.S +++ b/cpu/i386/start.S @@ -173,7 +173,41 @@ bss_fail: 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 @@ -183,7 +217,14 @@ bss_ok: 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 /* indicate (lack of) progress */ movw $0x85, %ax diff --git a/include/configs/sc520_cdp.h b/include/configs/sc520_cdp.h index 19e5889ff..82faca810 100644 --- a/include/configs/sc520_cdp.h +++ b/include/configs/sc520_cdp.h @@ -28,6 +28,8 @@ #ifndef __CONFIG_H #define __CONFIG_H +#define CONFIG_SKIP_RELOCATE_UBOOT + #define GRUSS_TESTING /* * High Level Configuration Options diff --git a/include/configs/sc520_spunk.h b/include/configs/sc520_spunk.h index 20481bd49..36441696a 100644 --- a/include/configs/sc520_spunk.h +++ b/include/configs/sc520_spunk.h @@ -28,6 +28,8 @@ #ifndef __CONFIG_H #define __CONFIG_H +#define CONFIG_SKIP_RELOCATE_UBOOT + /* * High Level Configuration Options * (easy to change) diff --git a/lib_i386/board.c b/lib_i386/board.c index 29683ee26..e18dfa5bc 100644 --- a/lib_i386/board.c +++ b/lib_i386/board.c @@ -225,6 +225,9 @@ 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; @@ -238,6 +241,10 @@ 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 for (init_fnc_ptr = init_sequence, i=0; *init_fnc_ptr; ++init_fnc_ptr, i++) { show_boot_progress(0xa130|i); @@ -247,6 +254,26 @@ 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 b0f84de4e..3f3613a2f 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, + (ulong) handler + gd->reloc_off, (ulong) irq_handlers[irq].handler); status = disable_interrupts (); - irq_handlers[irq].handler = handler; + irq_handlers[irq].handler = handler + gd->reloc_off; irq_handlers[irq].arg = arg; irq_handlers[irq].count = 0; diff --git a/lib_i386/timer.c b/lib_i386/timer.c index 5cb1f54fb..58a0212ad 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; + new_func->isr_func = isr_func + gd->reloc_off; new_func->next = NULL; /* -- cgit v1.2.3