Skip to contentSkip to conversation

initcall: An outline of the idea

PATCH New Graeme Russ 3 participants 6 messages Mar 2, 2012 – Mar 8, 2012

Subsystems (5)
x86 PowerPC Kbuild MIPS +1 more subsystems
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 initcall: An outline of the idea

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
Makefile +23 -1
index f174996..d07f404 100644
@@ -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) | \
arch/blackfin/cpu/initcode.c +1 -0
index fb3a101..2f4cae5 100644
@@ -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)
arch/blackfin/cpu/serial.c +1 -0
index 6603dc0..89026f2 100644
@@ -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)
 {
arch/mips/cpu/mips32/au1x00/au1x00_serial.c +1 -0
index c25ba5a..d723dbf 100644
@@ -61,6 +61,7 @@ int serial_init (void)
 
 	return 0;
 }
+INIT_FUNC(serial_init, serial_f, *baudrate_f -SDRAM);
 
 
 void serial_setbrg (void)
arch/mips/cpu/mips32/incaip/asc_serial.c +1 -0
index 7239804..21e5cf2 100644
@@ -81,6 +81,7 @@ int serial_init (void)
 
     return 0;
 }
+INIT_FUNC(serial_init, serial_f, *baudrate_f -SDRAM);
 
 void serial_setbrg (void)
 {
arch/mips/cpu/xburst/jz_serial.c +1 -0
index e6c48e0..e306961 100644
@@ -61,6 +61,7 @@ int serial_init(void)
 
 	return 0;
 }
+INIT_FUNC(serial_init, serial_f, *baudrate_f -SDRAM);
 
 void serial_setbrg(void)
 {
arch/powerpc/cpu/mpc512x/serial.c +1 -0
index 7c53346..149ee73 100644
@@ -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)
 {
arch/powerpc/cpu/mpc5xx/serial.c +1 -0
index 88c6db8..14fd66c 100644
@@ -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)
 {
arch/sparc/cpu/leon2/serial.c +1 -0
index 4f41b8e..6ea7abd 100644
@@ -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)
 {
arch/sparc/cpu/leon3/serial.c +1 -0
index 4b2fcb8..327b525 100644
@@ -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)
 {
arch/x86/cpu/cpu.c +2 -2
index e9bb0d7..d96ae1b 100644
@@ -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)
 {
arch/x86/cpu/interrupts.c +1 -0
index 43ec3f8..1414c79 100644
@@ -227,6 +227,7 @@ int cpu_init_interrupts(void)
 
 	return 0;
 }
+INIT_FUNC(cpu_init_interrupts, interrupts, *exceptions);
 
 void __do_irq(int irq)
 {
arch/x86/cpu/sc520/sc520.c +1 -0
index 3fe85e7..8f350d4 100644
@@ -64,3 +64,4 @@ int cpu_init_r(void)
 
 	return x86_cpu_init_r();
 }
+INIT_FUNC(cpu_init_r, cpu_r, *malloc);
arch/x86/cpu/sc520/sc520_sdram.c +2 -0
index 9dc1334..4df602b 100644
@@ -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);
arch/x86/cpu/sc520/sc520_timer.c +1 -0
index 495a694..569f612 100644
@@ -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)
arch/x86/cpu/u-boot.lds +1 -0
index 8abaae1..85fff3c 100644
@@ -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)) }
arch/x86/lib/board.c +1 -133

146 lines not on this page · raw message

arch/x86/lib/init_helpers.c +14 -0
index 9f4dee0..f469e4a 100644
@@ -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);
arch/x86/lib/init_wrappers.c +11 -0
index adee8a4..893b0b9 100644
@@ -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
arch/x86/lib/relocate.c +3 -0
index 200baab..3c7fa79 100644
@@ -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);
board/amirix/ap1000/serial.c +1 -0
index 87003be..8f3bf6c 100644
@@ -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)
 {
board/bmw/serial.c +1 -0
index 0c97f12..f73a8f7 100644
@@ -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)
 {
board/eNET/eNET.c +3 -0
index 429fe1b..3caee71 100644
@@ -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)
 {
common/console.c +2 -0
index 1d9fd7f..831eaa7 100644
@@ -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 */
common/env_dataflash.c +1 -0
index 3c5af37..8fe4379 100644
@@ -114,3 +114,4 @@ int env_init(void)
 
 	return 0;
 }
+INIT_FUNC(env_init, env_init, *board_early_f -SDRAM);
common/env_eeprom.c +1 -0
index b66bba2..855c378 100644
@@ -289,3 +289,4 @@ int env_init(void)
 	return 0;
 }
 #endif
+INIT_FUNC(env_init, env_init, *board_early_f -SDRAM);
common/env_flash.c +1 -0
index aa970d4..4f84cd3 100644
@@ -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)
common/env_mgdisk.c +1 -0
index d00e141..d6209f7 100644
@@ -74,3 +74,4 @@ int env_init(void)
 
 	return 0;
 }
+INIT_FUNC(env_init, env_init, *board_early_f -SDRAM);
common/env_mmc.c +1 -0
index 0c58ae1..7722593 100644
@@ -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)
 {
common/env_nand.c +1 -0
index e8daec9..d88ad09 100644
@@ -134,6 +134,7 @@ int env_init(void)
 
 	return 0;
 }
+INIT_FUNC(env_init, env_init, *board_early_f -SDRAM);
 
 #ifdef CMD_SAVEENV
 /*
common/env_nowhere.c +1 -0
index 18fcf2c..dce854a 100644
@@ -49,3 +49,4 @@ int env_init(void)
 
 	return 0;
 }
+INIT_FUNC(env_init, env_init, *board_early_f -SDRAM);
common/env_nvram.c +1 -0
index 6483db3..1e998bb 100644
@@ -134,3 +134,4 @@ int env_init(void)
 
 	return 0;
 }
+INIT_FUNC(env_init, env_init, *board_early_f -SDRAM);
common/env_onenand.c +1 -0
index 652665a..5e17a87 100644
@@ -135,3 +135,4 @@ int env_init(void)
 
 	return 0;
 }
+INIT_FUNC(env_init, env_init, *board_early_f -SDRAM);
common/env_sf.c +1 -0
index bbd472f..b455ed5 100644
@@ -349,3 +349,4 @@ int env_init(void)
 
 	return 0;
 }
+INIT_FUNC(env_init, env_init, *board_early_f -SDRAM);
common/serial.c +1 -0
index 75cc1bb..39bd931 100644
@@ -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)
 {
common/stdio.c +1 -0
index 1bf9ba0..81d3f21 100644
@@ -242,3 +242,4 @@ int stdio_init (void)
 
 	return (0);
 }
+INIT_FUNC(stdio_init, std_io, *env_reloc serial_multi);
config.mk +2 -0
index ddaa477..d781195 100644
@@ -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)
doc/README.INIT_FUNC new file +31 -0
new file mode 100644
index 0000000..b545390
@@ -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 '-'
include/initcall.h new file +19 -0
new file mode 100644
index 0000000..a81cf21
@@ -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__ */
tools/Makefile +6 -0
index 64bcc4d..20afcef 100644
@@ -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) $@
tools/mkinitseq.c new file +278 -0

278 lines not on this page · raw message

u-boot-init.lds new file +25 -0
new file mode 100644
index 0000000..aca6c92
@@ -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*) }
+}
Signature · 1 line
1.7.7.6
#1 lore raw

PATCH 1/1 initcall: An outline of the idea

Hi Graeme,

Quoted 27 lines · Graeme Russ
doc/README.INIT_FUNC new file +21 -0
new file mode 100644
index 0000000..b545390
@@ -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

doc/README.INIT_FUNC line 31

Quoted 10 lines
doc/README.INIT_FUNC new file +10 -0
+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 '-'

What happens if there's a set of dependencies that cannot be resolved? From reading the above, it seems I can do something like this:

INIT_FUNC(ifunc1, class1, *class2);
INIT_FUNC(ifunc2, class2, *class1);

It would also seem that if you want to change the prerequisites for a given init_class, you need to find every instance of INIT_FUNC for that init_class and change it.

Perhaps there's a better way of solving this, but it maybe there should be a separate place which names the init classes and their prerequisites?

Quoted 15 lines
include/initcall.h new file +9 -0
new file mode 100644
index 0000000..a81cf21
@@ -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) \

include/initcall.h line 19

Quoted 10 lines
include/initcall.h new file +10 -0
+	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__ */

What are SKIP_INIT() and REPLACE_INIT() used for?

Perhaps the macro could be expanded to include a prototype for the function, so that gcc complains with a useful error message if there's a type mismatch.

Bye for now,

Signature · 3 lines
Laurence Withers, <[email protected]>                http://www.guralp.com/
Direct tel:+447753988197 or tel:+443333408643               Software Engineer
General support queries: <[email protected]>         CMG-DCM CMG-EAM CMG-NAM
#2 lore raw

PATCH 1/1 initcall: An outline of the idea

Hi Laurence,

Quoted 35 lines · Laurence Withers

Hi Graeme,

Quoted 32 lines · Graeme Russ
doc/README.INIT_FUNC new file +26 -0
new file mode 100644
index 0000000..b545390
@@ -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
Quoted 8 lines

doc/README.INIT_FUNC line 31

Quoted 5 lines
doc/README.INIT_FUNC new file +5 -0
+ + - 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 '-'

What happens if there's a set of dependencies that cannot be resolved? From reading the above, it seems I can do something like this:

tools/mkinitseq would return an error - It would be akin to a compilation error

Quoted 2 lines

INIT_FUNC(ifunc1, class1, *class2);
INIT_FUNC(ifunc2, class2, *class1);

What you need to keep in mind is that currently the init sequences are maintained as a fixed array of function pointers (except in one corner case arch, but that can be fixed) so you could just name the classes 'class1', 'class2', 'class3' and build the existing init sequences as-is. But there is no guarantee the order is the same for all the arches, hence the desire to group like functions together.

The dependencies are not really that complicated, so I don't imagine there will be much difficultly in getting the current sequences migrated.

It's when someone adds a board specific init function that things might get interesting...

Quoted 3 lines

It would also seem that if you want to change the prerequisites for a given init_class, you need to find every instance of INIT_FUNC for that init_class and change it.

Yes, but this would be rare - The idea of init class is to say, for example, 'PCI must be initialised before Ethernet' - The chance of this dependency rule changing is very low

Quoted 2 lines

Perhaps there's a better way of solving this, but it maybe there should be a separate place which names the init classes and their prerequisites?

Some board, SoCs or arches _may_ need slightly different prerequisites - For example, arch 'A' may need GPIO before PCI while arch 'B' may need PCI before GPIO

Quoted 20 lines
Quoted 20 lines
include/initcall.h new file +13 -0
new file mode 100644
index 0000000..a81cf21
@@ -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";
+
Quoted 8 lines

include/initcall.h line 19

Quoted 6 lines
include/initcall.h new file +6 -0
+#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__ */

What are SKIP_INIT() and REPLACE_INIT() used for?

Glad you asked :) - They are more advanced functions...

SKIP_INIT() drops all initialisation of a given init class - This allows a board to completely override an init class normally defined by the arch, SoC or CPU

REPLACE_INIT() replaces one init function with another - It is similar to weak functions

Quoted 2 lines

Perhaps the macro could be expanded to include a prototype for the function,

How so - Can you provide a code example?

Quoted 1 line

so that gcc complains with a useful error message if there's a type mismatch.

The type mismatch will be flagged when the file generated by mkinitseq is compiled - All functions are int foo(void)

Quoted 2 lines

Bye for now,

Thanks & Regards,

Graeme

#3 lore raw

PATCH 1/1 initcall: An outline of the idea

Quoted 3 lines · Graeme Russ
Quoted 1 line

Perhaps the macro could be expanded to include a prototype for the function,

How so - Can you provide a code example?

Sure, since all the functions are int(*)(void), just something like this:

+#define INIT_FUNC(fn, init_name, deps) \

+    static int ##fn (void); \
+    static const char __init_func_ ## fn[] __used \
+    __attribute__((__section__(".initfuncs"))) = \
+    "(" #fn ":" #init_name ";" #deps ")\n";

(I'm guessing static is OK for this use case?).

The patch overall looks like it will make it a lot simpler to understand and change the sequence initialisation functions are called, which is a very good thing. I'm just mindful of getting easy-to-diagnose error messages back when things go wrong.

An example:

	static int f1(int x)
	{
		return x + 1;
	}

	#define INIT_FUNC(fn) \
		static void fn(int)

	INIT_FUNC(f1);

gcc immediately throws the following error:

t2.c:9: error: conflicting types for ?f1? t2.c:1: note: previous definition of ?f1? was here

which is pretty clear.

Bye for now,

Signature · 3 lines
Laurence Withers, <[email protected]>                http://www.guralp.com/
Direct tel:+447753988197 or tel:+443333408643               Software Engineer
General support queries: <[email protected]>         CMG-DCM CMG-EAM CMG-NAM
#4 lore raw

PATCH 1/1 initcall: An outline of the idea

Review

Quoted 2 lines · Laurence Withers
(quoted diff) +2 -0
+#define INIT_FUNC(fn, init_name, deps) \
+    static int ##fn (void); \
                  ^^

Excuse the macro catenation operator; that shouldn't be there. Hopefully the example made it clear.

Bye for now,

Signature · 3 lines
Laurence Withers, <[email protected]>                http://www.guralp.com/
Direct tel:+447753988197 or tel:+443333408643               Software Engineer
General support queries: <[email protected]>         CMG-DCM CMG-EAM CMG-NAM
#5 lore raw

PATCH 1/1 initcall: An outline of the idea

In reply to Graeme Russ

Hi Graeme,

Quoted 51 lines · Graeme Russ

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 +++
Quoted 6 lines

?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

I read through this and it looks pretty nice. No point in commenting on the code at this stage I suspect.

But I wonder if this could fit on top of the generic board init series? Then we could move to initcalls for all boards rather than just x86, and in fact for U-Boot as a whole.

Plus a few questions. What tool do we need to display the result init sequence at build time? Can we make U-Boot print out the initcalls as it runs them (perhaps with pre-console buffer)?

Hoping you can pull this off!

Regards,
Simon