summaryrefslogtreecommitdiffstats
path: root/firmware/load_code.c
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 /firmware/load_code.c
parentcec7c99613b3c11deb8a05deecd7ee9d16b5ea8a (diff)
downloadrockbox-0d4585b28ffcac1b62ed37cee2c34de0515df468.tar.gz
rockbox-0d4585b28ffcac1b62ed37cee2c34de0515df468.tar.bz2
rockbox-0d4585b28ffcac1b62ed37cee2c34de0515df468.zip
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 'firmware/load_code.c')
-rw-r--r--firmware/load_code.c59
1 files changed, 49 insertions, 10 deletions
diff --git a/firmware/load_code.c b/firmware/load_code.c
index 75bac8b2ac..5b5307e622 100644
--- a/firmware/load_code.c
+++ b/firmware/load_code.c
@@ -26,37 +26,77 @@
#include "load_code.h"
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
+
/* load binary blob from disk to memory, returning a handle */
-void * lc_open(const char *filename, char *buf, size_t buf_size)
+void * lc_open(const char *filename, unsigned char *buf, size_t buf_size)
{
int fd = open(filename, O_RDONLY);
ssize_t read_size;
+ struct lc_header hdr;
+ unsigned char *buf_end = buf+buf_size;
+ off_t copy_size;
if (fd < 0)
{
DEBUGF("Could not open file");
- return NULL;
+ goto error;
}
#if NUM_CORES > 1
/* Make sure COP cache is flushed and invalidated before loading */
{
int my_core = switch_core(CURRENT_CORE ^ 1);
- cpucache_invalidate();
+ cpucache_commit_discard();
switch_core(my_core);
}
#endif
- read_size = read(fd, buf, buf_size);
+ /* read the header to obtain the load address */
+ read_size = read(fd, &hdr, sizeof(hdr));
+
+ if (read_size < 0)
+ {
+ DEBUGF("Could not read from file");
+ goto error_fd;
+ }
+
+ /* hdr.end_addr points to the end of the bss section,
+ * but there might be idata/icode behind that so the bytes to copy
+ * can be larger */
+ copy_size = MAX(filesize(fd), hdr.end_addr - hdr.load_addr);
+
+ if (hdr.load_addr < buf || (hdr.load_addr+copy_size) > buf_end)
+ {
+ DEBUGF("Binary doesn't fit into memory");
+ goto error_fd;
+ }
+
+ /* go back to beginning to load the whole thing (incl. header) */
+ if (lseek(fd, 0, SEEK_SET) < 0)
+ {
+ DEBUGF("lseek failed");
+ goto error_fd;
+ }
+
+ /* the header has the addresses where the code is linked at */
+ read_size = read(fd, hdr.load_addr, copy_size);
close(fd);
- cpucache_invalidate();
if (read_size < 0)
{
DEBUGF("Could not read from file");
- return NULL;
+ goto error;
}
- return buf;
+
+ /* commit dcache and discard icache */
+ cpucache_commit_discard();
+ /* return a pointer the header, reused by lc_get_header() */
+ return hdr.load_addr;
+
+error_fd:
+ close(fd);
+error:
+ return NULL;
}
#elif (CONFIG_PLATFORM & PLATFORM_HOSTED)
@@ -85,12 +125,11 @@ static inline char *_dlerror(void)
#include "rbpaths.h"
#include "general.h"
-void * _lc_open(const _lc_open_char *filename, char *buf, size_t buf_size)
+void * _lc_open(const _lc_open_char *filename, unsigned char *buf, size_t buf_size)
{
(void)buf;
(void)buf_size;
- void* dl_handle = dlopen(filename, RTLD_NOW);
- return dl_handle;
+ return dlopen(filename, RTLD_NOW);
}
void *lc_open_from_mem(void *addr, size_t blob_size)