From mboxrd@z Thu Jan 1 00:00:00 1970 From: Graeme Russ Date: Wed, 17 Aug 2011 23:22:23 +1000 Subject: [U-Boot] [RFC] New init sequence processing without init_sequence array Message-ID: <1313587343-3693-1-git-send-email-graeme.russ@gmail.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de 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 #include #include +#include #include #include + +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 #endif -- 1.7.5.2.317.g391b14