[U-Boot] [RFC 14/14] x86: Tweak initialisation procedure

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

---
arch/x86/cpu/start.S | 43 ++++++++++--------
arch/x86/include/asm/init_helpers.h | 3 +
arch/x86/include/asm/u-boot-x86.h | 2 -
arch/x86/lib/board.c | 87 ++++++++++++++++++++++++++++++----
arch/x86/lib/init_helpers.c | 14 ++++++
arch/x86/lib/relocate.c | 43 ++---------------
include/common.h | 11 ++++-
7 files changed, 131 insertions(+), 72 deletions(-)

diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S
index be21d97..9cfd54d 100644
--- a/arch/x86/cpu/start.S
+++ b/arch/x86/cpu/start.S
@@ -30,7 +30,7 @@
#include <version.h>
#include <asm/global_data.h>
#include <asm/processor-flags.h>
-#include <generated/asm-offsets.h>
+#include <generated/generic-asm-offsets.h>

.section .text
.code32
@@ -84,36 +84,41 @@ car_init_ret:
*/
movl $CONFIG_SYS_INIT_SP_ADDR, %esp

- /* Set parameter to board_init_f() to boot flags */
- xorl %eax, %eax
- movw %bx, %ax
+ /*
+ * Any setting of Global Data member need to be done here
+ * NOTE: car_init must clear CAR so that Global Data is initialised
+ * to zero!
+ */

- /* Enter, U-boot! */
+ /*
+ * Enter U-boot by calling:
+ * board_init_f(location_of_gd_in_temporary_memory)
+ */
+ movl $CONFIG_SYS_INIT_GD_ADDR, %eax
call board_init_f

/* indicate (lack of) progress */
movw $0x85, %ax
jmp die

-.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
+.globl board_init_f_r_trampoline
+.type board_init_f_r_trampoline, @function
+board_init_f_r_trampoline:
+ /*
+ * %eax contains the upper address of usable RAM. Create a fresh
+ * stack in RAM. x86 stack grows down, global data sits immediately
+ * above the stack, so we have to leave enough room between the top
+ * of the stack and top of RAM for global data
+ */
+ subl $GENERATED_GBL_DATA_SIZE, %eax
andl $~15, %eax
-
- /* Create a new stack */
movl %eax, %esp

/*
- * 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 (ignored)
+ * Re-enter U-Boot by calling:
+ * board_init_f_r(location_of_gd_in_RAM)
*/
- movl %eax, %edx
- xorl %ecx, %ecx
- call relocate_code
+ call board_init_f_r

die:
hlt
diff --git a/arch/x86/include/asm/init_helpers.h b/arch/x86/include/asm/init_helpers.h
index 14ef11a..2d08834 100644
--- a/arch/x86/include/asm/init_helpers.h
+++ b/arch/x86/include/asm/init_helpers.h
@@ -28,6 +28,9 @@ int display_banner(void);
int display_dram_config(void);
int init_baudrate_f(void);

+int copy_gd_to_ram_f_r(gd_t *id);
+int init_cache_f_r(gd_t *id);
+
int mem_malloc_init_r(void);
int init_bd_struct_r(void);
int flash_init_r(void);
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h
index eaa50cc..093ad11 100644
--- a/arch/x86/include/asm/u-boot-x86.h
+++ b/arch/x86/include/asm/u-boot-x86.h
@@ -63,6 +63,4 @@ 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 b06063a..05d362d 100644
--- a/arch/x86/lib/board.c
+++ b/arch/x86/lib/board.c
@@ -35,6 +35,7 @@
#include <watchdog.h>
#include <stdio_dev.h>
#include <asm/u-boot-x86.h>
+#include <asm/relocate.h>

#include <asm/init_helpers.h>
#include <asm/init_wrappers.h>
@@ -51,12 +52,35 @@ DECLARE_GLOBAL_DATA_PTR = (gd_t *) (CONFIG_SYS_INIT_GD_ADDR);
/*
* Breath some life into the board...
*
- * Initialize an SMC for serial comms, and carry out some hardware
- * tests.
+ * Getting the board up and running is a three-stage process:
+ * 1) Execute from Flash, SDRAM Uninitialised
+ * At this point, there is a limited amount of non-SDRAM memory
+ * (typically the CPU cache, but can also be SRAM or even a buffer of
+ * of some peripheral). This limited memory is used to hold the initial
+ * copy of the Global Data Structure and a temporary stack.
*
- * The first part of initialization is running from Flash memory;
- * its main purpose is to initialize the RAM so that we
- * can relocate the monitor code to RAM.
+ * The following is performed during this phase of execution:
+ * - Core low-level CPU initialisation
+ * - Console initialisation
+ * - SDRAM initialisation
+ *
+ * 2) Execute from Flash, SDRAM Initialised
+ * At this point we copy Global Data from the initial non-SDRAM
+ * memory and set up the permanent stack in SDRAM. The CPU cache is no
+ * longer being used as temporary memory, so we can now fully enable
+ * it.
+ *
+ * The following is performed during this phase of execution:
+ * - Create final stack in SDRAM
+ * - Copy Global Data from temporary memory to SDRAM
+ * - Enabling of CPU cache(s),
+ * - Copying of U-Boot code and data from Flash to RAM
+ * - Clearing of the BSS
+ * - ELF relocation adjustments
+ *
+ * 3) Execute from SDRAM
+ * The following is performed during this phase of execution:
+ * - All remaining initialisation
*/

/*
@@ -72,6 +96,7 @@ DECLARE_GLOBAL_DATA_PTR = (gd_t *) (CONFIG_SYS_INIT_GD_ADDR);
* "continue" and != 0 means "fatal error, hang the system".
*/
typedef int (init_fnc_t) (void);
+typedef int (init_fnc_gd_t) (gd_t *);

init_fnc_t *init_sequence_f[] = {
cpu_init_f,
@@ -85,6 +110,18 @@ init_fnc_t *init_sequence_f[] = {
NULL,
};

+init_fnc_gd_t *init_sequence_f_r[] = {
+ copy_gd_to_ram_f_r,
+ init_cache_f_r,
+ calculate_relocation_address,
+ copy_uboot_to_ram,
+ clear_bss,
+ do_elf_reloc_fixups,
+
+ NULL,
+};
+
+
init_fnc_t *init_sequence_r[] = {
init_bd_struct_r,
mem_malloc_init_r,
@@ -161,15 +198,28 @@ static void do_init_loop(init_fnc_t **init_fnc_ptr)
}
}

+static void do_init_loop_gt(init_fnc_gd_t **init_fnc_ptr, gd_t *id)
+{
+ for (; *init_fnc_ptr; ++init_fnc_ptr) {
+ WATCHDOG_RESET();
+ if ((*init_fnc_ptr)(id) != 0)
+ hang();
+ }
+}
+
/* Perform all steps necessary to get RAM initialised ready for relocation */
-void board_init_f(ulong boot_flags)
+void board_init_f(gd_t *id)
{
- gd->flags = boot_flags;
+ /*
+ * NOTE: The gd_t pointer parameter is not used, but should be, in
+ * future, passed to the init_xxx_f functions which would
+ * allow the DECLARE_GLOBAL_DATA_PTR 'hack' to be removed
+ */

do_init_loop(init_sequence_f);

/*
- * SDRAM is now initialised setup a new stack in SDRAM
+ * SDRAM is now initialised - setup the final stack in SDRAM
*
* Code execution will continue in Flash, but with the stack
* in SDRAM. This allows us to copy global data out of the CPU
@@ -177,14 +227,29 @@ void board_init_f(ulong boot_flags)
* enable caching for the copy operation (which speeds it up
* considerably)
*/
- setup_sdram_environment(gd->ram_size, GENERATED_GBL_DATA_SIZE);
+ board_init_f_r_trampoline(gd->ram_size);
+
+ /* NOTREACHED - board_init_f_r_trampoline() does not return */
+ while (1)
+ ;
+}
+
+void board_init_f_r(gd_t *id)
+{
+ do_init_loop_gt(init_sequence_f_r, id);
+
+ /*
+ * Transfer execution from Flash to RAM by calculating the address
+ * of the in-RAM copy of board_init_r() and calling it
+ */
+ (board_init_r + id->reloc_off)(id);

- /* NOTREACHED - setup_sdram_environment() does not return */
+ /* NOTREACHED - board_init_r() does not return */
while (1)
;
}

-void board_init_r(gd_t *id, ulong dest_addr)
+void board_init_r(gd_t *id)
{
/* Global data pointer is now writable */
gd = id;
diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c
index a589fd3..c932812 100644
--- a/arch/x86/lib/init_helpers.c
+++ b/arch/x86/lib/init_helpers.c
@@ -70,6 +70,20 @@ int init_baudrate_f(void)
return 0;
}

+
+int copy_gd_to_ram_f_r(gd_t *id)
+{
+ memcpy(id, gd, sizeof(gd_t));
+
+ return 0;
+}
+
+int init_cache_f_r(gd_t *id)
+{
+ /* Initialise the CPU cache(s) */
+ return init_cache();
+}
+
int mem_malloc_init_r(void)
{
mem_malloc_init(((gd->relocaddr - CONFIG_SYS_MALLOC_LEN)+3)&~3,
diff --git a/arch/x86/lib/relocate.c b/arch/x86/lib/relocate.c
index f8c0b3f..cbce22b 100644
--- a/arch/x86/lib/relocate.c
+++ b/arch/x86/lib/relocate.c
@@ -34,14 +34,10 @@
#include <common.h>
#include <malloc.h>
#include <asm/u-boot-x86.h>
+#include <asm/relocate.h>
#include <elf.h>

-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 *);
-
-static int calculate_relocation_address(gd_t *id)
+int calculate_relocation_address(gd_t *id)
{
ulong text_start = (ulong)&__text_start;
ulong bss_end = (ulong)&__bss_end;
@@ -67,7 +63,7 @@ static int calculate_relocation_address(gd_t *id)
return 0;
}

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

@@ -76,7 +72,7 @@ static int copy_uboot_to_ram(gd_t *id)
return 0;
}

-static int clear_bss(gd_t *id)
+int clear_bss(gd_t *id)
{
ulong dst_addr = (ulong)&__bss_start + id->reloc_off;
size_t len = (size_t)&__bss_end - (size_t)&__bss_start;
@@ -86,7 +82,7 @@ static int clear_bss(gd_t *id)
return 0;
}

-static int do_elf_reloc_fixups(gd_t *id)
+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);
@@ -119,32 +115,3 @@ static int do_elf_reloc_fixups(gd_t *id)

return 0;
}
-
-typedef void (board_init_r_t) (gd_t *, ulong);
-
-__attribute__ ((__noreturn__))
-void relocate_code(ulong dummy_1, gd_t *id, ulong dummy_2)
-{
- 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));
-
- if (init_cache() != 0)
- hang();
-
- 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)
- ;
-}
diff --git a/include/common.h b/include/common.h
index 05a658c..4ef2a80 100644
--- a/include/common.h
+++ b/include/common.h
@@ -275,8 +275,15 @@ int abortboot(int bootdelay);
extern char console_buffer[];

/* arch/$(ARCH)/lib/board.c */
-void board_init_f (ulong) __attribute__ ((noreturn));
-void board_init_r (gd_t *, ulong) __attribute__ ((noreturn));
+#ifndef CONFIG_X86 /* Horrible Hack */
+void board_init_f (ulong) __attribute__ ((noreturn));
+void board_init_r (gd_t *, ulong) __attribute__ ((noreturn));
+#else
+void board_init_f(gd_t *) __attribute__ ((noreturn));
+void board_init_f_r_trampoline(ulong) __attribute__ ((noreturn));
+void board_init_f_r(gd_t *) __attribute__ ((noreturn));
+void board_init_r(gd_t *) __attribute__ ((noreturn));
+#endif
int checkboard (void);
int checkflash (void);
int checkdram (void);
--
1.7.5.2.317.g391b14