diff --git a/arch/arm/boards/animeo_ip/init.c b/arch/arm/boards/animeo_ip/init.c index 0fda013..2069ab3 100644 --- a/arch/arm/boards/animeo_ip/init.c +++ b/arch/arm/boards/animeo_ip/init.c @@ -346,6 +346,7 @@ animeo_ip_shutdown_uart(IOMEM(AT91SAM9260_BASE_US0)); animeo_ip_shutdown_uart(IOMEM(AT91SAM9260_BASE_US1)); } +postdevshutdown_exitcall(animeo_ip_shutdown); static int animeo_ip_console_init(void) { @@ -353,7 +354,6 @@ usart0 = at91_register_uart(1, ATMEL_UART_RTS); usart1 = at91_register_uart(2, ATMEL_UART_RTS); - board_shutdown = animeo_ip_shutdown; barebox_set_model("Somfy Animeo IP"); barebox_set_hostname("animeoip"); diff --git a/arch/arm/cpu/cpu.c b/arch/arm/cpu/cpu.c index badd676..5e70802 100644 --- a/arch/arm/cpu/cpu.c +++ b/arch/arm/cpu/cpu.c @@ -93,7 +93,7 @@ * This function is called by shutdown_barebox to get a clean * memory/cache state. */ -void arch_shutdown(void) +static void arch_shutdown(void) { uint32_t r; @@ -108,6 +108,7 @@ r |= PSR_I_BIT; __asm__ __volatile__("msr cpsr, %0" : : "r"(r)); } +archshutdown_exitcall(arch_shutdown); extern unsigned long arm_stack_top; diff --git a/arch/arm/include/asm/common.h b/arch/arm/include/asm/common.h index 9ff3b19..07ae619 100644 --- a/arch/arm/include/asm/common.h +++ b/arch/arm/include/asm/common.h @@ -1,8 +1,6 @@ #ifndef __ASM_ARM_COMMON_H #define __ASM_ARM_COMMON_H -#define ARCH_SHUTDOWN - static inline unsigned long get_pc(void) { unsigned long pc; diff --git a/arch/arm/lib/barebox.lds.S b/arch/arm/lib/barebox.lds.S index bb0354a..5344557 100644 --- a/arch/arm/lib/barebox.lds.S +++ b/arch/arm/lib/barebox.lds.S @@ -90,6 +90,10 @@ .barebox_initcalls : { INITCALLS } __barebox_initcalls_end = .; + __barebox_exitcalls_start = .; + .barebox_exitcalls : { EXITCALLS } + __barebox_exitcalls_end = .; + __usymtab_start = .; __usymtab : { BAREBOX_SYMS } __usymtab_end = .; diff --git a/arch/blackfin/boards/ipe337/barebox.lds.S b/arch/blackfin/boards/ipe337/barebox.lds.S index 9bb7cc4..51a586a 100644 --- a/arch/blackfin/boards/ipe337/barebox.lds.S +++ b/arch/blackfin/boards/ipe337/barebox.lds.S @@ -76,6 +76,10 @@ .barebox_initcalls : { INITCALLS } ___barebox_initcalls_end = .; + ___barebox_exitcalls_start = .; + .barebox_exitcalls : { EXITCALLS } + ___barebox_exitcalls_end = .; + ___usymtab_start = .; __usymtab : { BAREBOX_SYMS } ___usymtab_end = .; diff --git a/arch/blackfin/include/asm/common.h b/arch/blackfin/include/asm/common.h index fa58e37..443adf7 100644 --- a/arch/blackfin/include/asm/common.h +++ b/arch/blackfin/include/asm/common.h @@ -1,5 +1 @@ - -/* We have to disable instruction cache before - * executing an external program - */ -#define ARCH_SHUTDOWN +/* nothing special */ diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c index 88ad618..3a04f28 100644 --- a/arch/blackfin/lib/board.c +++ b/arch/blackfin/lib/board.c @@ -38,7 +38,11 @@ start_barebox(); } -void arch_shutdown(void) +/* We have to disable instruction cache before + * executing an external program + */ +static void arch_shutdown(void) { icache_disable(); } +archshutdown_exitcall(arch_shutdown); diff --git a/arch/efi/lib/elf_ia32_efi.lds.S b/arch/efi/lib/elf_ia32_efi.lds.S index a5f6287..69f43f5 100644 --- a/arch/efi/lib/elf_ia32_efi.lds.S +++ b/arch/efi/lib/elf_ia32_efi.lds.S @@ -56,6 +56,10 @@ __barebox_initcalls : { INITCALLS } __barebox_initcalls_end = .; + __barebox_exitcalls_start = .; + __barebox_exitcalls : { EXITCALLS } + __barebox_exitcalls_end = .; + . = ALIGN(64); __barebox_magicvar_start = .; .barebox_magicvar : { BAREBOX_MAGICVARS } diff --git a/arch/efi/lib/elf_x86_64_efi.lds.S b/arch/efi/lib/elf_x86_64_efi.lds.S index d48432d..9aa4e8d 100644 --- a/arch/efi/lib/elf_x86_64_efi.lds.S +++ b/arch/efi/lib/elf_x86_64_efi.lds.S @@ -58,6 +58,10 @@ __barebox_initcalls : { INITCALLS } __barebox_initcalls_end = .; + __barebox_exitcalls_start = .; + __barebox_exitcalls : { EXITCALLS } + __barebox_exitcalls_end = .; + . = ALIGN(64); __barebox_magicvar_start = .; .barebox_magicvar : { BAREBOX_MAGICVARS } diff --git a/arch/mips/lib/barebox.lds.S b/arch/mips/lib/barebox.lds.S index c690e71..8057634 100644 --- a/arch/mips/lib/barebox.lds.S +++ b/arch/mips/lib/barebox.lds.S @@ -67,6 +67,10 @@ .barebox_initcalls : { INITCALLS } __barebox_initcalls_end = .; + __barebox_exitcalls_start = .; + .barebox_exitcalls : { EXITCALLS } + __barebox_exitcalls_end = .; + __usymtab_start = .; __usymtab : { BAREBOX_SYMS } __usymtab_end = .; diff --git a/arch/nios2/cpu/barebox.lds.S b/arch/nios2/cpu/barebox.lds.S index 943c507..a2d7fa8 100644 --- a/arch/nios2/cpu/barebox.lds.S +++ b/arch/nios2/cpu/barebox.lds.S @@ -63,6 +63,10 @@ .barebox_initcalls : { INITCALLS } __barebox_initcalls_end = .; + __barebox_exitcalls_start = .; + .barebox_exitcalls : { EXITCALLS } + __barebox_exitcalls_end = .; + ___usymtab_start = .; __usymtab : { BAREBOX_SYMS } ___usymtab_end = .; diff --git a/arch/nios2/lib/board.c b/arch/nios2/lib/board.c index 7c4dc76..537675c 100644 --- a/arch/nios2/lib/board.c +++ b/arch/nios2/lib/board.c @@ -30,7 +30,3 @@ start_barebox(); } - -void arch_shutdown(void) -{ -} diff --git a/arch/openrisc/cpu/barebox.lds.S b/arch/openrisc/cpu/barebox.lds.S index 9c353f3..b819ca0 100644 --- a/arch/openrisc/cpu/barebox.lds.S +++ b/arch/openrisc/cpu/barebox.lds.S @@ -65,6 +65,10 @@ .barebox_initcalls : { INITCALLS } > ram __barebox_initcalls_end = .; + __barebox_exitcalls_start = .; + .barebox_exitcalls : { EXITCALLS } > ram + __barebox_exitcalls_end = .; + ___usymtab_start = .; __usymtab : { BAREBOX_SYMS } > ram ___usymtab_end = .; diff --git a/arch/openrisc/lib/board.c b/arch/openrisc/lib/board.c index 98033b4..25bcc05 100644 --- a/arch/openrisc/lib/board.c +++ b/arch/openrisc/lib/board.c @@ -29,7 +29,3 @@ start_barebox(); } - -void arch_shutdown(void) -{ -} diff --git a/arch/ppc/boards/pcm030/barebox.lds.S b/arch/ppc/boards/pcm030/barebox.lds.S index 1332ad1..0e08e05 100644 --- a/arch/ppc/boards/pcm030/barebox.lds.S +++ b/arch/ppc/boards/pcm030/barebox.lds.S @@ -112,6 +112,11 @@ __barebox_initcalls_end = .; __initcall_entries = (__barebox_initcalls_end - __barebox_initcalls_start) >> 2; + __barebox_exitcalls_start = .; + .barebox_exitcalls : { EXITCALLS } + __barebox_exitcalls_end = .; + __exitcall_entries = (__barebox_exitcalls_end - __barebox_exitcalls_start) >> 2; + __usymtab_start = .; __usymtab : { BAREBOX_SYMS } __usymtab_end = .; diff --git a/arch/ppc/mach-mpc85xx/barebox.lds.S b/arch/ppc/mach-mpc85xx/barebox.lds.S index 87ab7ac..1f7f52c 100644 --- a/arch/ppc/mach-mpc85xx/barebox.lds.S +++ b/arch/ppc/mach-mpc85xx/barebox.lds.S @@ -109,6 +109,11 @@ __barebox_initcalls_end = .; __initcall_entries = (__barebox_initcalls_end - __barebox_initcalls_start)>>2; + __barebox_exitcalls_start = .; + .barebox_exitcalls : { EXITCALLS } + __barebox_exitcalls_end = .; + __exitcall_entries = (__barebox_exitcalls_end - __barebox_exitcalls_start) >> 2; + __usymtab_start = .; __usymtab : { BAREBOX_SYMS } __usymtab_end = .; diff --git a/arch/sandbox/board/barebox.lds.S b/arch/sandbox/board/barebox.lds.S index db5b7de..0d67ab6 100644 --- a/arch/sandbox/board/barebox.lds.S +++ b/arch/sandbox/board/barebox.lds.S @@ -8,6 +8,11 @@ __barebox_initcalls_end = .; . = ALIGN(64); + __barebox_exitcalls_start = .; + __barebox_exitcalls : { EXITCALLS } + __barebox_exitcalls_end = .; + + . = ALIGN(64); __barebox_magicvar_start = .; .barebox_magicvar : { BAREBOX_MAGICVARS } __barebox_magicvar_end = .; diff --git a/arch/x86/lib/barebox.lds.S b/arch/x86/lib/barebox.lds.S index 6cf6b10..23d7546 100644 --- a/arch/x86/lib/barebox.lds.S +++ b/arch/x86/lib/barebox.lds.S @@ -185,7 +185,14 @@ . = ALIGN(4); } > barebox - .__usymtab : AT ( LOADADDR(.barebox_initcalls) + SIZEOF (.barebox_initcalls) ) { + .barebox_exitcalls : AT ( LOADADDR(.barebox_initcalls) + SIZEOF (.barebox_initcalls) ) { + __barebox_exitcalls_start = .; + EXITCALLS + __barebox_exitcalls_end = .; + . = ALIGN(4); + } > barebox + + .__usymtab : AT ( LOADADDR(.barebox_exitcalls) + SIZEOF (.barebox_exitcalls) ) { __usymtab_start = .; BAREBOX_SYMS __usymtab_end = .; diff --git a/common/startup.c b/common/startup.c index 6178fc5..802b90e 100644 --- a/common/startup.c +++ b/common/startup.c @@ -45,6 +45,9 @@ extern initcall_t __barebox_initcalls_start[], __barebox_early_initcalls_end[], __barebox_initcalls_end[]; +extern exitcall_t __barebox_exitcalls_start[], __barebox_exitcalls_end[]; + + #if defined CONFIG_FS_RAMFS && defined CONFIG_FS_DEVFS static int mount_root(void) { @@ -132,18 +135,17 @@ for (;;); } -void (*board_shutdown)(void); - /* Everything needed to cleanly shutdown barebox. * Should be called before starting an OS to get * the devices into a clean state */ void shutdown_barebox(void) { - devices_shutdown(); -#ifdef ARCH_SHUTDOWN - arch_shutdown(); -#endif - if (board_shutdown) - board_shutdown(); + exitcall_t *exitcall; + + for (exitcall = __barebox_exitcalls_start; + exitcall < __barebox_exitcalls_end; exitcall++) { + pr_debug("exitcall-> %pS\n", *exitcall); + (*exitcall)(); + } } diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 338bea1..943deb4 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -459,7 +459,7 @@ return buf; } -void devices_shutdown(void) +static void devices_shutdown(void) { struct device_d *dev; @@ -468,6 +468,7 @@ dev->bus->remove(dev); } } +devshutdown_exitcall(devices_shutdown); int dev_get_drvdata(struct device_d *dev, const void **data) { diff --git a/include/asm-generic/barebox.lds.h b/include/asm-generic/barebox.lds.h index 00d6eca..772058e 100644 --- a/include/asm-generic/barebox.lds.h +++ b/include/asm-generic/barebox.lds.h @@ -38,6 +38,15 @@ KEEP(*(.initcall.13)) \ KEEP(*(.initcall.14)) +#define EXITCALLS \ + KEEP(*(.exitcall.0)) \ + KEEP(*(.exitcall.1)) \ + KEEP(*(.exitcall.2)) \ + KEEP(*(.exitcall.3)) \ + KEEP(*(.exitcall.4)) \ + KEEP(*(.exitcall.5)) \ + KEEP(*(.exitcall.6)) + #define BAREBOX_CMDS KEEP(*(SORT_BY_NAME(.barebox_cmd*))) #define BAREBOX_SYMS KEEP(*(__usymtab)) diff --git a/include/common.h b/include/common.h index eef371c..6b9dd4d 100644 --- a/include/common.h +++ b/include/common.h @@ -116,7 +116,6 @@ void __noreturn start_barebox(void); void shutdown_barebox(void); -extern void (*board_shutdown)(void); /* * architectures which have special calling conventions for @@ -124,8 +123,6 @@ */ extern void (*do_execute)(void *func, int argc, char *argv[]); -void arch_shutdown(void); - int run_shell(void); #ifdef CONFIG_SHELL_HUSH diff --git a/include/driver.h b/include/driver.h index 9c60054..728f8ab 100644 --- a/include/driver.h +++ b/include/driver.h @@ -339,11 +339,6 @@ /* Use this if you have nothing to do in your drivers probe function */ int dummy_probe(struct device_d *); -/* Iterate over all activated devices (i.e. the ones with drivers and shut - * them down. - */ -void devices_shutdown(void); - int generic_memmap_ro(struct cdev *dev, void **map, int flags); int generic_memmap_rw(struct cdev *dev, void **map, int flags); diff --git a/include/init.h b/include/init.h index f619c95..527d49a 100644 --- a/include/init.h +++ b/include/init.h @@ -7,17 +7,24 @@ #define __init #define __initdata #define __initconst +#define __exit +#define __exitdata /* For assembly routines */ #define __BARE_INIT .section ".text_bare_init.text","ax" #ifndef __ASSEMBLY__ typedef int (*initcall_t)(void); +typedef void (*exitcall_t)(void); #define __define_initcall(level,fn,id) \ static initcall_t __initcall_##fn##id __attribute__((__used__)) \ __attribute__((__section__(".initcall." level))) = fn +#define __define_exitcall(level,fn,id) \ + static exitcall_t __exitcall_##fn##id __attribute__((__used__)) \ + __attribute__((__section__(".exitcall." level))) = fn + /* * A "pure" initcall has no dependencies on anything else, and purely @@ -42,6 +49,14 @@ #define environment_initcall(fn) __define_initcall("13",fn,13) #define postenvironment_initcall(fn) __define_initcall("14",fn,14) +#define early_exitcall(fn) __define_exitcall("0",fn,0) +#define predevshutdown_exitcall(fn) __define_exitcall("1",fn,1) +#define devshutdown_exitcall(fn) __define_exitcall("2",fn,2) +#define postdevshutdown_exitcall(fn) __define_exitcall("3",fn,3) +#define prearchshutdown_exitcall(fn) __define_exitcall("4",fn,4) +#define archshutdown_exitcall(fn) __define_exitcall("5",fn,5) +#define postarchshutdown_exitcall(fn) __define_exitcall("6",fn,6) + /* section for code used very early when * - we're not running from where we linked at * - bss not cleared