diff options
Diffstat (limited to 'apps/plugin.c')
-rw-r--r-- | apps/plugin.c | 102 |
1 files changed, 71 insertions, 31 deletions
diff --git a/apps/plugin.c b/apps/plugin.c index 53a05bf527..cc540cd988 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -42,7 +42,6 @@ #include "errno.h" #include "diacritic.h" #include "filefuncs.h" -#include "load_code.h" #if CONFIG_CHARGING #include "power.h" @@ -76,19 +75,21 @@ static unsigned int open_files; #if (CONFIG_PLATFORM & PLATFORM_HOSTED) static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE]; +void *sim_plugin_load(char *plugin, void **pd); +void sim_plugin_close(void *pd); void sim_lcd_ex_init(unsigned long (*getpixel)(int, int)); void sim_lcd_ex_update_rect(int x, int y, int width, int height); #else +#define sim_plugin_close(x) extern unsigned char pluginbuf[]; #include "bitswap.h" #endif /* for actual plugins only, not for codecs */ +static bool plugin_loaded = false; static int plugin_size = 0; static bool (*pfn_tsr_exit)(bool reenter) = NULL; /* TSR exit callback */ static char current_plugin[MAX_PATH]; -/* NULL if no plugin is loaded, otherwise the handle that lc_open() returned */ -static void *current_plugin_handle; char *plugin_get_current_filename(void); @@ -727,60 +728,98 @@ int plugin_load(const char* plugin, const void* parameter) { int rc, i; struct plugin_header *hdr; +#if (CONFIG_PLATFORM & PLATFORM_HOSTED) + void *pd; +#else /* PLATFOR_NATIVE */ + int fd; + ssize_t readsize; +#if NUM_CORES > 1 + unsigned my_core; +#endif +#endif /* CONFIG_PLATFORM */ #if LCD_DEPTH > 1 fb_data* old_backdrop; #endif - if (current_plugin_handle && pfn_tsr_exit) - { /* if we have a resident old plugin and a callback */ + if (pfn_tsr_exit != NULL) /* if we have a resident old plugin: */ + { if (pfn_tsr_exit(!strcmp(current_plugin, plugin)) == false ) { /* not allowing another plugin to load */ return PLUGIN_OK; } - lc_close(current_plugin_handle); - current_plugin_handle = pfn_tsr_exit = NULL; + pfn_tsr_exit = NULL; + plugin_loaded = false; } splash(0, ID2P(LANG_WAIT)); strcpy(current_plugin, plugin); - current_plugin_handle = lc_open(plugin, pluginbuf, PLUGIN_BUFFER_SIZE); - if (current_plugin_handle == NULL) { +#if (CONFIG_PLATFORM & PLATFORM_HOSTED) + hdr = sim_plugin_load((char *)plugin, &pd); + if (pd == NULL) { splashf(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin); return -1; } + if (hdr == NULL + || hdr->magic != PLUGIN_MAGIC + || hdr->target_id != TARGET_ID) { + sim_plugin_close(pd); + splash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL)); + return -1; + } + if (hdr->api_version > PLUGIN_API_VERSION + || hdr->api_version < PLUGIN_MIN_API_VERSION) { + sim_plugin_close(pd); + splash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION)); + return -1; + } +#else + fd = open(plugin, O_RDONLY); + if (fd < 0) { + splashf(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin); + return fd; + } +#if NUM_CORES > 1 + /* Make sure COP cache is flushed and invalidated before loading */ + my_core = switch_core(CURRENT_CORE ^ 1); + cpucache_invalidate(); + switch_core(my_core); +#endif - hdr = lc_get_header(current_plugin_handle); + readsize = read(fd, pluginbuf, PLUGIN_BUFFER_SIZE); + close(fd); - if (hdr == NULL + if (readsize < 0) { + splashf(HZ*2, str(LANG_READ_FAILED), plugin); + return -1; + } + hdr = (struct plugin_header *)pluginbuf; + + if ((unsigned)readsize <= sizeof(struct plugin_header) || hdr->magic != PLUGIN_MAGIC || hdr->target_id != TARGET_ID -#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || hdr->load_addr != pluginbuf - || hdr->end_addr > pluginbuf + PLUGIN_BUFFER_SIZE -#endif - ) - { - lc_close(current_plugin_handle); + || hdr->end_addr > pluginbuf + PLUGIN_BUFFER_SIZE) { splash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL)); return -1; } if (hdr->api_version > PLUGIN_API_VERSION - || hdr->api_version < PLUGIN_MIN_API_VERSION) - { - lc_close(current_plugin_handle); + || hdr->api_version < PLUGIN_MIN_API_VERSION) { splash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION)); return -1; } -#if (CONFIG_PLATFORM & PLATFORM_NATIVE) plugin_size = hdr->end_addr - pluginbuf; -#else - plugin_size = 0; + + /* zero out bss area only, above guards end of pluginbuf */ + if (plugin_size > readsize) + memset(pluginbuf + readsize, 0, plugin_size - readsize); #endif *(hdr->api) = &rockbox_api; + plugin_loaded = true; + #if defined HAVE_LCD_BITMAP && LCD_DEPTH > 1 old_backdrop = lcd_get_backdrop(); @@ -795,6 +834,8 @@ int plugin_load(const char* plugin, const void* parameter) FOR_NB_SCREENS(i) viewportmanager_theme_enable(i, false, NULL); + + cpucache_invalidate(); #ifdef HAVE_TOUCHSCREEN touchscreen_set_mode(TOUCHSCREEN_BUTTON); @@ -806,12 +847,6 @@ int plugin_load(const char* plugin, const void* parameter) rc = hdr->entry_point(parameter); - if (!pfn_tsr_exit) - { /* close handle if plugin is no tsr one */ - lc_close(current_plugin_handle); - current_plugin_handle = NULL; - } - /* Go back to the global setting in case the plugin changed it */ #ifdef HAVE_TOUCHSCREEN touchscreen_set_mode(global_settings.touch_mode); @@ -852,8 +887,11 @@ int plugin_load(const char* plugin, const void* parameter) FOR_NB_SCREENS(i) viewportmanager_theme_undo(i, false); + if (pfn_tsr_exit == NULL) + plugin_loaded = false; + #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE - if(open_files != 0 && !current_plugin_handle) + if(open_files != 0 && !plugin_loaded) { int fd; logf("Plugin '%s' leaks file handles", plugin); @@ -871,6 +909,8 @@ int plugin_load(const char* plugin, const void* parameter) } #endif + sim_plugin_close(pd); + if (rc == PLUGIN_ERROR) splash(HZ*2, str(LANG_PLUGIN_ERROR)); @@ -883,7 +923,7 @@ void* plugin_get_buffer(size_t *buffer_size) { int buffer_pos; - if (current_plugin_handle) + if (plugin_loaded) { if (plugin_size >= PLUGIN_BUFFER_SIZE) return NULL; |