summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2010-09-09 16:17:21 +0000
committerThomas Martitz <kugel@rockbox.org>2010-09-09 16:17:21 +0000
commit0d4585b28ffcac1b62ed37cee2c34de0515df468 (patch)
tree70ace8b78a4d0a44da50d692e893fadd93f85878 /apps
parentcec7c99613b3c11deb8a05deecd7ee9d16b5ea8a (diff)
Extend lc_open() to also being able to load overlay plugins.
For this it needs to look at the plugin header. Since lc_open() doesn't know it's a plugin, the header needs to be changed slightly to include the new lc_header (which needs to be the first element in plugin_header so it can be casted savely). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28054 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/codecs.c7
-rw-r--r--apps/codecs.h23
-rw-r--r--apps/codecs/codec_crt0.c28
-rw-r--r--apps/plugin.c17
-rw-r--r--apps/plugin.h21
-rw-r--r--apps/plugins/lib/overlay.c76
6 files changed, 89 insertions, 83 deletions
diff --git a/apps/codecs.c b/apps/codecs.c
index 35f6363986..3fa05be59a 100644
--- a/apps/codecs.c
+++ b/apps/codecs.c
@@ -181,7 +181,8 @@ void codec_get_full_path(char *path, const char *codec_root_fn)
static int codec_load_ram(void *handle, struct codec_api *api)
{
- struct codec_header *hdr = lc_get_header(handle);
+ struct codec_header *c_hdr = lc_get_header(handle);
+ struct lc_header *hdr = c_hdr ? &c_hdr->lc_hdr : NULL;
int status;
if (hdr == NULL
@@ -215,8 +216,8 @@ static int codec_load_ram(void *handle, struct codec_api *api)
codec_size = 0;
#endif
- *(hdr->api) = api;
- status = hdr->entry_point();
+ *(c_hdr->api) = api;
+ status = c_hdr->entry_point();
lc_close(handle);
diff --git a/apps/codecs.h b/apps/codecs.h
index f94c81ab20..1c0b9da6ba 100644
--- a/apps/codecs.h
+++ b/apps/codecs.h
@@ -51,6 +51,7 @@
#include "settings.h"
#include "gcc_extensions.h"
+#include "load_code.h"
#ifdef CODEC
#if defined(DEBUG) || defined(SIMULATOR)
@@ -240,11 +241,7 @@ struct codec_api {
/* codec header */
struct codec_header {
- unsigned long magic; /* RCOD or RENC */
- unsigned short target_id;
- unsigned short api_version;
- unsigned char *load_addr;
- unsigned char *end_addr;
+ struct lc_header lc_hdr; /* must be first */
enum codec_status(*entry_point)(void);
struct codec_api **api;
};
@@ -261,27 +258,27 @@ extern unsigned char plugin_end_addr[];
#define CODEC_HEADER \
const struct codec_header __header \
__attribute__ ((section (".header")))= { \
- CODEC_MAGIC, TARGET_ID, CODEC_API_VERSION, \
- plugin_start_addr, plugin_end_addr, codec_start, &ci };
+ { CODEC_MAGIC, TARGET_ID, CODEC_API_VERSION, \
+ plugin_start_addr, plugin_end_addr }, codec_start, &ci };
/* encoders */
#define CODEC_ENC_HEADER \
const struct codec_header __header \
__attribute__ ((section (".header")))= { \
- CODEC_ENC_MAGIC, TARGET_ID, CODEC_API_VERSION, \
- plugin_start_addr, plugin_end_addr, codec_start, &ci };
+ { CODEC_ENC_MAGIC, TARGET_ID, CODEC_API_VERSION, \
+ plugin_start_addr, plugin_end_addr }, codec_start, &ci };
#else /* def SIMULATOR */
/* decoders */
#define CODEC_HEADER \
const struct codec_header __header \
__attribute__((visibility("default"))) = { \
- CODEC_MAGIC, TARGET_ID, CODEC_API_VERSION, \
- NULL, NULL, codec_start, &ci };
+ { CODEC_MAGIC, TARGET_ID, CODEC_API_VERSION, NULL, NULL }, \
+ codec_start, &ci };
/* encoders */
#define CODEC_ENC_HEADER \
const struct codec_header __header = { \
- CODEC_ENC_MAGIC, TARGET_ID, CODEC_API_VERSION, \
- NULL, NULL, codec_start, &ci };
+ { CODEC_ENC_MAGIC, TARGET_ID, CODEC_API_VERSION, NULL, NULL }, \
+ codec_start, &ci };
#endif /* SIMULATOR */
#endif /* CODEC */
diff --git a/apps/codecs/codec_crt0.c b/apps/codecs/codec_crt0.c
index fdb79092f4..c845f79a40 100644
--- a/apps/codecs/codec_crt0.c
+++ b/apps/codecs/codec_crt0.c
@@ -20,15 +20,10 @@
****************************************************************************/
#include "config.h"
-#include "codeclib.h"
+#include "codecs.h"
struct codec_api *ci DATA_ATTR;
-extern unsigned char iramcopy[];
-extern unsigned char iramstart[];
-extern unsigned char iramend[];
-extern unsigned char iedata[];
-extern unsigned char iend[];
extern unsigned char plugin_bss_start[];
extern unsigned char plugin_end_addr[];
@@ -42,14 +37,23 @@ enum codec_status codec_start(void)
{
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
#ifdef USE_IRAM
- ci->memcpy(iramstart, iramcopy, iramend - iramstart);
- ci->memset(iedata, 0, iend - iedata);
-#endif
+ extern char iramcopy[], iramstart[], iramend[], iedata[], iend[];
+ size_t iram_size = iramend - iramstart;
+ size_t ibss_size = iend - iedata;
+ if (iram_size > 0 || ibss_size > 0)
+ {
+ ci->memcpy(iramstart, iramcopy, iram_size);
+ ci->memset(iedata, 0, ibss_size);
+ /* make the icache (if it exists) up to date with the new code */
+ ci->cpucache_invalidate();
+ /* barrier to prevent reordering iram copy and BSS clearing,
+ * because the BSS segment alias the IRAM copy.
+ */
+ asm volatile ("" ::: "memory");
+ }
+#endif /* PLUGIN_USE_IRAM */
ci->memset(plugin_bss_start, 0, plugin_end_addr - plugin_bss_start);
#endif
- /* writeback cleared iedata and bss areas, invalidate icache for
- * copied code */
- ci->cpucache_invalidate();
return codec_main();
}
diff --git a/apps/plugin.c b/apps/plugin.c
index 9e08951828..9b490d0fa9 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -723,12 +723,18 @@ static const struct plugin_api rockbox_api = {
/* new stuff at the end, sort into place next time
the API gets incompatible */
dir_get_info,
+
+ lc_open,
+ lc_open_from_mem,
+ lc_get_header,
+ lc_close,
};
int plugin_load(const char* plugin, const void* parameter)
{
int rc, i;
- struct plugin_header *hdr;
+ struct plugin_header *p_hdr;
+ struct lc_header *hdr;
#if LCD_DEPTH > 1
fb_data* old_backdrop;
@@ -754,7 +760,10 @@ int plugin_load(const char* plugin, const void* parameter)
return -1;
}
- hdr = lc_get_header(current_plugin_handle);
+ p_hdr = lc_get_header(current_plugin_handle);
+
+ hdr = p_hdr ? &p_hdr->lc_hdr : NULL;
+
if (hdr == NULL
|| hdr->magic != PLUGIN_MAGIC
@@ -782,7 +791,7 @@ int plugin_load(const char* plugin, const void* parameter)
plugin_size = 0;
#endif
- *(hdr->api) = &rockbox_api;
+ *(p_hdr->api) = &rockbox_api;
#if defined HAVE_LCD_BITMAP && LCD_DEPTH > 1
old_backdrop = lcd_get_backdrop();
@@ -806,7 +815,7 @@ int plugin_load(const char* plugin, const void* parameter)
open_files = 0;
#endif
- rc = hdr->entry_point(parameter);
+ rc = p_hdr->entry_point(parameter);
if (!pfn_tsr_exit)
{ /* close handle if plugin is no tsr one */
diff --git a/apps/plugin.h b/apps/plugin.h
index bafd4070f6..a69b85bbfd 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -53,6 +53,7 @@ void* plugin_get_buffer(size_t *buffer_size);
#include "thread.h"
#include "button.h"
#include "action.h"
+#include "load_code.h"
#include "usb.h"
#include "font.h"
#include "lcd.h"
@@ -895,15 +896,17 @@ struct plugin_api {
/* new stuff at the end, sort into place next time
the API gets incompatible */
struct dirinfo (*dir_get_info)(DIR* parent, struct dirent *entry);
+
+ /* load code api for overlay */
+ void* (*lc_open)(const char *filename, unsigned char *buf, size_t buf_size);
+ void* (*lc_open_from_mem)(void* addr, size_t blob_size);
+ void* (*lc_get_header)(void *handle);
+ void (*lc_close)(void *handle);
};
/* plugin header */
struct plugin_header {
- unsigned long magic;
- unsigned short target_id;
- unsigned short api_version;
- unsigned char *load_addr;
- unsigned char *end_addr;
+ struct lc_header lc_hdr; /* must be the first */
enum plugin_status(*entry_point)(const void*);
const struct plugin_api **api;
};
@@ -916,15 +919,15 @@ extern unsigned char plugin_end_addr[];
const struct plugin_api *rb DATA_ATTR; \
const struct plugin_header __header \
__attribute__ ((section (".header")))= { \
- PLUGIN_MAGIC, TARGET_ID, PLUGIN_API_VERSION, \
- plugin_start_addr, plugin_end_addr, plugin__start, &rb };
+ { PLUGIN_MAGIC, TARGET_ID, PLUGIN_API_VERSION, \
+ plugin_start_addr, plugin_end_addr }, plugin__start, &rb };
#else /* PLATFORM_HOSTED */
#define PLUGIN_HEADER \
const struct plugin_api *rb DATA_ATTR; \
const struct plugin_header __header \
__attribute__((visibility("default"))) = { \
- PLUGIN_MAGIC, TARGET_ID, PLUGIN_API_VERSION, \
- NULL, NULL, plugin__start, &rb };
+ { PLUGIN_MAGIC, TARGET_ID, PLUGIN_API_VERSION, NULL, NULL },
+ plugin__start, &rb };
#endif /* CONFIG_PLATFORM */
#endif /* PLUGIN */
diff --git a/apps/plugins/lib/overlay.c b/apps/plugins/lib/overlay.c
index 8a04cf8aa7..f64df29823 100644
--- a/apps/plugins/lib/overlay.c
+++ b/apps/plugins/lib/overlay.c
@@ -47,64 +47,56 @@
enum plugin_status run_overlay(const void* parameter,
unsigned char *filename, unsigned char *name)
{
- int fd, readsize;
size_t audiobuf_size;
unsigned char *audiobuf;
- static struct plugin_header header;
+ void *handle;
+ struct plugin_header *p_hdr;
+ struct lc_header *hdr;
- fd = rb->open(filename, O_RDONLY);
- if (fd < 0)
+ audiobuf = rb->plugin_get_audio_buffer(&audiobuf_size);
+ if (!audiobuf)
{
- rb->splashf(2*HZ, "Can't open %s", filename);
- return PLUGIN_ERROR;
+ rb->splash(2*HZ, "Can't optain memory");
+ goto error;
}
- readsize = rb->read(fd, &header, sizeof(header));
- rb->close(fd);
- /* Close for now. Less code than doing it in all error checks.
- * Would need to seek back anyway. */
- if (readsize != sizeof(header))
- {
- rb->splashf(2*HZ, "Reading %s overlay failed.", name);
- return PLUGIN_ERROR;
- }
- if (header.magic != PLUGIN_MAGIC || header.target_id != TARGET_ID)
+ handle = rb->lc_open(filename, audiobuf, audiobuf_size);
+ if (!handle)
{
- rb->splashf(2*HZ, "%s overlay: Incompatible model.", name);
- return PLUGIN_ERROR;
- }
- if (header.api_version != PLUGIN_API_VERSION)
- {
- rb->splashf(2*HZ, "%s overlay: Incompatible version.", name);
- return PLUGIN_ERROR;
+ rb->splashf(2*HZ, "Can't open %s", filename);
+ goto error;
}
- audiobuf = rb->plugin_get_audio_buffer(&audiobuf_size);
- if (header.load_addr < audiobuf ||
- header.end_addr > audiobuf + audiobuf_size)
+ p_hdr = rb->lc_get_header(handle);
+ if (!p_hdr)
{
- rb->splashf(2*HZ, "%s overlay doesn't fit into memory.", name);
- return PLUGIN_ERROR;
+ rb->splash(2*HZ, "Can't get header");
+ goto error_close;
}
+ else
+ hdr = &p_hdr->lc_hdr;
- fd = rb->open(filename, O_RDONLY);
- if (fd < 0)
+ if (hdr->magic != PLUGIN_MAGIC || hdr->target_id != TARGET_ID)
{
- rb->splashf(2*HZ, "Can't open %s", filename);
- return PLUGIN_ERROR;
+ rb->splashf(2*HZ, "%s overlay: Incompatible model.", name);
+ goto error_close;
}
- readsize = rb->read(fd, header.load_addr, header.end_addr - header.load_addr);
- rb->close(fd);
- if (readsize < 0)
+
+ if (hdr->api_version > PLUGIN_API_VERSION
+ || hdr->api_version < PLUGIN_MIN_API_VERSION)
{
- rb->splashf(2*HZ, "Reading %s overlay failed.", name);
- return PLUGIN_ERROR;
+ rb->splashf(2*HZ, "%s overlay: Incompatible version.", name);
+ goto error_close;
}
- /* Zero out bss area */
- rb->memset(header.load_addr + readsize, 0,
- header.end_addr - (header.load_addr + readsize));
- *(header.api) = rb;
- return header.entry_point(parameter);
+ rb->lc_close(handle);
+
+ *(p_hdr->api) = rb;
+ return p_hdr->entry_point(parameter);
+
+error_close:
+ rb->lc_close(handle);
+error:
+ return PLUGIN_ERROR;
}