[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