diff options
| author | Thomas Martitz <kugel@rockbox.org> | 2010-09-09 16:17:21 +0000 |
|---|---|---|
| committer | Thomas Martitz <kugel@rockbox.org> | 2010-09-09 16:17:21 +0000 |
| commit | 0d4585b28ffcac1b62ed37cee2c34de0515df468 (patch) | |
| tree | 70ace8b78a4d0a44da50d692e893fadd93f85878 /firmware | |
| parent | cec7c99613b3c11deb8a05deecd7ee9d16b5ea8a (diff) | |
| download | rockbox-0d4585b28ffcac1b62ed37cee2c34de0515df468.zip rockbox-0d4585b28ffcac1b62ed37cee2c34de0515df468.tar.gz rockbox-0d4585b28ffcac1b62ed37cee2c34de0515df468.tar.bz2 rockbox-0d4585b28ffcac1b62ed37cee2c34de0515df468.tar.xz | |
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')
| -rw-r--r-- | firmware/export/load_code.h | 27 | ||||
| -rw-r--r-- | firmware/load_code.c | 59 | ||||
| -rw-r--r-- | firmware/target/hosted/android/lc-android.c | 2 |
3 files changed, 72 insertions, 16 deletions
diff --git a/firmware/export/load_code.h b/firmware/export/load_code.h index 6f5e5d0..55ce601 100644 --- a/firmware/export/load_code.h +++ b/firmware/export/load_code.h @@ -20,17 +20,21 @@ ****************************************************************************/ +#ifndef __LOAD_CODE_H__ +#define __LOAD_CODE_H__ + #include "config.h" #if (CONFIG_PLATFORM & PLATFORM_NATIVE) #include "system.h" -extern void *lc_open(const char *filename, char *buf, size_t buf_size); +extern void *lc_open(const char *filename, unsigned char *buf, size_t buf_size); /* header is always at the beginning of the blob, and handle actually points - * to the start of the blob */ + * to the start of the blob (the header is there) */ static inline void *lc_open_from_mem(void* addr, size_t blob_size) { (void)blob_size; + /* commit dcache and discard icache */ cpucache_invalidate(); return addr; } @@ -48,14 +52,27 @@ static inline void lc_close(void *handle) { (void)handle; } #else #define _lc_open_char char #endif -extern void *_lc_open(const _lc_open_char *filename, char *buf, size_t buf_size); +extern void *_lc_open(const _lc_open_char *filename, unsigned char *buf, size_t buf_size); extern void *_lc_get_header(void *handle); extern void _lc_close(void *handle); -extern void *lc_open(const char *filename, char *buf, size_t buf_size); -/* not possiible on hosted platforms */ +extern void *lc_open(const char *filename, unsigned char *buf, size_t buf_size); extern void *lc_open_from_mem(void *addr, size_t blob_size); extern void *lc_get_header(void *handle); extern void lc_close(void *handle); extern const char* lc_last_error(void); #endif + +/* this struct needs to be the first part of other headers + * (lc_open() casts the other header to this one to load to the correct + * address) + */ +struct lc_header { + unsigned long magic; + unsigned short target_id; + unsigned short api_version; + unsigned char *load_addr; + unsigned char *end_addr; +}; + +#endif /* __LOAD_CODE_H__ */ diff --git a/firmware/load_code.c b/firmware/load_code.c index 75bac8b..5b5307e 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) diff --git a/firmware/target/hosted/android/lc-android.c b/firmware/target/hosted/android/lc-android.c index 52ab08b..434e901 100644 --- a/firmware/target/hosted/android/lc-android.c +++ b/firmware/target/hosted/android/lc-android.c @@ -23,7 +23,7 @@ #include "load_code.h" /* the load_code wrappers simply wrap, nothing to do */ -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) { return _lc_open(filename, buf, buf_size); } |