Add basic relocation to i386 port
authorGraeme Russ <graeme.russ@gmail.com>
Tue, 24 Feb 2009 10:14:56 +0000 (21:14 +1100)
committerWolfgang Denk <wd@denx.de>
Fri, 20 Mar 2009 21:39:13 +0000 (22:39 +0100)
Signed-off-by: Graeme Russ <graeme.russ@gmail.com>
cpu/i386/interrupts.c
cpu/i386/start.S
include/configs/sc520_cdp.h
include/configs/sc520_spunk.h
lib_i386/board.c
lib_i386/interrupts.c
lib_i386/timer.c

index 026a21b..063ea42 100644 (file)
@@ -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);
 }
 
 
index b6175b1..59089ef 100644 (file)
@@ -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
index 19e5889..82faca8 100644 (file)
@@ -28,6 +28,8 @@
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
+#define CONFIG_SKIP_RELOCATE_UBOOT
+
 #define GRUSS_TESTING
 /*
  * High Level Configuration Options
index 20481bd..3644169 100644 (file)
@@ -28,6 +28,8 @@
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
+#define CONFIG_SKIP_RELOCATE_UBOOT
+
 /*
  * High Level Configuration Options
  * (easy to change)
index 29683ee..e18dfa5 100644 (file)
@@ -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);
index b0f84de..3f3613a 100644 (file)
@@ -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;
 
index 5cb1f54..58a0212 100644 (file)
@@ -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;
 
        /*