diff options
author | Thomas Martitz <kugel@rockbox.org> | 2010-08-27 00:29:50 +0000 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2010-08-27 00:29:50 +0000 |
commit | 194174a371b16dfc24960d1e33371c0a7ef1c2c2 (patch) | |
tree | b924bf74a96bb7dedcaebb45319569c003d81e8b /apps | |
parent | 97d2a6ec5ca8ace8daed29c8c69aab9595147b3a (diff) | |
download | rockbox-194174a371b16dfc24960d1e33371c0a7ef1c2c2.tar.gz rockbox-194174a371b16dfc24960d1e33371c0a7ef1c2c2.zip |
2nd try: Introduce a small api for loading code (codecs,plugins) from disk/memory.
It's a used by codec/plugin loading and vastly reduces code duplication. It's also a step forward in getting rid of libuisimulator in the application ports.
Apparently sh needs linker symbols prefixed with _ even if they're referenced without from C code.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27902 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r-- | apps/codecs.c | 101 | ||||
-rw-r--r-- | apps/plugin.c | 102 | ||||
-rw-r--r-- | apps/plugins/plugin.lds | 1 | ||||
-rw-r--r-- | apps/plugins/plugin_crt0.c | 6 |
4 files changed, 75 insertions, 135 deletions
diff --git a/apps/codecs.c b/apps/codecs.c index 9e77dd9099..b072c65f40 100644 --- a/apps/codecs.c +++ b/apps/codecs.c @@ -28,6 +28,7 @@ #include <ctype.h> #include <stdarg.h> #include "string-extra.h" +#include "load_code.h" #include "debug.h" #include "button.h" #include "dir.h" @@ -74,26 +75,13 @@ size_t codec_size; extern void* plugin_get_audio_buffer(size_t *buffer_size); +#if (CONFIG_PLATFORM & PLATFORM_NATIVE) && defined(HAVE_RECORDING) #undef open static int open(const char* pathname, int flags, ...) { -#if (CONFIG_PLATFORM & PLATFORM_HOSTED) - int fd; - if (flags & O_CREAT) - { - va_list ap; - va_start(ap, flags); - fd = sim_open(pathname, flags, va_arg(ap, unsigned int)); - va_end(ap); - } - else - fd = sim_open(pathname, flags); - - return fd; -#else return file_open(pathname, flags); -#endif } +#endif struct codec_api ci = { 0, /* filesize */ @@ -197,62 +185,46 @@ void codec_get_full_path(char *path, const char *codec_root_fn) CODECS_DIR, codec_root_fn); } -static int codec_load_ram(int size, struct codec_api *api) +static int codec_load_ram(void *handle, struct codec_api *api) { - struct codec_header *hdr; + struct codec_header *hdr = lc_get_header(handle); int status; -#if (CONFIG_PLATFORM & PLATFORM_NATIVE) - hdr = (struct codec_header *)codecbuf; - - if (size <= (signed)sizeof(struct codec_header) + + if (hdr == NULL || (hdr->magic != CODEC_MAGIC #ifdef HAVE_RECORDING && hdr->magic != CODEC_ENC_MAGIC #endif ) || hdr->target_id != TARGET_ID +#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || hdr->load_addr != codecbuf - || hdr->end_addr > codecbuf + CODEC_SIZE) + || hdr->end_addr > codecbuf + CODEC_SIZE +#endif + ) { logf("codec header error"); + lc_close(handle); return CODEC_ERROR; } - codec_size = hdr->end_addr - codecbuf; - -#elif (CONFIG_PLATFORM & PLATFORM_HOSTED) - void *pd; - - hdr = sim_codec_load_ram(codecbuf, size, &pd); - - if (pd == NULL) - return CODEC_ERROR; - - if (hdr == NULL - || (hdr->magic != CODEC_MAGIC -#ifdef HAVE_RECORDING - && hdr->magic != CODEC_ENC_MAGIC -#endif - ) - || hdr->target_id != TARGET_ID) { - sim_codec_close(pd); - return CODEC_ERROR; - } - - codec_size = codecbuf - codecbuf; - -#endif /* CONFIG_PLATFORM */ if (hdr->api_version > CODEC_API_VERSION || hdr->api_version < CODEC_MIN_API_VERSION) { - sim_codec_close(pd); + logf("codec api version error"); + lc_close(handle); return CODEC_ERROR; } +#if (CONFIG_PLATFORM & PLATFORM_NATIVE) + codec_size = hdr->end_addr - codecbuf; +#else + codec_size = 0; +#endif + *(hdr->api) = api; - cpucache_invalidate(); status = hdr->entry_point(); - sim_codec_close(pd); + lc_close(handle); return status; } @@ -260,36 +232,37 @@ static int codec_load_ram(int size, struct codec_api *api) int codec_load_buf(unsigned int hid, struct codec_api *api) { int rc; + void *handle; rc = bufread(hid, CODEC_SIZE, codecbuf); if (rc < 0) { logf("error loading codec"); return CODEC_ERROR; } + handle = lc_open_from_mem(codecbuf, rc); + if (handle == NULL) + { + logf("error loading codec"); + return CODEC_ERROR; + } + api->discard_codec(); - return codec_load_ram(rc, api); + return codec_load_ram(handle, api); } int codec_load_file(const char *plugin, struct codec_api *api) { char path[MAX_PATH]; - int fd; - int rc; + void *handle; codec_get_full_path(path, plugin); - - fd = open(path, O_RDONLY); - if (fd < 0) { - logf("Codec load error:%d", fd); + + handle = lc_open(path, codecbuf, CODEC_SIZE); + + if (handle == NULL) { + logf("Codec load error"); splashf(HZ*2, "Couldn't load codec: %s", path); - return fd; - } - - rc = read(fd, &codecbuf[0], CODEC_SIZE); - close(fd); - if (rc <= 0) { - logf("Codec read error"); return CODEC_ERROR; } - return codec_load_ram((size_t)rc, api); + return codec_load_ram(handle, api); } diff --git a/apps/plugin.c b/apps/plugin.c index cc540cd988..53a05bf527 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -42,6 +42,7 @@ #include "errno.h" #include "diacritic.h" #include "filefuncs.h" +#include "load_code.h" #if CONFIG_CHARGING #include "power.h" @@ -75,21 +76,19 @@ 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); @@ -728,98 +727,60 @@ 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 (pfn_tsr_exit != NULL) /* if we have a resident old plugin: */ - { + if (current_plugin_handle && pfn_tsr_exit) + { /* if we have a resident old plugin and a callback */ if (pfn_tsr_exit(!strcmp(current_plugin, plugin)) == false ) { /* not allowing another plugin to load */ return PLUGIN_OK; } - pfn_tsr_exit = NULL; - plugin_loaded = false; + lc_close(current_plugin_handle); + current_plugin_handle = pfn_tsr_exit = NULL; } splash(0, ID2P(LANG_WAIT)); strcpy(current_plugin, plugin); -#if (CONFIG_PLATFORM & PLATFORM_HOSTED) - hdr = sim_plugin_load((char *)plugin, &pd); - if (pd == NULL) { + current_plugin_handle = lc_open(plugin, pluginbuf, PLUGIN_BUFFER_SIZE); + if (current_plugin_handle == 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 - readsize = read(fd, pluginbuf, PLUGIN_BUFFER_SIZE); - close(fd); + hdr = lc_get_header(current_plugin_handle); - 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) + if (hdr == NULL || 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) { + || hdr->end_addr > pluginbuf + PLUGIN_BUFFER_SIZE +#endif + ) + { + lc_close(current_plugin_handle); splash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL)); return -1; } if (hdr->api_version > PLUGIN_API_VERSION - || hdr->api_version < PLUGIN_MIN_API_VERSION) { + || hdr->api_version < PLUGIN_MIN_API_VERSION) + { + lc_close(current_plugin_handle); splash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION)); return -1; } +#if (CONFIG_PLATFORM & PLATFORM_NATIVE) plugin_size = hdr->end_addr - pluginbuf; - - /* zero out bss area only, above guards end of pluginbuf */ - if (plugin_size > readsize) - memset(pluginbuf + readsize, 0, plugin_size - readsize); +#else + plugin_size = 0; #endif *(hdr->api) = &rockbox_api; - plugin_loaded = true; - #if defined HAVE_LCD_BITMAP && LCD_DEPTH > 1 old_backdrop = lcd_get_backdrop(); @@ -834,8 +795,6 @@ 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); @@ -847,6 +806,12 @@ 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); @@ -887,11 +852,8 @@ 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 && !plugin_loaded) + if(open_files != 0 && !current_plugin_handle) { int fd; logf("Plugin '%s' leaks file handles", plugin); @@ -909,8 +871,6 @@ 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)); @@ -923,7 +883,7 @@ void* plugin_get_buffer(size_t *buffer_size) { int buffer_pos; - if (plugin_loaded) + if (current_plugin_handle) { if (plugin_size >= PLUGIN_BUFFER_SIZE) return NULL; diff --git a/apps/plugins/plugin.lds b/apps/plugins/plugin.lds index f150b9d168..653b8bae87 100644 --- a/apps/plugins/plugin.lds +++ b/apps/plugins/plugin.lds @@ -278,6 +278,7 @@ SECTIONS .bss (NOLOAD) : { plugin_bss_start = .; + _plugin_bss_start = .; *(.bss*) #if defined(IRAMSIZE) && IRAMSIZE == 0 *(.ibss) diff --git a/apps/plugins/plugin_crt0.c b/apps/plugins/plugin_crt0.c index 536eccaffa..e34124c5a2 100644 --- a/apps/plugins/plugin_crt0.c +++ b/apps/plugins/plugin_crt0.c @@ -32,6 +32,8 @@ PLUGIN_HEADER #define EXIT_MAGIC 0x0CDEBABE extern enum plugin_status plugin_start(const void*); +extern unsigned char plugin_bss_start[]; +extern unsigned char plugin_end_addr[]; static jmp_buf __exit_env; /* only 1 atexit handler for now, chain in the exit handler if you need more */ @@ -61,6 +63,10 @@ enum plugin_status plugin__start(const void *param) int exit_ret; enum plugin_status ret; + /* zero out the bss section */ +#if (CONFIG_PLATFORM & PLATFORM_NATIVE) + rb->memset(plugin_bss_start, 0, plugin_end_addr - plugin_bss_start); +#endif /* we come back here if exit() was called or the plugin returned normally */ exit_ret = setjmp(__exit_env); if (exit_ret == 0) |