[U-Boot] [WIP, PATCH] initcall: An outline of the idea

Graeme Russ graeme.russ at gmail.com
Fri Mar 2 12:05:12 CET 2012


This is a very rough (i.e. it is not even close to finished and maybe won't
even appply as it sits on top of some other dev patches I have) but it
should give you an idea of what the INIT_FUNC implementation will look like.

Ultimately, tools/mkinitseq.c will process the dependencies and generate
a C file containing the three init sequence arrays which have been deleted
from arch/x86/lib/board.c

---
 Makefile                                    |   24 +++-
 arch/blackfin/cpu/initcode.c                |    1 +
 arch/blackfin/cpu/serial.c                  |    1 +
 arch/mips/cpu/mips32/au1x00/au1x00_serial.c |    1 +
 arch/mips/cpu/mips32/incaip/asc_serial.c    |    1 +
 arch/mips/cpu/xburst/jz_serial.c            |    1 +
 arch/powerpc/cpu/mpc512x/serial.c           |    1 +
 arch/powerpc/cpu/mpc5xx/serial.c            |    1 +
 arch/sparc/cpu/leon2/serial.c               |    1 +
 arch/sparc/cpu/leon3/serial.c               |    1 +
 arch/x86/cpu/cpu.c                          |    4 +-
 arch/x86/cpu/interrupts.c                   |    1 +
 arch/x86/cpu/sc520/sc520.c                  |    1 +
 arch/x86/cpu/sc520/sc520_sdram.c            |    2 +
 arch/x86/cpu/sc520/sc520_timer.c            |    1 +
 arch/x86/cpu/u-boot.lds                     |    1 +
 arch/x86/lib/board.c                        |  134 +-------------
 arch/x86/lib/init_helpers.c                 |   14 ++
 arch/x86/lib/init_wrappers.c                |   11 +
 arch/x86/lib/relocate.c                     |    3 +
 board/amirix/ap1000/serial.c                |    1 +
 board/bmw/serial.c                          |    1 +
 board/eNET/eNET.c                           |    3 +
 common/console.c                            |    2 +
 common/env_dataflash.c                      |    1 +
 common/env_eeprom.c                         |    1 +
 common/env_flash.c                          |    1 +
 common/env_mgdisk.c                         |    1 +
 common/env_mmc.c                            |    1 +
 common/env_nand.c                           |    1 +
 common/env_nowhere.c                        |    1 +
 common/env_nvram.c                          |    1 +
 common/env_onenand.c                        |    1 +
 common/env_sf.c                             |    1 +
 common/serial.c                             |    1 +
 common/stdio.c                              |    1 +
 config.mk                                   |    2 +
 doc/README.INIT_FUNC                        |   31 +++
 include/initcall.h                          |   19 ++
 tools/Makefile                              |    6 +
 tools/mkinitseq.c                           |  278 +++++++++++++++++++++++++++
 u-boot-init.lds                             |   25 +++
 42 files changed, 449 insertions(+), 136 deletions(-)
 create mode 100644 doc/README.INIT_FUNC
 create mode 100644 include/initcall.h
 create mode 100644 tools/mkinitseq.c
 create mode 100644 u-boot-init.lds

diff --git a/Makefile b/Makefile
index f174996..d07f404 100644
--- a/Makefile
+++ b/Makefile
@@ -460,8 +460,30 @@ GEN_UBOOT = \
 			-Map u-boot.map -o u-boot
 endif
 
+GEN_UBOOT_INIT = \
+		UNDEF_SYM=`$(OBJDUMP) -x $(LIBBOARD) $(LIBS) | \
+		sed  -n -e 's/.*\($(SYM_PREFIX)__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
+		cd $(LNDIR) && $(LD) $(LDFLAGS) $(LDFLAGS_$(@F)) $$UNDEF_SYM $(__OBJS) \
+			--start-group $(__LIBS) --end-group \
+			-Map u-boot-init.map -o u-boot-init
+
+$(obj)u-boot-init:	depend \
+		$(SUBDIR_TOOLS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT)
+		$(GEN_UBOOT_INIT)
+
+$(obj)u-boot-init.bin:	$(obj)u-boot-init
+		$(OBJCOPY) -j .initfuncs -O binary $< $@
+
+$(obj)init_seq.c:	tools $(obj)u-boot-init.bin
+		$(obj)tools/mkinitseq $(obj)u-boot-init.bin
+
 $(obj)u-boot:	depend \
-		$(SUBDIR_TOOLS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) $(obj)u-boot.lds
+		$(SUBDIR_TOOLS) \
+		$(OBJS) $(LIBBOARD) \
+		$(LIBS) \
+		$(LDSCRIPT) \
+		$(obj)init_seq.c \
+		$(obj)u-boot.lds
 		$(GEN_UBOOT)
 ifeq ($(CONFIG_KALLSYMS),y)
 		smap=`$(call SYSTEM_MAP,u-boot) | \
diff --git a/arch/blackfin/cpu/initcode.c b/arch/blackfin/cpu/initcode.c
index fb3a101..2f4cae5 100644
--- a/arch/blackfin/cpu/initcode.c
+++ b/arch/blackfin/cpu/initcode.c
@@ -78,6 +78,7 @@ static inline void serial_init(void)
 			serial_early_set_baud(uart_base, CONFIG_BAUDRATE);
 	}
 }
+INIT_FUNC(serial_init, serial_f, *baudrate_f -SDRAM);
 
 __attribute__((always_inline))
 static inline void serial_deinit(void)
diff --git a/arch/blackfin/cpu/serial.c b/arch/blackfin/cpu/serial.c
index 6603dc0..89026f2 100644
--- a/arch/blackfin/cpu/serial.c
+++ b/arch/blackfin/cpu/serial.c
@@ -318,6 +318,7 @@ int serial_init(void)
 	uart_lsr_clear(UART_DLL);
 	return 0;
 }
+INIT_FUNC(serial_init, serial_f, *baudrate_f -SDRAM);
 
 int serial_tstc(void)
 {
diff --git a/arch/mips/cpu/mips32/au1x00/au1x00_serial.c b/arch/mips/cpu/mips32/au1x00/au1x00_serial.c
index c25ba5a..d723dbf 100644
--- a/arch/mips/cpu/mips32/au1x00/au1x00_serial.c
+++ b/arch/mips/cpu/mips32/au1x00/au1x00_serial.c
@@ -61,6 +61,7 @@ int serial_init (void)
 
 	return 0;
 }
+INIT_FUNC(serial_init, serial_f, *baudrate_f -SDRAM);
 
 
 void serial_setbrg (void)
diff --git a/arch/mips/cpu/mips32/incaip/asc_serial.c b/arch/mips/cpu/mips32/incaip/asc_serial.c
index 7239804..21e5cf2 100644
--- a/arch/mips/cpu/mips32/incaip/asc_serial.c
+++ b/arch/mips/cpu/mips32/incaip/asc_serial.c
@@ -81,6 +81,7 @@ int serial_init (void)
 
     return 0;
 }
+INIT_FUNC(serial_init, serial_f, *baudrate_f -SDRAM);
 
 void serial_setbrg (void)
 {
diff --git a/arch/mips/cpu/xburst/jz_serial.c b/arch/mips/cpu/xburst/jz_serial.c
index e6c48e0..e306961 100644
--- a/arch/mips/cpu/xburst/jz_serial.c
+++ b/arch/mips/cpu/xburst/jz_serial.c
@@ -61,6 +61,7 @@ int serial_init(void)
 
 	return 0;
 }
+INIT_FUNC(serial_init, serial_f, *baudrate_f -SDRAM);
 
 void serial_setbrg(void)
 {
diff --git a/arch/powerpc/cpu/mpc512x/serial.c b/arch/powerpc/cpu/mpc512x/serial.c
index 7c53346..149ee73 100644
--- a/arch/powerpc/cpu/mpc512x/serial.c
+++ b/arch/powerpc/cpu/mpc512x/serial.c
@@ -376,6 +376,7 @@ int serial_init(void)
 {
 	return serial_init_dev(CONFIG_PSC_CONSOLE);
 }
+INIT_FUNC(serial_init, serial_f, *baudrate_f -SDRAM);
 
 void serial_putc(const char c)
 {
diff --git a/arch/powerpc/cpu/mpc5xx/serial.c b/arch/powerpc/cpu/mpc5xx/serial.c
index 88c6db8..14fd66c 100644
--- a/arch/powerpc/cpu/mpc5xx/serial.c
+++ b/arch/powerpc/cpu/mpc5xx/serial.c
@@ -62,6 +62,7 @@ int serial_init (void)
 #endif
 	return 0;
 }
+INIT_FUNC(serial_init, serial_f, *baudrate_f -SDRAM);
 
 void serial_putc(const char c)
 {
diff --git a/arch/sparc/cpu/leon2/serial.c b/arch/sparc/cpu/leon2/serial.c
index 4f41b8e..6ea7abd 100644
--- a/arch/sparc/cpu/leon2/serial.c
+++ b/arch/sparc/cpu/leon2/serial.c
@@ -71,6 +71,7 @@ int serial_init(void)
 
 	return 0;
 }
+INIT_FUNC(serial_init, serial_f, *baudrate_f -SDRAM);
 
 void serial_putc(const char c)
 {
diff --git a/arch/sparc/cpu/leon3/serial.c b/arch/sparc/cpu/leon3/serial.c
index 4b2fcb8..327b525 100644
--- a/arch/sparc/cpu/leon3/serial.c
+++ b/arch/sparc/cpu/leon3/serial.c
@@ -71,6 +71,7 @@ int serial_init(void)
 	}
 	return -1;		/* didn't find hardware */
 }
+INIT_FUNC(serial_init, serial_f, *baudrate_f -SDRAM);
 
 void serial_putc(const char c)
 {
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
index e9bb0d7..d96ae1b 100644
--- a/arch/x86/cpu/cpu.c
+++ b/arch/x86/cpu/cpu.c
@@ -121,7 +121,7 @@ void setup_gdt(gd_t *id, u64 *gdt_addr)
 	load_fs(X86_GDT_ENTRY_32BIT_FS);
 }
 
-int x86_cpu_init_f(void)
+int cpu_init_f(void)
 {
 	const u32 em_rst = ~X86_CR0_EM;
 	const u32 mp_ne_set = X86_CR0_MP | X86_CR0_NE;
@@ -136,7 +136,7 @@ int x86_cpu_init_f(void)
 
 	return 0;
 }
-int cpu_init_f(void) __attribute__((weak, alias("x86_cpu_init_f")));
+INIT_FUNC(cpu_init_f, cpu_f, *RESET -SDRAM);
 
 int x86_cpu_init_r(void)
 {
diff --git a/arch/x86/cpu/interrupts.c b/arch/x86/cpu/interrupts.c
index 43ec3f8..1414c79 100644
--- a/arch/x86/cpu/interrupts.c
+++ b/arch/x86/cpu/interrupts.c
@@ -227,6 +227,7 @@ int cpu_init_interrupts(void)
 
 	return 0;
 }
+INIT_FUNC(cpu_init_interrupts, interrupts, *exceptions);
 
 void __do_irq(int irq)
 {
diff --git a/arch/x86/cpu/sc520/sc520.c b/arch/x86/cpu/sc520/sc520.c
index 3fe85e7..8f350d4 100644
--- a/arch/x86/cpu/sc520/sc520.c
+++ b/arch/x86/cpu/sc520/sc520.c
@@ -64,3 +64,4 @@ int cpu_init_r(void)
 
 	return x86_cpu_init_r();
 }
+INIT_FUNC(cpu_init_r, cpu_r, *malloc);
diff --git a/arch/x86/cpu/sc520/sc520_sdram.c b/arch/x86/cpu/sc520/sc520_sdram.c
index 9dc1334..4df602b 100644
--- a/arch/x86/cpu/sc520/sc520_sdram.c
+++ b/arch/x86/cpu/sc520/sc520_sdram.c
@@ -51,6 +51,7 @@ int dram_init_f(void)
 
 	return 0;
 }
+INIT_FUNC(dram_init_f, dram_f, *console_f -SDRAM);
 
 static inline void sc520_dummy_write(void)
 {
@@ -477,3 +478,4 @@ int dram_init(void)
 
 	return 0;
 }
+INIT_FUNC(dram_init, dram_r, *interrupts board_early_r);
diff --git a/arch/x86/cpu/sc520/sc520_timer.c b/arch/x86/cpu/sc520/sc520_timer.c
index 495a694..569f612 100644
--- a/arch/x86/cpu/sc520/sc520_timer.c
+++ b/arch/x86/cpu/sc520/sc520_timer.c
@@ -69,6 +69,7 @@ int timer_init(void)
 
 	return 0;
 }
+INIT_FUNC(timer_init, timer, *interrupts);
 
 /* Allow boards to override udelay implementation */
 void __udelay(unsigned long usec)
diff --git a/arch/x86/cpu/u-boot.lds b/arch/x86/cpu/u-boot.lds
index 8abaae1..85fff3c 100644
--- a/arch/x86/cpu/u-boot.lds
+++ b/arch/x86/cpu/u-boot.lds
@@ -90,6 +90,7 @@ SECTIONS
 	/DISCARD/ : { *(.plt*) }
 	/DISCARD/ : { *(.interp*) }
 	/DISCARD/ : { *(.gnu*) }
+	/DISCARD/ : { *(.initfuncs*) }
 
 	/* 16bit realmode trampoline code */
 	.realmode REALMODE_BASE : AT ( LOADADDR(.rel.dyn) + SIZEOF(.rel.dyn) ) { KEEP(*(.realmode)) }
diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c
index dceb69c..ad7b518 100644
--- a/arch/x86/lib/board.c
+++ b/arch/x86/lib/board.c
@@ -39,6 +39,7 @@
 
 #include <asm/init_helpers.h>
 #include <asm/init_wrappers.h>
+#include <initcall.h>
 
 /*
  * Breath some life into the board...
@@ -77,139 +78,6 @@
  *      - All remaining initialisation
  */
 
-/*
- * The requirements for any new initalization function is simple: it is
- * a function with no parameters which returns an integer return code,
- * where 0 means "continue" and != 0 means "fatal error, hang the system"
- */
-typedef int (init_fnc_t) (void);
-
-/*
- * init_sequence_f is the list of init functions which are run when U-Boot
- * is executing from Flash with a limited 'C' environment. The following
- * limitations must be considered when implementing an '_f' function:
- *  - 'static' variables are read-only
- *  - Global Data (gd->xxx) is read/write
- *  - Stack space is limited
- *
- * The '_f' sequence must, as a minimum, initialise SDRAM. It _should_
- * also initialise the console (to provide early debug output)
- */
-init_fnc_t *init_sequence_f[] = {
-	cpu_init_f,
-	board_early_init_f,
-	env_init,
-	init_baudrate_f,
-	serial_init,
-	console_init_f,
-	dram_init_f,
-	calculate_relocation_address,
-
-	NULL,
-};
-
-/*
- * init_sequence_f_r is the list of init functions which are run when
- * U-Boot is executing from Flash with a semi-limited 'C' environment.
- * The following limitations must be considered when implementing an
- * '_f_r' function:
- *  - 'static' variables are read-only
- *  - Global Data (gd->xxx) is read/write
- *
- * The '_f_r' sequence must, as a minimum, copy U-Boot to RAM (if
- * supported).  It _should_, if possible, copy global data to RAM and
- * initialise the CPU caches (to speed up the relocation process)
- */
-init_fnc_t *init_sequence_f_r[] = {
-	copy_gd_to_ram_f_r,
-	init_cache_f_r,
-	copy_uboot_to_ram,
-	clear_bss,
-	do_elf_reloc_fixups,
-
-	NULL,
-};
-
-/*
- * init_sequence_r is the list of init functions which are run when U-Boot
- * is executing from RAM with a full 'C' environment. There are no longer
- * any limitations which must be considered when implementing an '_r'
- * function, (i.e.'static' variables are read/write)
- *
- * If not already done, the '_r' sequence must copy global data to RAM and
- * (should) initialise the CPU caches.
- */
-init_fnc_t *init_sequence_r[] = {
-	set_reloc_flag_r,
-	init_bd_struct_r,
-	mem_malloc_init_r,
-	cpu_init_r,
-	board_early_init_r,
-	dram_init,
-	interrupt_init,
-	timer_init,
-	display_banner,
-	display_dram_config,
-#ifdef CONFIG_SERIAL_MULTI
-	serial_initialize_r,
-#endif
-#ifndef CONFIG_SYS_NO_FLASH
-	flash_init_r,
-#endif
-	env_relocate_r,
-#ifdef CONFIG_CMD_NET
-	init_ip_address_r,
-#endif
-#ifdef CONFIG_PCI
-	pci_init_r,
-#endif
-	stdio_init,
-	jumptable_init_r,
-	console_init_r,
-#ifdef CONFIG_MISC_INIT_R
-	misc_init_r,
-#endif
-#if defined(CONFIG_CMD_PCMCIA) && !defined(CONFIG_CMD_IDE)
-	pci_init_r,
-#endif
-#if defined(CONFIG_CMD_KGDB)
-	kgdb_init_r,
-#endif
-	enable_interrupts_r,
-#ifdef CONFIG_STATUS_LED
-	status_led_set_r,
-#endif
-	set_load_addr_r,
-#if defined(CONFIG_CMD_NET)
-	set_bootfile_r,
-#endif
-#if defined(CONFIG_CMD_IDE)
-	ide_init_r,
-#endif
-#if defined(CONFIG_CMD_SCSI)
-	scsi_init_r,
-#endif
-#if defined(CONFIG_CMD_DOC)
-	doc_init_r,
-#endif
-#ifdef CONFIG_BITBANGMII
-	bb_miiphy_init_r,
-#endif
-#if defined(CONFIG_CMD_NET)
-	eth_initialize_r,
-#ifdef CONFIG_RESET_PHY_R
-	reset_phy_r,
-#endif
-#endif
-#ifdef CONFIG_GENERIC_MMC
-	mmc_initialize_r,
-#endif
-#ifdef CONFIG_LAST_STAGE_INIT
-	last_stage_init,
-#endif
-	NULL,
-};
-
 static void do_init_loop(init_fnc_t **init_fnc_ptr)
 {
 	for (; *init_fnc_ptr; ++init_fnc_ptr) {
diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c
index 9f4dee0..f469e4a 100644
--- a/arch/x86/lib/init_helpers.c
+++ b/arch/x86/lib/init_helpers.c
@@ -50,6 +50,7 @@ int display_banner(void)
 
 	return 0;
 }
+INIT_FUNC(display_banner, banner, *RELOC serial_multi);
 
 int display_dram_config(void)
 {
@@ -64,12 +65,14 @@ int display_dram_config(void)
 
 	return 0;
 }
+INIT_FUNC(display_dram_config, display_dram, *dram_r banner serial_multi);
 
 int init_baudrate_f(void)
 {
 	gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE);
 	return 0;
 }
+INIT_FUNC(init_baudrate_f, baudrate_f, *env_init -SDRAM);
 
 int calculate_relocation_address(void)
 {
@@ -106,6 +109,7 @@ int calculate_relocation_address(void)
 
 	return 0;
 }
+INIT_FUNC(calculate_relocation_address, calc_reloc, *dram_f -SDRAM);
 
 int copy_gd_to_ram_f_r(void)
 {
@@ -131,12 +135,14 @@ int copy_gd_to_ram_f_r(void)
 
 	return 0;
 }
+INIT_FUNC(copy_gd_to_ram_f_r, copy_gd, *SDRAM -RELOC);
 
 int init_cache_f_r(void)
 {
 	/* Initialise the CPU cache(s) */
 	return init_cache();
 }
+INIT_FUNC(init_cache_f_r, cache_f_r, *copy_gd -RELOC);
 
 int set_reloc_flag_r(void)
 {
@@ -144,6 +150,7 @@ int set_reloc_flag_r(void)
 
 	return 0;
 }
+INIT_FUNC(set_reloc_flag_r, reloc_flag, *RELOC);
 
 int mem_malloc_init_r(void)
 {
@@ -152,6 +159,7 @@ int mem_malloc_init_r(void)
 
 	return 0;
 }
+INIT_FUNC(mem_malloc_init_r, malloc, *bd_struct);
 
 bd_t bd_data;
 
@@ -162,6 +170,7 @@ int init_bd_struct_r(void)
 
 	return 0;
 }
+INIT_FUNC(init_bd_struct_r, bd_struct, *reloc_flag);
 
 #ifndef CONFIG_SYS_NO_FLASH
 int flash_init_r(void)
@@ -177,6 +186,7 @@ int flash_init_r(void)
 
 	return 0;
 }
+INIT_FUNC(flash_init_r, flash_r, *RELOC);
 #endif
 
 int init_ip_address_r(void)
@@ -186,6 +196,7 @@ int init_ip_address_r(void)
 
 	return 0;
 }
+INIT_FUNC(init_ip_address_r, ip_address, *env_reloc);
 
 #ifdef CONFIG_STATUS_LED
 int status_led_set_r(void)
@@ -194,6 +205,7 @@ int status_led_set_r(void)
 
 	return 0;
 }
+INIT_FUNC(status_led_set_r, status_led, *RELOC gpio);
 #endif
 
 int set_bootfile_r(void)
@@ -207,6 +219,7 @@ int set_bootfile_r(void)
 
 	return 0;
 }
+INIT_FUNC(set_bootfile_r, bootfile, *env_reloc);
 
 int set_load_addr_r(void)
 {
@@ -215,3 +228,4 @@ int set_load_addr_r(void)
 
 	return 0;
 }
+INIT_FUNC(set_load_addr_r, load_addr, *env_reloc);
diff --git a/arch/x86/lib/init_wrappers.c b/arch/x86/lib/init_wrappers.c
index adee8a4..893b0b9 100644
--- a/arch/x86/lib/init_wrappers.c
+++ b/arch/x86/lib/init_wrappers.c
@@ -36,6 +36,7 @@ int serial_initialize_r(void)
 
 	return 0;
 }
+INIT_FUNC(serial_initialize_r, serial_multi, *RELOC);
 
 int env_relocate_r(void)
 {
@@ -44,6 +45,7 @@ int env_relocate_r(void)
 
 	return 0;
 }
+INIT_FUNC(env_relocate_r, env_reloc, *RELOC *env_init);
 
 
 int pci_init_r(void)
@@ -53,6 +55,7 @@ int pci_init_r(void)
 
 	return 0;
 }
+INIT_FUNC(pci_init_r, pci, *cpu_r);
 
 int jumptable_init_r(void)
 {
@@ -60,6 +63,7 @@ int jumptable_init_r(void)
 
 	return 0;
 }
+INIT_FUNC(jumptable_init_r, jumptable, *malloc);
 
 int pcmcia_init_r(void)
 {
@@ -76,6 +80,7 @@ int kgdb_init_r(void)
 
 	return 0;
 }
+INIT_FUNC(kgdb_init_r, kgdb, *std_io *exceptions -enable_interrupts);
 
 int enable_interrupts_r(void)
 {
@@ -84,6 +89,7 @@ int enable_interrupts_r(void)
 
 	return 0;
 }
+INIT_FUNC(enable_interrupts_r, enable_interrupts, *interrupts);
 
 int eth_initialize_r(void)
 {
@@ -92,6 +98,7 @@ int eth_initialize_r(void)
 
 	return 0;
 }
+INIT_FUNC(eth_initialize_r, eth, *pci);
 
 int reset_phy_r(void)
 {
@@ -102,6 +109,7 @@ int reset_phy_r(void)
 
 	return 0;
 }
+INIT_FUNC(reset_phy_r, phy_reset, *eth);
 
 int ide_init_r(void)
 {
@@ -110,6 +118,7 @@ int ide_init_r(void)
 
 	return 0;
 }
+INIT_FUNC(ide_init_r, ide, *env_reloc pci);
 
 int scsi_init_r(void)
 {
@@ -118,6 +127,7 @@ int scsi_init_r(void)
 
 	return 0;
 }
+INIT_FUNC(scsi_init_r, scsi, *env_reloc pci);
 
 #ifdef CONFIG_BITBANGMII
 int bb_miiphy_init_r(void)
@@ -126,6 +136,7 @@ int bb_miiphy_init_r(void)
 
 	return 0;
 }
+INIT_FUNC(bb_miiphy_init_r, bb_miiphy, *RELOC);
 #endif
 
 #ifdef CONFIG_POST
diff --git a/arch/x86/lib/relocate.c b/arch/x86/lib/relocate.c
index 200baab..3c7fa79 100644
--- a/arch/x86/lib/relocate.c
+++ b/arch/x86/lib/relocate.c
@@ -45,6 +45,7 @@ int copy_uboot_to_ram(void)
 
 	return 0;
 }
+INIT_FUNC(copy_uboot_to_ram, copy_to_ram, *SDRAM +cache_f_r -RELOC);
 
 int clear_bss(void)
 {
@@ -55,6 +56,7 @@ int clear_bss(void)
 
 	return 0;
 }
+INIT_FUNC(clear_bss, clear_bss, *SDRAM +copy_to_ram -RELOC);
 
 int do_elf_reloc_fixups(void)
 {
@@ -89,3 +91,4 @@ int do_elf_reloc_fixups(void)
 
 	return 0;
 }
+INIT_FUNC(do_elf_reloc_fixups, elf_reloc, *copy_to_ram -RELOC);
diff --git a/board/amirix/ap1000/serial.c b/board/amirix/ap1000/serial.c
index 87003be..8f3bf6c 100644
--- a/board/amirix/ap1000/serial.c
+++ b/board/amirix/ap1000/serial.c
@@ -45,6 +45,7 @@ int serial_init (void)
 
 	return 0;
 }
+INIT_FUNC(serial_init, serial_f, *baudrate_f -SDRAM);
 
 void serial_putc (const char c)
 {
diff --git a/board/bmw/serial.c b/board/bmw/serial.c
index 0c97f12..f73a8f7 100644
--- a/board/bmw/serial.c
+++ b/board/bmw/serial.c
@@ -46,6 +46,7 @@ int serial_init (void)
 
 	return (0);
 }
+INIT_FUNC(serial_init, serial_f, *baudrate_f -SDRAM);
 
 void serial_putc (const char c)
 {
diff --git a/board/eNET/eNET.c b/board/eNET/eNET.c
index 429fe1b..3caee71 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(board_early_init_f, board_early_f, *cpu_f -SDRAM);
 
 static void enet_setup_pars(void)
 {
@@ -161,6 +162,7 @@ int board_early_init_r(void)
 
 	return 0;
 }
+INIT_FUNC(board_early_init_r, board_early_r, *interrupts -pci);
 
 void show_boot_progress(int val)
 {
@@ -191,6 +193,7 @@ int last_stage_init(void)
 
 	return 0;
 }
+INIT_FUNC(last_stage_init, last_stage, **);
 
 ulong board_flash_get_legacy(ulong base, int banknum, flash_info_t *info)
 {
diff --git a/common/console.c b/common/console.c
index 1d9fd7f..831eaa7 100644
--- a/common/console.c
+++ b/common/console.c
@@ -596,6 +596,7 @@ int console_init_f(void)
 
 	return 0;
 }
+INIT_FUNC(console_init_f, console_f, *serial_f -SDRAM);
 
 void stdio_print_current_devices(void)
 {
@@ -783,5 +784,6 @@ int console_init_r(void)
 
 	return 0;
 }
+INIT_FUNC(console_init_r, console_r, *std_io);
 
 #endif /* CONFIG_SYS_CONSOLE_IS_IN_ENV */
diff --git a/common/env_dataflash.c b/common/env_dataflash.c
index 3c5af37..8fe4379 100644
--- a/common/env_dataflash.c
+++ b/common/env_dataflash.c
@@ -114,3 +114,4 @@ int env_init(void)
 
 	return 0;
 }
+INIT_FUNC(env_init, env_init, *board_early_f -SDRAM);
diff --git a/common/env_eeprom.c b/common/env_eeprom.c
index b66bba2..855c378 100644
--- a/common/env_eeprom.c
+++ b/common/env_eeprom.c
@@ -289,3 +289,4 @@ int env_init(void)
 	return 0;
 }
 #endif
+INIT_FUNC(env_init, env_init, *board_early_f -SDRAM);
diff --git a/common/env_flash.c b/common/env_flash.c
index aa970d4..4f84cd3 100644
--- a/common/env_flash.c
+++ b/common/env_flash.c
@@ -240,6 +240,7 @@ int env_init(void)
 	gd->env_valid	= 0;
 	return 0;
 }
+INIT_FUNC(env_init, env_init, *board_early_f -SDRAM);
 
 #ifdef CMD_SAVEENV
 int saveenv(void)
diff --git a/common/env_mgdisk.c b/common/env_mgdisk.c
index d00e141..d6209f7 100644
--- a/common/env_mgdisk.c
+++ b/common/env_mgdisk.c
@@ -74,3 +74,4 @@ int env_init(void)
 
 	return 0;
 }
+INIT_FUNC(env_init, env_init, *board_early_f -SDRAM);
diff --git a/common/env_mmc.c b/common/env_mmc.c
index 0c58ae1..7722593 100644
--- a/common/env_mmc.c
+++ b/common/env_mmc.c
@@ -62,6 +62,7 @@ int env_init(void)
 
 	return 0;
 }
+INIT_FUNC(env_init, env_init, *board_early_f -SDRAM);
 
 static int init_mmc_for_env(struct mmc *mmc)
 {
diff --git a/common/env_nand.c b/common/env_nand.c
index e8daec9..d88ad09 100644
--- a/common/env_nand.c
+++ b/common/env_nand.c
@@ -134,6 +134,7 @@ int env_init(void)
 
 	return 0;
 }
+INIT_FUNC(env_init, env_init, *board_early_f -SDRAM);
 
 #ifdef CMD_SAVEENV
 /*
diff --git a/common/env_nowhere.c b/common/env_nowhere.c
index 18fcf2c..dce854a 100644
--- a/common/env_nowhere.c
+++ b/common/env_nowhere.c
@@ -49,3 +49,4 @@ int env_init(void)
 
 	return 0;
 }
+INIT_FUNC(env_init, env_init, *board_early_f -SDRAM);
diff --git a/common/env_nvram.c b/common/env_nvram.c
index 6483db3..1e998bb 100644
--- a/common/env_nvram.c
+++ b/common/env_nvram.c
@@ -134,3 +134,4 @@ int env_init(void)
 
 	return 0;
 }
+INIT_FUNC(env_init, env_init, *board_early_f -SDRAM);
diff --git a/common/env_onenand.c b/common/env_onenand.c
index 652665a..5e17a87 100644
--- a/common/env_onenand.c
+++ b/common/env_onenand.c
@@ -135,3 +135,4 @@ int env_init(void)
 
 	return 0;
 }
+INIT_FUNC(env_init, env_init, *board_early_f -SDRAM);
diff --git a/common/env_sf.c b/common/env_sf.c
index bbd472f..b455ed5 100644
--- a/common/env_sf.c
+++ b/common/env_sf.c
@@ -349,3 +349,4 @@ int env_init(void)
 
 	return 0;
 }
+INIT_FUNC(env_init, env_init, *board_early_f -SDRAM);
diff --git a/common/serial.c b/common/serial.c
index 75cc1bb..39bd931 100644
--- a/common/serial.c
+++ b/common/serial.c
@@ -190,6 +190,7 @@ int serial_init(void)
 {
 	return get_current()->init();
 }
+INIT_FUNC(serial_init, serial_f, *baudrate_f -SDRAM);
 
 void serial_setbrg(void)
 {
diff --git a/common/stdio.c b/common/stdio.c
index 1bf9ba0..81d3f21 100644
--- a/common/stdio.c
+++ b/common/stdio.c
@@ -242,3 +242,4 @@ int stdio_init (void)
 
 	return (0);
 }
+INIT_FUNC(stdio_init, std_io, *env_reloc serial_multi);
diff --git a/config.mk b/config.mk
index ddaa477..d781195 100644
--- a/config.mk
+++ b/config.mk
@@ -254,6 +254,8 @@ ifneq ($(CONFIG_SYS_TEXT_BASE),)
 LDFLAGS_u-boot += -Ttext $(CONFIG_SYS_TEXT_BASE)
 endif
 
+LDFLAGS_u-boot-init += -T $(obj)u-boot-init.lds $(LDFLAGS_FINAL)
+
 LDFLAGS_u-boot-spl += -T $(obj)u-boot-spl.lds $(LDFLAGS_FINAL)
 ifneq ($(CONFIG_SPL_TEXT_BASE),)
 LDFLAGS_u-boot-spl += -Ttext $(CONFIG_SPL_TEXT_BASE)
diff --git a/doc/README.INIT_FUNC b/doc/README.INIT_FUNC
new file mode 100644
index 0000000..b545390
--- /dev/null
+++ b/doc/README.INIT_FUNC
@@ -0,0 +1,31 @@
+The INIT_FUNC macro allows initialisation functions (i.e. functions which are
+executed before the main loop) to be easily added to the init sequence
+
+The format of the INIT_FUNC macro is:
+
+INIT_FUNC({function_name}, {init_class}, {prerequisite init_class(es)})
+
+{function_name} is the name of the init function to call. This function must
+have the following prototype:
+
+int foo(void);
+
+Each init function must return 0 to indicate success - any other return value
+indicates failure and the init sequence will stop
+
+{init_class} is a simple test string to describe the basic purpose of the init
+function. Multiple init functions may share the same init_class string
+
+{prerequisite init_class(es)} is a list of init_class strings (see above) which
+defines what init functions are executed before and after the given init
+function. Each prerequisite init_class is seperated by a space and preceeded by
+either:
+ * - At least one function of this init class must exist (i.e. there must be at
+     least one INIT_FUNC entry with {init_class} set to the init class named
+     after the '*' - All init functions with an init class matching the class
+     named after the '*' will be executed before this function
+ + - All init functions with an init class matching the class named after the
+     '+' will be executed before this function, but there does not need to be
+     any functions with the named init class in the init sequence
+ - - This function will be called before any other functions with the init
+     class named after the '-'
diff --git a/include/initcall.h b/include/initcall.h
new file mode 100644
index 0000000..a81cf21
--- /dev/null
+++ b/include/initcall.h
@@ -0,0 +1,19 @@
+#ifndef __INIT_CALL_H__
+#define __INIT_CALL_H__
+#include <linux/compiler.h>
+#define INIT_FUNC(fn, init_name, deps) \
+	static const char __init_func_ ## fn[] __used \
+	__attribute__((__section__(".initfuncs"))) = \
+	"(" #fn ":" #init_name ";" #deps ")\n";
+
+#define SKIP_INIT(init_name) \
+	static const char __skip_init_ ## req[] __used \
+	__attribute__((__section__(".initfuncs"))) = \
+	"{" #init_name "}\n";
+
+#define REPLACE_INIT(old_func, new_func) \
+	static const char __replace_init_ ## old_func[] __used \
+	__attribute__((__section__(".initfuncs"))) = \
+	"[" #old_func "," #new_func "]\n";
+
+#endif /* !__INIT_CALL_H__ */
diff --git a/tools/Makefile b/tools/Makefile
index 64bcc4d..20afcef 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -68,6 +68,7 @@ BIN_FILES-$(CONFIG_CMD_LOADS) += img2srec$(SFX)
 BIN_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes$(SFX)
 BIN_FILES-y += mkenvimage$(SFX)
 BIN_FILES-y += mkimage$(SFX)
+BIN_FILES-y += mkinitseq$(SFX)
 BIN_FILES-$(CONFIG_MX28) += mxsboot$(SFX)
 BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX)
 BIN_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1$(SFX)
@@ -94,6 +95,7 @@ NOPED_OBJ_FILES-y += imximage.o
 NOPED_OBJ_FILES-y += omapimage.o
 NOPED_OBJ_FILES-y += mkenvimage.o
 NOPED_OBJ_FILES-y += mkimage.o
+NOPED_OBJ_FILES-y += mkinitseq.o
 OBJ_FILES-$(CONFIG_MX28) += mxsboot.o
 OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o
 NOPED_OBJ_FILES-y += os_support.o
@@ -213,6 +215,10 @@ $(obj)mkimage$(SFX):	$(obj)aisimage.o \
 	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
 	$(HOSTSTRIP) $@
 
+$(obj)mkinitseq$(SFX):	$(obj)mkinitseq.o
+	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
+	$(HOSTSTRIP) $@
+
 $(obj)mpc86x_clk$(SFX):	$(obj)mpc86x_clk.o
 	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
 	$(HOSTSTRIP) $@
diff --git a/tools/mkinitseq.c b/tools/mkinitseq.c
new file mode 100644
index 0000000..1ee7d4c
--- /dev/null
+++ b/tools/mkinitseq.c
@@ -0,0 +1,278 @@
+/*
+ * (C) Copyright 2008 Semihalf
+ *
+ * (C) Copyright 2000-2009
+ * DENX Software Engineering
+ * Wolfgang Denk, wd at denx.de
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "os_support.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+#include <linux/list.h>
+
+#undef MKINITSEQ_DEBUG
+
+#ifdef MKINITSEQ_DEBUG
+#define debug(fmt,args...)	printf (fmt ,##args)
+#else
+#define debug(fmt,args...)
+#endif /* MKINITSEQ_DEBUG */
+
+#include <version.h>
+
+enum INIT_DEP_TYPE {
+	none,
+	pre_req_mandatory,
+	pre_req_optional,
+	post_req
+};
+
+struct init_dep {
+	struct list_head list;
+
+	enum INIT_DEP_TYPE dep_type;
+	char *init_id;
+};
+
+struct init_function {
+	struct list_head list;
+	char *function_name;
+	char *init_id;
+	struct init_dep deps;
+};
+
+
+static struct init_dep *create_init_dep(unsigned char *ptr,
+					int dep_id_start,
+					int dep_id_end,
+					enum INIT_DEP_TYPE dep_type)
+{
+	struct init_dep *tmp_dep;
+
+	tmp_dep = (struct init_dep *)malloc(sizeof(struct init_dep));
+
+	tmp_dep->dep_type = dep_type;
+
+	tmp_dep->init_id = (char *)malloc(dep_id_end - dep_id_start + 2);
+	memcpy(tmp_dep->init_id, &ptr[dep_id_start], dep_id_end - dep_id_start + 2);
+	tmp_dep->init_id[dep_id_end - dep_id_start + 1] = 0x00;
+
+	switch(dep_type) {
+	case pre_req_mandatory:
+		printf("Found Mandatory Pre-Req.: %s\n", tmp_dep->init_id);
+		break;
+
+	case pre_req_optional:
+		printf("Found Optional Pre-Req.: %s\n", tmp_dep->init_id);
+		break;
+
+	case post_req:
+		printf("Found Post Pre-Req.: %s\n", tmp_dep->init_id);
+		break;
+
+	case none:
+		printf("No dep type: %s\n", tmp_dep->init_id);
+		break;
+	}
+
+	return tmp_dep;
+}
+
+
+int main (int argc, char **argv)
+{
+	int init_funcs;
+	struct stat sbuf;
+	unsigned char *ptr;
+	int i;
+
+	printf("Generating init sequence from %s\n", argv[1]);
+
+	if ((init_funcs = open(argv[1], O_RDONLY|O_BINARY)) < 0) {
+		fprintf (stderr, "%s: Can't open %s: %s\n",
+			 argv[0], argv[1], strerror(errno));
+		exit (EXIT_FAILURE);
+	}
+
+	if (fstat(init_funcs, &sbuf) < 0) {
+		fprintf (stderr, "%s: Can't stat %s: %s\n",
+			 argv[0], argv[1], strerror(errno));
+		exit (EXIT_FAILURE);
+	}
+
+	ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, init_funcs, 0);
+	if (ptr == MAP_FAILED) {
+		fprintf (stderr, "%s: Can't read %s: %s\n",
+			 argv[0], argv[1], strerror(errno));
+		exit (EXIT_FAILURE);
+	}
+
+	struct init_function init_functions;
+	INIT_LIST_HEAD(&init_functions.list);
+
+	int function_name_start = 0;
+	int function_name_end = 0;
+	int init_id_start = 0;
+	int init_id_end = 0;
+	struct init_function *tmp;
+	struct init_dep *tmp_dep;
+	enum INIT_DEP_TYPE dep_type = none;
+	int dep_id_start = -1;
+	int dep_id_end = -1;
+	int mandatory_dep_found = -1;
+
+	for(i = 0; i < sbuf.st_size; i++) {
+
+//		if(ptr[i])
+//			printf("%c", ptr[i]);
+
+		switch(ptr[i]) {
+		case '(':
+			function_name_start = i + 1;
+			break;
+		case ':':
+			function_name_end = i - 1;
+			init_id_start = i + 1;
+			break;
+		case ';':
+			init_id_end = i - 1;
+			tmp = (struct init_function *)malloc(sizeof(struct init_function));
+
+			INIT_LIST_HEAD(&tmp->deps.list);
+
+			tmp->function_name = (char *)malloc(function_name_end - function_name_start + 2);
+			memcpy(tmp->function_name, &ptr[function_name_start], function_name_end - function_name_start + 2);
+			tmp->function_name[function_name_end - function_name_start + 1] = 0x00;
+
+			tmp->init_id = (char *)malloc(init_id_end - init_id_start + 2);
+			memcpy(tmp->init_id, &ptr[init_id_start], init_id_end - init_id_start + 2);
+			tmp->init_id[init_id_end - init_id_start + 1] = 0x00;
+
+			printf("Found function: %s, ID: %s\n", tmp->function_name, tmp->init_id);
+			list_add(&(tmp->list), &(init_functions.list));
+			break;
+
+		case '*':
+			if(dep_id_start > 0) {
+				dep_id_end = i - 1;
+
+				while(ptr[dep_id_end] == ' ')
+					dep_id_end--;
+
+				tmp_dep = create_init_dep(ptr, dep_id_start, dep_id_end, dep_type);
+
+				if(dep_type == pre_req_mandatory)
+					mandatory_dep_found = 1;
+
+				list_add(&(tmp_dep->list), &(tmp->deps.list));
+
+			}
+
+			dep_type = pre_req_mandatory;
+			dep_id_start = i + 1;
+
+			while(ptr[dep_id_start] == ' ')
+				dep_id_start++;
+
+			break;
+
+		case '+':
+			if(dep_id_start > 0) {
+				dep_id_end = i - 1;
+
+				while(ptr[dep_id_end] == ' ')
+					dep_id_end--;
+
+				tmp_dep = create_init_dep(ptr, dep_id_start, dep_id_end, dep_type);
+
+				if(dep_type == pre_req_mandatory)
+					mandatory_dep_found = 1;
+
+				list_add(&(tmp_dep->list), &(tmp->deps.list));
+
+			}
+
+			dep_type = pre_req_optional;
+			dep_id_start = i + 1;
+			break;
+
+		case '-':
+			if(dep_id_start > 0) {
+				dep_id_end = i - 1;
+
+				while(ptr[dep_id_end] == ' ')
+					dep_id_end--;
+
+				tmp_dep = create_init_dep(ptr, dep_id_start, dep_id_end, dep_type);
+
+				if(dep_type == pre_req_mandatory)
+					mandatory_dep_found = 1;
+
+				list_add(&(tmp_dep->list), &(tmp->deps.list));
+
+			}
+
+			dep_type = post_req;
+			dep_id_start = i + 1;
+			break;
+
+		case ')':
+			if(dep_id_start > 0) {
+				dep_id_end = i - 1;
+
+				while(ptr[dep_id_end] == ' ')
+					dep_id_end--;
+
+				tmp_dep = create_init_dep(ptr, dep_id_start, dep_id_end, dep_type);
+
+				if(dep_type == pre_req_mandatory)
+					mandatory_dep_found = 1;
+
+				list_add(&(tmp_dep->list), &(tmp->deps.list));
+
+				if(mandatory_dep_found < 0)
+					printf("Error: No mandatory dependencies specified\n");
+
+			} else {
+				printf("Error: No dependencies specified\n");
+
+			}
+
+			mandatory_dep_found = -1;
+			dep_id_start = -1;
+			tmp = NULL;
+			break;
+
+		default:
+			break;
+		}
+	}
+
+
+
+	(void) munmap((void *)ptr, sbuf.st_size);
+	(void) close (init_funcs);
+	exit (EXIT_SUCCESS);
+}
diff --git a/u-boot-init.lds b/u-boot-init.lds
new file mode 100644
index 0000000..aca6c92
--- /dev/null
+++ b/u-boot-init.lds
@@ -0,0 +1,25 @@
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+SECTIONS
+{
+
+ .initfuncs : { KEEP(*(.initfuncs*)) }
+
+ /DISCARD/ : { *(.text*) }
+ /DISCARD/ : { *(.debug*) }
+ /DISCARD/ : { *(.u_boot_cmd*) }
+ /DISCARD/ : { *(.rodata*) }
+ /DISCARD/ : { *(.data*) }
+ /DISCARD/ : { *(.dynsym*) }
+ /DISCARD/ : { *(.hash*) }
+ /DISCARD/ : { *(.bss*) }
+ /DISCARD/ : { *(.bss) }
+ /DISCARD/ : { *(.rel.dyn*) }
+ /DISCARD/ : { *(.rel.dyn) }
+ /DISCARD/ : { *(.dynstr*) }
+ /DISCARD/ : { *(.dynamic*) }
+ /DISCARD/ : { *(.plt*) }
+ /DISCARD/ : { *(.interp*) }
+ /DISCARD/ : { *(.gnu*) }
+ /DISCARD/ : { *(.comment*) }
+}
-- 
1.7.7.6



More information about the U-Boot mailing list