[U-Boot] [RFC 03/14] x86: Allow cache before copy to RAM

Graeme Russ
2011-12-23T12:25:40Z

---
arch/x86/cpu/start.S | 37 +++++++-----------
arch/x86/include/asm/u-boot-x86.h | 1 +
arch/x86/lib/board.c | 76 +++++++++++++++++++++++-------------
3 files changed, 64 insertions(+), 50 deletions(-)

diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S
index f87633b..be21d97 100644
--- a/arch/x86/cpu/start.S
+++ b/arch/x86/cpu/start.S
@@ -95,32 +95,25 @@ car_init_ret:
movw $0x85, %ax
jmp die

-.globl relocate_code
-.type relocate_code, @function
-relocate_code:
+.globl setup_sdram_environment
+.type setup_sdram_environment, @function
+setup_sdram_environment:
+ /* Leave room for Global Data - Round down to 16 byte boundary */
+ subl %edx, %eax
+ andl $~15, %eax
+
+ /* Create a new stack */
+ movl %eax, %esp
+
/*
- * SDRAM has been initialised, U-Boot code has been copied into
- * RAM, BSS has been cleared and relocation adjustments have been
- * made. It is now time to jump into the in-RAM copy of U-Boot
- *
+ * relocate_code(ulong stack_ptr, gd_t *id, ulong reloc_addr)
* %eax = Address of top of stack
* %edx = Address of Global Data
- * %ecx = Base address of in-RAM copy of U-Boot
+ * %ecx = Base address of in-RAM copy of U-Boot (ignored)
*/
-
- /* Setup stack in RAM */
- movl %eax, %esp
-
- /* Setup call address of in-RAM copy of board_init_r() */
- movl $board_init_r, %ebp
- addl (GENERATED_GD_RELOC_OFF)(%edx), %ebp
-
- /* Setup parameters to board_init_r() */
- movl %edx, %eax
- movl %ecx, %edx
-
- /* Jump to in-RAM copy of board_init_r() */
- call *%ebp
+ movl %eax, %edx
+ xorl %ecx, %ecx
+ call relocate_code

die:
hlt
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h
index 755f88a..757a8ee 100644
--- a/arch/x86/include/asm/u-boot-x86.h
+++ b/arch/x86/include/asm/u-boot-x86.h
@@ -61,5 +61,6 @@ u32 isa_map_rom(u32 bus_addr, int size);
int video_bios_init(void);
int video_init(void);

+void setup_sdram_environment(phys_size_t ram_size, ulong gd_size);

#endif /* _U_BOOT_I386_H_ */
diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c
index ba6b59f..4736477 100644
--- a/arch/x86/lib/board.c
+++ b/arch/x86/lib/board.c
@@ -124,10 +124,10 @@ static void display_flash_config(ulong size)
*/
typedef int (init_fnc_t) (void);

-static int calculate_relocation_address(void);
-static int copy_uboot_to_ram(void);
-static int clear_bss(void);
-static int do_elf_reloc_fixups(void);
+static int calculate_relocation_address(gd_t *);
+static int copy_uboot_to_ram(gd_t *);
+static int clear_bss(gd_t *);
+static int do_elf_reloc_fixups(gd_t *);

init_fnc_t *init_sequence_f[] = {
cpu_init_f,
@@ -137,10 +137,6 @@ init_fnc_t *init_sequence_f[] = {
serial_init,
console_init_f,
dram_init_f,
- calculate_relocation_address,
- copy_uboot_to_ram,
- clear_bss,
- do_elf_reloc_fixups,

NULL,
};
@@ -159,7 +155,7 @@ init_fnc_t *init_sequence_r[] = {

gd_t *gd;

-static int calculate_relocation_address(void)
+static int calculate_relocation_address(gd_t *id)
{
ulong text_start = (ulong)&__text_start;
ulong bss_end = (ulong)&__bss_end;
@@ -167,7 +163,7 @@ static int calculate_relocation_address(void)
ulong rel_offset;

/* Calculate destination RAM Address and relocation offset */
- dest_addr = gd->ram_size;
+ dest_addr = id->start_addr_sp;
dest_addr -= CONFIG_SYS_STACK_SIZE;
dest_addr -= (bss_end - text_start);

@@ -179,33 +175,32 @@ static int calculate_relocation_address(void)

rel_offset = dest_addr - text_start;

- gd->start_addr_sp = gd->ram_size;
- gd->relocaddr = dest_addr;
- gd->reloc_off = rel_offset;
+ id->relocaddr = dest_addr;
+ id->reloc_off = rel_offset;

return 0;
}

-static int copy_uboot_to_ram(void)
+static int copy_uboot_to_ram(gd_t *id)
{
- size_t len = (size_t)(&__data_end) - (size_t)(&__text_start);
+ size_t len = (size_t)&__data_end - (size_t)&__text_start;

- memcpy((void *)gd->relocaddr, (void *)&__text_start, len);
+ memcpy((void *)id->relocaddr, (void *)&__text_start, len);

return 0;
}

-static int clear_bss(void)
+static int clear_bss(gd_t *id)
{
- ulong dst_addr = (ulong)(&__bss_start) + gd->reloc_off;
- size_t len = (size_t)(&__bss_end) - (size_t)(&__bss_start);
+ ulong dst_addr = (ulong)&__bss_start + id->reloc_off;
+ size_t len = (size_t)&__bss_end - (size_t)&__bss_start;

memset((void *)dst_addr, 0x00, len);

return 0;
}

-static int do_elf_reloc_fixups(void)
+static int do_elf_reloc_fixups(gd_t *id)
{
Elf32_Rel *re_src = (Elf32_Rel *)(&__rel_dyn_start);
Elf32_Rel *re_end = (Elf32_Rel *)(&__rel_dyn_end);
@@ -225,13 +220,13 @@ static int do_elf_reloc_fixups(void)

/* Switch to the in-RAM version */
offset_ptr_ram = (Elf32_Addr *)((ulong)offset_ptr_rom +
- gd->reloc_off);
+ id->reloc_off);

/* Check that the target points into .text */
if (*offset_ptr_ram >= CONFIG_SYS_TEXT_BASE &&
*offset_ptr_ram <
(CONFIG_SYS_TEXT_BASE + size)) {
- *offset_ptr_ram += gd->reloc_off;
+ *offset_ptr_ram += id->reloc_off;
}
}
} while (re_src++ < re_end);
@@ -251,10 +246,35 @@ void board_init_f(ulong boot_flags)
hang();
}

- gd->flags |= GD_FLG_RELOC;
+ /* SDRAM is now initialised setup a new stack in SDRAM */
+ setup_sdram_environment(gd->ram_size, GENERATED_GBL_DATA_SIZE);
+
+ /* NOTREACHED - relocate_code() does not return */
+ while (1)
+ ;
+}

- /* Enter the relocated U-Boot! */
- relocate_code(gd->start_addr_sp, gd, gd->relocaddr);
+typedef void (board_init_r_t) (gd_t *, ulong);
+
+void relocate_code(ulong stack_ptr, gd_t *id, ulong reloc_addr)
+{
+ board_init_r_t *board_init_r_func;
+
+ /* We are running from flash, but the stack is now in SDRAM */
+
+ /* gd is still in CAR - Copy it into SDRAM */
+ memcpy(id, gd, sizeof(gd_t));
+
+ id->start_addr_sp = stack_ptr;
+
+ calculate_relocation_address(id);
+ copy_uboot_to_ram(id);
+ clear_bss(id);
+ do_elf_reloc_fixups(id);
+
+ board_init_r_func = board_init_r;
+ board_init_r_func += id->reloc_off;
+ board_init_r_func(id, id->relocaddr);

/* NOTREACHED - relocate_code() does not return */
while (1)
@@ -270,14 +290,14 @@ void board_init_r(gd_t *id, ulong dest_addr)
ulong size;
#endif
static bd_t bd_data;
- static gd_t gd_data;
init_fnc_t **init_fnc_ptr;

show_boot_progress(0x21);

/* Global data pointer is now writable */
- gd = &gd_data;
- memcpy(gd, id, sizeof(gd_t));
+ gd = id;
+
+ gd->flags |= GD_FLG_RELOC;

/* compiler optimization barrier needed for GCC >= 3.4 */
__asm__ __volatile__("" : : : "memory");
--
1.7.5.2.317.g391b14