From patchwork Fri Mar 2 11:05:12 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Graeme Russ X-Patchwork-Id: 144219 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 4CDFB1007D3 for ; Fri, 2 Mar 2012 22:05:33 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id F1AA5280D8; Fri, 2 Mar 2012 12:05:27 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id K9dwRYAYiYFW; Fri, 2 Mar 2012 12:05:27 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 04682280C0; Fri, 2 Mar 2012 12:05:26 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 81CBC280C0 for ; Fri, 2 Mar 2012 12:05:23 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ZzVA8eMmJs6a for ; Fri, 2 Mar 2012 12:05:22 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-pz0-f44.google.com (mail-pz0-f44.google.com [209.85.210.44]) by theia.denx.de (Postfix) with ESMTPS id 5CF55280AB for ; Fri, 2 Mar 2012 12:05:20 +0100 (CET) Received: by dakl33 with SMTP id l33so1782721dak.3 for ; Fri, 02 Mar 2012 03:05:18 -0800 (PST) Received-SPF: pass (google.com: domain of graeme.russ@gmail.com designates 10.68.195.99 as permitted sender) client-ip=10.68.195.99; Authentication-Results: mr.google.com; spf=pass (google.com: domain of graeme.russ@gmail.com designates 10.68.195.99 as permitted sender) smtp.mail=graeme.russ@gmail.com; dkim=pass header.i=graeme.russ@gmail.com Received: from mr.google.com ([10.68.195.99]) by 10.68.195.99 with SMTP id id3mr14006127pbc.149.1330686318948 (num_hops = 1); Fri, 02 Mar 2012 03:05:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer; bh=ru1RTQCdddxFIwRd5EymPJCfHsCm7K9H2qQ1ESZcwb0=; b=HuRK4cmwUGdldpz6F9vGL6FAymXm3CFcj5sj7a11juFg++zdumzFokIcdHCayqYY+p aCZLslADxIakd4JRWouP01XVWctQbLRfpeX+isuKWisXeROHL6nd3fTJ+TT++KbRHH5J Ye3sKCF3ZKOHQPXc4x9X1Yz2xWp2mB1UXTwuPHhHWiMiolDEimaWquUDR/5Djgy/CGRc qo+OPgvRZlJXVpWY8/X6gwE8/SaqxANnxZeY8hLZIotcjzTk2loxJJqEaFOMpoEslE4i YUQfscveA2h/GztMuFY0C6AvQqcw95VdspHY2X6qsVIP6SXrqgLHzuUbeHlSDiS313me sgSA== Received: by 10.68.195.99 with SMTP id id3mr11628873pbc.149.1330686318425; Fri, 02 Mar 2012 03:05:18 -0800 (PST) Received: from dingo.localhost (d58-106-94-125.sbr801.nsw.optusnet.com.au. [58.106.94.125]) by mx.google.com with ESMTPS id h2sm4275674pbv.18.2012.03.02.03.05.16 (version=SSLv3 cipher=OTHER); Fri, 02 Mar 2012 03:05:17 -0800 (PST) From: Graeme Russ To: u-boot@lists.denx.de Date: Fri, 2 Mar 2012 22:05:12 +1100 Message-Id: <1330686312-28712-1-git-send-email-graeme.russ@gmail.com> X-Mailer: git-send-email 1.7.7.6 Subject: [U-Boot] [WIP, PATCH] initcall: An outline of the idea X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de 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 #include +#include /* * 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 +#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@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 +#include +#include +#include +#include +#include +#include +#include +#include + +#undef MKINITSEQ_DEBUG + +#ifdef MKINITSEQ_DEBUG +#define debug(fmt,args...) printf (fmt ,##args) +#else +#define debug(fmt,args...) +#endif /* MKINITSEQ_DEBUG */ + +#include + +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*) } +}