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

Graeme Russ graeme.russ at gmail.com
Fri Dec 23 13:25:51 CET 2011


---
 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



More information about the U-Boot mailing list