Index: apps/plugin.c =================================================================== --- apps/plugin.c (revision 31045) +++ apps/plugin.c (working copy) @@ -127,7 +127,10 @@ #else extern unsigned char pluginbuf[]; #include "bitswap.h" +#if (CONFIG_CODEC != SWCODEC) && defined(HAVE_INIT_ATTR) +extern unsigned char initend[]; #endif +#endif /* for actual plugins only, not for codecs */ static int plugin_size = 0; @@ -821,6 +824,7 @@ } lc_close(current_plugin_handle); current_plugin_handle = pfn_tsr_exit = NULL; + plugin_size = 0; } splash(0, ID2P(LANG_WAIT)); @@ -897,6 +901,7 @@ { /* close handle if plugin is no tsr one */ lc_close(current_plugin_handle); current_plugin_handle = NULL; + plugin_size = 0; } /* Go back to the global setting in case the plugin changed it */ @@ -961,27 +966,29 @@ return rc; } +#if (CONFIG_CODEC != SWCODEC) && defined(HAVE_INIT_ATTR) +/* HWCODEC targets don't have a codec buffer and INIT_ATTR code goes into + * the plugin buffer. This ensures code using the plugin buffer via + * plugin_get_buffer doesn't overwrite INIT_ATTR code. */ +void plugin_keep_init_code(bool keep) +{ + if (keep) + plugin_size = &initend[0] - &pluginbuf[0]; + else + plugin_size = 0; +} +#endif + /* Returns a pointer to the portion of the plugin buffer that is not already being used. If no plugin is loaded, returns the entire plugin buffer */ void* plugin_get_buffer(size_t *buffer_size) { - int buffer_pos; + if (plugin_size >= PLUGIN_BUFFER_SIZE) + return NULL; - if (current_plugin_handle) - { - if (plugin_size >= PLUGIN_BUFFER_SIZE) - return NULL; + *buffer_size = PLUGIN_BUFFER_SIZE-plugin_size; - *buffer_size = PLUGIN_BUFFER_SIZE-plugin_size; - buffer_pos = plugin_size; - } - else - { - *buffer_size = PLUGIN_BUFFER_SIZE; - buffer_pos = 0; - } - - return &pluginbuf[buffer_pos]; + return &pluginbuf[plugin_size]; } /* Returns a pointer to the mp3 buffer. Index: apps/plugin.h =================================================================== --- apps/plugin.h (revision 31045) +++ apps/plugin.h (working copy) @@ -979,6 +979,9 @@ int plugin_load(const char* plugin, const void* parameter); void* plugin_get_audio_buffer(size_t *buffer_size); +#if (CONFIG_CODEC != SWCODEC) && defined(HAVE_INIT_ATTR) +void plugin_keep_init_code(bool keep) INIT_ATTR; +#endif /* plugin_tsr, callback returns true to allow the new plugin to load, Index: apps/main.c =================================================================== --- apps/main.c (revision 31045) +++ apps/main.c (working copy) @@ -155,7 +155,11 @@ { sys_handle_argv(argc, argv); #else -int main(void) INIT_ATTR MAIN_NORETURN_ATTR; +int main(void) +#if !defined(AUTOROCK) || (CONFIG_CODEC == SWCODEC) + INIT_ATTR +#endif + MAIN_NORETURN_ATTR; int main(void) { #endif @@ -178,6 +182,12 @@ usb_start_monitoring(); #endif +#if (CONFIG_CODEC != SWCODEC) && defined(HAVE_INIT_ATTR) + /* no calls INIT_ATTR functions after this point on HWCODEC targets! + * AUTOROCK may load a plugin, overwriting INIT_ATTR code. */ + plugin_keep_init_code(false); +#endif + #ifdef AUTOROCK { char filename[MAX_PATH]; @@ -435,6 +445,10 @@ bool coldstart = (PACR2 & 0x4000) != 0; /* starting from Flash */ #endif +#if (CONFIG_CODEC != SWCODEC) && defined(HAVE_INIT_ATTR) + plugin_keep_init_code(true); +#endif + system_init(); core_allocator_init(); kernel_init(); Index: firmware/target/sh/archos/audio-archos.c =================================================================== --- firmware/target/sh/archos/audio-archos.c (revision 31045) +++ firmware/target/sh/archos/audio-archos.c (working copy) @@ -70,6 +70,7 @@ unsigned long mas_version_code; #if CONFIG_CODEC == MAS3507D +static void mas_poll_start(void) INIT_ATTR; static void mas_poll_start(void) { unsigned int count; @@ -215,6 +216,7 @@ } #endif /* #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */ +static void setup_sci0(void) INIT_ATTR; static void setup_sci0(void) { /* PB15 is I/O, PB14 is IRQ6, PB12 is SCK0, PB9 is TxD0 */ Index: firmware/target/sh/archos/app.lds =================================================================== --- firmware/target/sh/archos/app.lds (revision 31045) +++ firmware/target/sh/archos/app.lds (working copy) @@ -99,7 +99,19 @@ . = ALIGN(0x4); _iend = .; } > IRAM - + +#ifdef HAVE_INIT_ATTR + .init ENDAUDIOADDR : + { + _initstart = .; + *(.init) + . = ALIGN(0x4); + _initend = .; + } AT> DRAM + + _initcopy = LOADADDR(.init); +#endif + .stack _noloaddram (NOLOAD) : { *(.stack) Index: firmware/target/sh/crt0.S =================================================================== --- firmware/target/sh/crt0.S (revision 31045) +++ firmware/target/sh/crt0.S (working copy) @@ -98,114 +98,106 @@ mov #0,r0 ldc r0,gbr - /* .iram copy is done first since it is reclaimed for other - * uninitialized sections */ + mova .sectioncopies,r0 + mov r0,r5 + mova .sectionfills,r0 - /* copy the .iram section */ - mov.l .iramcopy_k,r0 - mov.l .iram_k,r1 - mov.l .iramend_k,r2 - /* Note: We cannot put a PC relative load into the delay slot of a 'bra' - instruction (the offset would be wrong), but there is nothing else to - do before the loop, so the delay slot would be 'nop'. The cmp / bf - sequence is the same length, but more efficient. */ - cmp/hi r1,r2 - bf .noiramcopy -.iramloop: - mov.l @r0+,r3 - mov.l r3,@r1 - add #4,r1 - cmp/hi r1,r2 - bt .iramloop -.noiramcopy: + /* first, copy sections */ +.nextcopy: + mov.l @r5+,r1 /* source for copy */ + mov.l @r5+,r2 /* start of section at destination */ + mov.l @r5+,r3 /* end of section at destination */ - /* zero out .ibss */ - mov.l .iedata_k,r0 - mov.l .iend_k,r1 - bra .iedatastart - mov #0,r2 -.iedataloop: /* backwards is faster and shorter */ - mov.l r2,@-r1 -.iedatastart: - cmp/hi r0,r1 - bt .iedataloop + cmp/eq r1,r2 + bt .skipcopy /* if src == dest, no need to copy */ + + cmp/hi r2,r3 /* don't copy empty sections */ + bf .skipcopy - /* zero out bss */ - mov.l .edata_k,r0 - mov.l .end_k,r1 - bra .edatastart - mov #0,r2 -.edataloop: /* backwards is faster and shorter */ - mov.l r2,@-r1 -.edatastart: - cmp/hi r0,r1 - bt .edataloop +.copyloop: + mov.l @r1+,r4 + mov.l r4,@r2 + add #4,r2 + cmp/hi r2,r3 + bt .copyloop - /* copy the .data section, for rombased execution */ - mov.l .datacopy_k,r0 - mov.l .data_k,r1 - cmp/eq r0,r1 - bt .nodatacopy /* Don't copy if src and dest are equal */ - mov.l .dataend_k,r2 +.skipcopy: + cmp/hi r5,r0 + bt .nextcopy /* copy more sections until fills are reached */ + + /* now, fill sections */ + mova .fillsend,r0 + mov.l .deadbeef_k,r3 /* stack munging with 0xdeadbeef is first */ + +.nextfill: + mov.l @r5+,r1 /* start of section at destination */ + bra .fillsection + mov.l @r5+,r2 /* end of section at destination */ + +.fillloop: + mov.l r3,@-r2 /* backwards is faster and shorter */ +.fillsection: cmp/hi r1,r2 - bf .nodatacopy -.dataloop: - mov.l @r0+,r3 - mov.l r3,@r1 - add #4,r1 - cmp/hi r1,r2 - bt .dataloop -.nodatacopy: + bt .fillloop - /* Munge the main thread stack */ - mov.l .stackbegin_k,r0 - mov.l .stackend_k,r1 - mov r1,r15 - mov.l .deadbeef_k,r2 -.mungeloop: /* backwards is faster and shorter */ - mov.l r2,@-r1 - cmp/hi r0,r1 - bt .mungeloop - + mov #0,r3 /* rest of filling is with zeroes */ + cmp/hi r5,r0 + bt .nextfill /* stop at the end of the table */ + /* call the mainline */ mov.l .main_k,r0 + mov.l .stackend_k,r15 jsr @r0 nop .hoo: bra .hoo nop - .align 2 + .align 4 .vbr_k: .long vectors #ifdef DEBUG .orig_vbr_k: .long 0x09000000 #endif -.iedata_k: - .long _iedata -.iend_k: - .long _iend -.iramcopy_k: - .long _iramcopy -.iram_k: - .long _iramstart -.iramend_k: - .long _iramend -.edata_k: - .long _edata -.end_k: - .long _end -.datacopy_k: + + /* list of sections to copy + * first copy sections where the source may be overwritten */ +.sectioncopies: + /* copy the .iram section */ + .long _iramcopy /* start of section at source */ + .long _iramstart /* start of section at destination */ + .long _iramend /* end of section at destination */ + +#ifdef HAVE_INIT_ATTR + /* copy the .init section */ + .long _initcopy + .long _initstart + .long _initend +#endif + + /* copy the .data section (only needed for rom based execution) */ .long _datacopy -.data_k: .long _datastart -.dataend_k: .long _dataend -.stackbegin_k: + + /* list of sections to fill, must follow list of sections to copy */ + /* first fill uses 0xdeadbeef and rest use 0 */ +.sectionfills: + /* munge the main thread stack */ .long _stackbegin .stackend_k: .long _stackend + + /* zero out .ibss */ + .long _iedata + .long _iend + + /* zero out .bss */ + .long _edata + .long _end +.fillsend: /* end of list of sections to fill */ + .deadbeef_k: .long 0xdeadbeef .main_k: Index: firmware/export/mascodec.h =================================================================== --- firmware/export/mascodec.h (revision 31045) +++ firmware/export/mascodec.h (working copy) @@ -23,7 +23,7 @@ /* unused: int mas_default_read(unsigned short *buf); */ #if CONFIG_CODEC == MAS3507D -int mas_run(unsigned short address); +int mas_run(unsigned short address) INIT_ATTR; #endif int mas_readmem(int bank, int addr, unsigned long* dest, int len); int mas_writemem(int bank, int addr, const unsigned long* src, int len); @@ -34,7 +34,7 @@ int mas_direct_config_write(unsigned char reg, unsigned int val); int mas_codec_writereg(int reg, unsigned int val); int mas_codec_readreg(int reg); -unsigned long mas_readver(void); +unsigned long mas_readver(void) INIT_ATTR; #endif Index: firmware/export/mp3_playback.h =================================================================== --- firmware/export/mp3_playback.h (revision 31045) +++ firmware/export/mp3_playback.h (working copy) @@ -31,7 +31,7 @@ int avc, int channel_config, int stereo_width, int mdb_strength, int mdb_harmonics, int mdb_center, int mdb_shape, bool mdb_enable, - bool superbass); + bool superbass) INIT_ATTR; /* exported just for mpeg.c, to keep the recording there */ #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) Index: firmware/export/dac3550a.h =================================================================== --- firmware/export/dac3550a.h (revision 31045) +++ firmware/export/dac3550a.h (working copy) @@ -41,7 +41,7 @@ extern int dac_volume(unsigned int left, unsigned int right, bool deemph); extern void dac_enable(bool enable); extern void dac_line_in(bool enable); -extern void dac_init(void); +extern void dac_init(void) INIT_ATTR; #endif /* _DAC3550A_H_ */ Index: firmware/export/config.h =================================================================== --- firmware/export/config.h (revision 31045) +++ firmware/export/config.h (working copy) @@ -888,7 +888,7 @@ #endif #if (defined(CPU_PP) || (CONFIG_CPU == AS3525) || (CONFIG_CPU == AS3525v2) || \ - (CONFIG_CPU == IMX31L) || (CONFIG_CPU == IMX233)) \ + (CONFIG_CPU == IMX31L) || (CONFIG_CPU == IMX233) || defined(CPU_SH)) \ && (CONFIG_PLATFORM & PLATFORM_NATIVE) && !defined(BOOTLOADER) /* Functions that have INIT_ATTR attached are NOT guaranteed to survive after * root_menu() has been called. Their code may be overwritten by other data or Index: firmware/rom.lds =================================================================== --- firmware/rom.lds (revision 31045) +++ firmware/rom.lds (working copy) @@ -105,6 +105,18 @@ . = ALIGN(0x4); } > FLASH +#ifdef HAVE_INIT_ATTR + .init : + { + _initstart = .; + *(.init) + . = ALIGN(0x4); + _initend = .; + } > FLASH + + _initcopy = LOADADDR(.init); +#endif + .rodata : { *(.rodata)