From 0d4585b28ffcac1b62ed37cee2c34de0515df468 Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Thu, 9 Sep 2010 16:17:21 +0000 Subject: 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 --- firmware/load_code.c | 59 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 10 deletions(-) (limited to 'firmware/load_code.c') 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) -- cgit v1.2.3