[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