initcall: An outline of the idea
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -242,3 +242,4 @@ int stdio_init (void)return (0 ); } +INIT_FUNC(stdio_init, std_io, *env_reloc serial_multi);
config.mk +2 -0
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 1/1 initcall: An outline of the idea
Hi Graeme,
Quoted 27 lines · Graeme Russ
doc/README.INIT_FUNC new file +21
-0@@ -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@@ -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
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@@ -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 ofINIT_FUNCfor thatinit_classand 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@@ -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()andREPLACE_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
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
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
PATCH 1/1 initcall: An outline of the idea
In reply to Graeme RussHi 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_FUNCimplementation will look like.Ultimately,
tools/mkinitseq.cwill process the dependencies and generate a C file containing the three init sequence arrays which have been deleted fromarch/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 100644tools/mkinitseq.c
?create mode 100644u-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