summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGraeme Russ <graeme.russ@gmail.com>2009-02-24 21:14:56 +1100
committerWolfgang Denk <wd@denx.de>2009-03-20 22:39:13 +0100
commite17ee157ca9ff0d4cc5841d06c4b70c1603df29c (patch)
treeb86269e5e8d1b944250fdf4b98d3bed066ba7f92
parent8c63d47651f77d9fb887cad433370b866eb0a193 (diff)
Add basic relocation to i386 port
Signed-off-by: Graeme Russ <graeme.russ@gmail.com>
-rw-r--r--cpu/i386/interrupts.c4
-rw-r--r--cpu/i386/start.S41
-rw-r--r--include/configs/sc520_cdp.h2
-rw-r--r--include/configs/sc520_spunk.h2
-rw-r--r--lib_i386/board.c27
-rw-r--r--lib_i386/interrupts.c4
-rw-r--r--lib_i386/timer.c2
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;
/*