[U-Boot] [RFC] New init sequence processing without init_sequence array

Graeme Russ graeme.russ at gmail.com
Wed Aug 17 15:22:23 CEST 2011


I have been thinking about the problem of the pesky init_sequence arrays
and the inevitable #ifdefs and empty stub functions that result so I
thought I'de have a crack at a more dynamic implementation. And like all
good programmers, I stole the solution ;). This implementation is based
on Linux's __initcall(fn) et. al. macros

If this works cross-platform, we can finally move board_init_* into
/lib/ - Wouldn't that be nice

Thoughts?

Regards,

Graeme

P.S Compile tested on x86 gcc 4.5.2 only - haven't fired it up yet
---
 arch/x86/cpu/sc520/sc520.c       |    1 +
 arch/x86/cpu/sc520/sc520_sdram.c |    1 +
 arch/x86/cpu/u-boot.lds          |    5 +++++
 arch/x86/lib/board.c             |   36 +++++++++++++++---------------------
 board/eNET/eNET.c                |    1 +
 common/console.c                 |    1 +
 common/env_flash.c               |    2 ++
 common/serial.c                  |    1 +
 include/common.h                 |    8 ++++++++
 9 files changed, 35 insertions(+), 21 deletions(-)

diff --git a/arch/x86/cpu/sc520/sc520.c b/arch/x86/cpu/sc520/sc520.c
index e37c403..fc2996a 100644
--- a/arch/x86/cpu/sc520/sc520.c
+++ b/arch/x86/cpu/sc520/sc520.c
@@ -53,6 +53,7 @@ int cpu_init_f(void)

 	return x86_cpu_init_f();
 }
+INIT_FUNC(f, 010, cpu_init_f);

 int cpu_init_r(void)
 {
diff --git a/arch/x86/cpu/sc520/sc520_sdram.c b/arch/x86/cpu/sc520/sc520_sdram.c
index f3623f5..08674eb 100644
--- a/arch/x86/cpu/sc520/sc520_sdram.c
+++ b/arch/x86/cpu/sc520/sc520_sdram.c
@@ -57,6 +57,7 @@ int dram_init_f(void)

 	return 0;
 }
+INIT_FUNC(f, 070, dram_init_f);

 static inline void sc520_dummy_write(void)
 {
diff --git a/arch/x86/cpu/u-boot.lds b/arch/x86/cpu/u-boot.lds
index fe28030..48b5b99 100644
--- a/arch/x86/cpu/u-boot.lds
+++ b/arch/x86/cpu/u-boot.lds
@@ -57,6 +57,11 @@ SECTIONS
 	__data_end = .;

 	. = ALIGN(4);
+	__initfuncs_f_start = .;
+	.initfuncs_f : { KEEP(*(SORT_BY_NAME(.initfuncs_f*))) }
+	__initfuncs_f_end = .;
+
+	. = ALIGN(4);
 	__bss_start = ABSOLUTE(.);
 	.bss (NOLOAD) : { *(.bss) }
 	. = ALIGN(4);
diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c
index b1b8680..de06800 100644
--- a/arch/x86/lib/board.c
+++ b/arch/x86/lib/board.c
@@ -64,6 +64,8 @@ extern ulong __rel_dyn_start;
 extern ulong __rel_dyn_end;
 extern ulong __bss_start;
 extern ulong __bss_end;
+extern ulong __initfuncs_f_start;
+extern ulong __initfuncs_f_end;

 /************************************************************************
  * Init Utilities							*
@@ -83,6 +85,7 @@ static int init_baudrate (void)

 	return (0);
 }
+INIT_FUNC(f, 040, init_baudrate);

 static int display_banner (void)
 {
@@ -152,22 +155,6 @@ static int copy_uboot_to_ram(void);
 static int clear_bss(void);
 static int do_elf_reloc_fixups(void);

-init_fnc_t *init_sequence_f[] = {
-	cpu_init_f,
-	board_early_init_f,
-	env_init,
-	init_baudrate,
-	serial_init,
-	console_init_f,
-	dram_init_f,
-	calculate_relocation_address,
-	copy_uboot_to_ram,
-	clear_bss,
-	do_elf_reloc_fixups,
-
-	NULL,
-};
-
 init_fnc_t *init_sequence_r[] = {
 	cpu_init_r,		/* basic cpu dependent setup */
 	board_early_init_r,	/* basic board dependent setup */
@@ -201,6 +188,7 @@ static int calculate_relocation_address(void)

 	return 0;
 }
+INIT_FUNC(f, 080, calculate_relocation_address);

 static int copy_uboot_to_ram(void)
 {
@@ -213,6 +201,7 @@ static int copy_uboot_to_ram(void)

 	return 0;
 }
+INIT_FUNC(f, 090, copy_uboot_to_ram);

 static int clear_bss(void)
 {
@@ -227,6 +216,7 @@ static int clear_bss(void)

 	return 0;
 }
+INIT_FUNC(f, 100, clear_bss);

 static int do_elf_reloc_fixups(void)
 {
@@ -241,18 +231,22 @@ static int do_elf_reloc_fixups(void)

 	return 0;
 }
+INIT_FUNC(f, 110, do_elf_reloc_fixups);

 /* Load U-Boot into RAM, initialize BSS, perform relocation adjustments */
 void board_init_f(ulong boot_flags)
 {
-	init_fnc_t **init_fnc_ptr;
-
 	gd->flags = boot_flags;

-	for (init_fnc_ptr = init_sequence_f; *init_fnc_ptr; ++init_fnc_ptr) {
-		if ((*init_fnc_ptr)() != 0)
+	init_fnc_t *init_fnc_ptr = (init_fnc_t *)(&__initfuncs_f_start);
+	init_fnc_t *init_func_end = (init_fnc_t *)(&__initfuncs_f_end);
+
+	do {
+		if ((init_fnc_ptr)() != 0)
 			hang();
-	}
+
+	} while (init_fnc_ptr++ < init_func_end);
+

 	gd->flags |= GD_FLG_RELOC;

diff --git a/board/eNET/eNET.c b/board/eNET/eNET.c
index 2a5636c..2167df9 100644
--- a/board/eNET/eNET.c
+++ b/board/eNET/eNET.c
@@ -106,6 +106,7 @@ int board_early_init_f(void)

 	return 0;
 }
+INIT_FUNC(f, 020, board_early_init_f);

 static void enet_setup_pars(void)
 {
diff --git a/common/console.c b/common/console.c
index 8c650e0..559c799 100644
--- a/common/console.c
+++ b/common/console.c
@@ -531,6 +531,7 @@ int console_init_f(void)

 	return 0;
 }
+INIT_FUNC(f, 060, console_init_f);

 void stdio_print_current_devices(void)
 {
diff --git a/common/env_flash.c b/common/env_flash.c
index 50ca4ffa..a63c108 100644
--- a/common/env_flash.c
+++ b/common/env_flash.c
@@ -126,6 +126,7 @@ int  env_init(void)

 	return 0;
 }
+INIT_FUNC(f, 030, env_init);

 #ifdef CMD_SAVEENV
 int saveenv(void)
@@ -252,6 +253,7 @@ int  env_init(void)
 	gd->env_valid = 0;
 	return 0;
 }
+INIT_FUNC(f, 030, env_init);

 #ifdef CMD_SAVEENV

diff --git a/common/serial.c b/common/serial.c
index 995d268..5d097d8 100644
--- a/common/serial.c
+++ b/common/serial.c
@@ -168,6 +168,7 @@ int serial_init (void)

 	return serial_current->init ();
 }
+INIT_FUNC(f, 050, serial_init);

 void serial_setbrg (void)
 {
diff --git a/include/common.h b/include/common.h
index 12a1074..61126f1 100644
--- a/include/common.h
+++ b/include/common.h
@@ -39,8 +39,16 @@ typedef volatile unsigned char	vu_char;
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/string.h>
+#include <linux/compiler.h>
 #include <asm/ptrace.h>
 #include <stdarg.h>
+
+typedef int (*initfunc_t)(void);
+
+#define INIT_FUNC(stage,step,fn) \
+	static initfunc_t __initfunc_ ## fn ## stage __used \
+	__attribute__((__section__(".initfuncs_" #stage "." #step))) = fn
+
 #if defined(CONFIG_PCI) && (defined(CONFIG_4xx) && !defined(CONFIG_AP1000))
 #include <pci.h>
 #endif
--
1.7.5.2.317.g391b14



More information about the U-Boot mailing list