diff options
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 6f5e5d0842..55ce601ee5 100644 --- a/firmware/export/load_code.h +++ b/firmware/export/load_code.h | |||
@@ -20,17 +20,21 @@ | |||
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | 21 | ||
22 | 22 | ||
23 | #ifndef __LOAD_CODE_H__ | ||
24 | #define __LOAD_CODE_H__ | ||
25 | |||
23 | #include "config.h" | 26 | #include "config.h" |
24 | 27 | ||
25 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | 28 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) |
26 | #include "system.h" | 29 | #include "system.h" |
27 | 30 | ||
28 | extern void *lc_open(const char *filename, char *buf, size_t buf_size); | 31 | extern void *lc_open(const char *filename, unsigned char *buf, size_t buf_size); |
29 | /* header is always at the beginning of the blob, and handle actually points | 32 | /* header is always at the beginning of the blob, and handle actually points |
30 | * to the start of the blob */ | 33 | * to the start of the blob (the header is there) */ |
31 | static inline void *lc_open_from_mem(void* addr, size_t blob_size) | 34 | static inline void *lc_open_from_mem(void* addr, size_t blob_size) |
32 | { | 35 | { |
33 | (void)blob_size; | 36 | (void)blob_size; |
37 | /* commit dcache and discard icache */ | ||
34 | cpucache_invalidate(); | 38 | cpucache_invalidate(); |
35 | return addr; | 39 | return addr; |
36 | } | 40 | } |
@@ -48,14 +52,27 @@ static inline void lc_close(void *handle) { (void)handle; } | |||
48 | #else | 52 | #else |
49 | #define _lc_open_char char | 53 | #define _lc_open_char char |
50 | #endif | 54 | #endif |
51 | extern void *_lc_open(const _lc_open_char *filename, char *buf, size_t buf_size); | 55 | extern void *_lc_open(const _lc_open_char *filename, unsigned char *buf, size_t buf_size); |
52 | extern void *_lc_get_header(void *handle); | 56 | extern void *_lc_get_header(void *handle); |
53 | extern void _lc_close(void *handle); | 57 | extern void _lc_close(void *handle); |
54 | 58 | ||
55 | extern void *lc_open(const char *filename, char *buf, size_t buf_size); | 59 | extern void *lc_open(const char *filename, unsigned char *buf, size_t buf_size); |
56 | /* not possiible on hosted platforms */ | ||
57 | extern void *lc_open_from_mem(void *addr, size_t blob_size); | 60 | extern void *lc_open_from_mem(void *addr, size_t blob_size); |
58 | extern void *lc_get_header(void *handle); | 61 | extern void *lc_get_header(void *handle); |
59 | extern void lc_close(void *handle); | 62 | extern void lc_close(void *handle); |
60 | extern const char* lc_last_error(void); | 63 | extern const char* lc_last_error(void); |
61 | #endif | 64 | #endif |
65 | |||
66 | /* this struct needs to be the first part of other headers | ||
67 | * (lc_open() casts the other header to this one to load to the correct | ||
68 | * address) | ||
69 | */ | ||
70 | struct lc_header { | ||
71 | unsigned long magic; | ||
72 | unsigned short target_id; | ||
73 | unsigned short api_version; | ||
74 | unsigned char *load_addr; | ||
75 | unsigned char *end_addr; | ||
76 | }; | ||
77 | |||
78 | #endif /* __LOAD_CODE_H__ */ | ||
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 @@ | |||
26 | #include "load_code.h" | 26 | #include "load_code.h" |
27 | 27 | ||
28 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | 28 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) |
29 | |||
29 | /* load binary blob from disk to memory, returning a handle */ | 30 | /* load binary blob from disk to memory, returning a handle */ |
30 | void * lc_open(const char *filename, char *buf, size_t buf_size) | 31 | void * lc_open(const char *filename, unsigned char *buf, size_t buf_size) |
31 | { | 32 | { |
32 | int fd = open(filename, O_RDONLY); | 33 | int fd = open(filename, O_RDONLY); |
33 | ssize_t read_size; | 34 | ssize_t read_size; |
35 | struct lc_header hdr; | ||
36 | unsigned char *buf_end = buf+buf_size; | ||
37 | off_t copy_size; | ||
34 | 38 | ||
35 | if (fd < 0) | 39 | if (fd < 0) |
36 | { | 40 | { |
37 | DEBUGF("Could not open file"); | 41 | DEBUGF("Could not open file"); |
38 | return NULL; | 42 | goto error; |
39 | } | 43 | } |
40 | 44 | ||
41 | #if NUM_CORES > 1 | 45 | #if NUM_CORES > 1 |
42 | /* Make sure COP cache is flushed and invalidated before loading */ | 46 | /* Make sure COP cache is flushed and invalidated before loading */ |
43 | { | 47 | { |
44 | int my_core = switch_core(CURRENT_CORE ^ 1); | 48 | int my_core = switch_core(CURRENT_CORE ^ 1); |
45 | cpucache_invalidate(); | 49 | cpucache_commit_discard(); |
46 | switch_core(my_core); | 50 | switch_core(my_core); |
47 | } | 51 | } |
48 | #endif | 52 | #endif |
49 | 53 | ||
50 | read_size = read(fd, buf, buf_size); | 54 | /* read the header to obtain the load address */ |
55 | read_size = read(fd, &hdr, sizeof(hdr)); | ||
56 | |||
57 | if (read_size < 0) | ||
58 | { | ||
59 | DEBUGF("Could not read from file"); | ||
60 | goto error_fd; | ||
61 | } | ||
62 | |||
63 | /* hdr.end_addr points to the end of the bss section, | ||
64 | * but there might be idata/icode behind that so the bytes to copy | ||
65 | * can be larger */ | ||
66 | copy_size = MAX(filesize(fd), hdr.end_addr - hdr.load_addr); | ||
67 | |||
68 | if (hdr.load_addr < buf || (hdr.load_addr+copy_size) > buf_end) | ||
69 | { | ||
70 | DEBUGF("Binary doesn't fit into memory"); | ||
71 | goto error_fd; | ||
72 | } | ||
73 | |||
74 | /* go back to beginning to load the whole thing (incl. header) */ | ||
75 | if (lseek(fd, 0, SEEK_SET) < 0) | ||
76 | { | ||
77 | DEBUGF("lseek failed"); | ||
78 | goto error_fd; | ||
79 | } | ||
80 | |||
81 | /* the header has the addresses where the code is linked at */ | ||
82 | read_size = read(fd, hdr.load_addr, copy_size); | ||
51 | close(fd); | 83 | close(fd); |
52 | cpucache_invalidate(); | ||
53 | 84 | ||
54 | if (read_size < 0) | 85 | if (read_size < 0) |
55 | { | 86 | { |
56 | DEBUGF("Could not read from file"); | 87 | DEBUGF("Could not read from file"); |
57 | return NULL; | 88 | goto error; |
58 | } | 89 | } |
59 | return buf; | 90 | |
91 | /* commit dcache and discard icache */ | ||
92 | cpucache_commit_discard(); | ||
93 | /* return a pointer the header, reused by lc_get_header() */ | ||
94 | return hdr.load_addr; | ||
95 | |||
96 | error_fd: | ||
97 | close(fd); | ||
98 | error: | ||
99 | return NULL; | ||
60 | } | 100 | } |
61 | 101 | ||
62 | #elif (CONFIG_PLATFORM & PLATFORM_HOSTED) | 102 | #elif (CONFIG_PLATFORM & PLATFORM_HOSTED) |
@@ -85,12 +125,11 @@ static inline char *_dlerror(void) | |||
85 | #include "rbpaths.h" | 125 | #include "rbpaths.h" |
86 | #include "general.h" | 126 | #include "general.h" |
87 | 127 | ||
88 | void * _lc_open(const _lc_open_char *filename, char *buf, size_t buf_size) | 128 | void * _lc_open(const _lc_open_char *filename, unsigned char *buf, size_t buf_size) |
89 | { | 129 | { |
90 | (void)buf; | 130 | (void)buf; |
91 | (void)buf_size; | 131 | (void)buf_size; |
92 | void* dl_handle = dlopen(filename, RTLD_NOW); | 132 | return dlopen(filename, RTLD_NOW); |
93 | return dl_handle; | ||
94 | } | 133 | } |
95 | 134 | ||
96 | void *lc_open_from_mem(void *addr, size_t blob_size) | 135 | 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 52ab08badb..434e901a56 100644 --- a/firmware/target/hosted/android/lc-android.c +++ b/firmware/target/hosted/android/lc-android.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include "load_code.h" | 23 | #include "load_code.h" |
24 | 24 | ||
25 | /* the load_code wrappers simply wrap, nothing to do */ | 25 | /* the load_code wrappers simply wrap, nothing to do */ |
26 | void *lc_open(const char *filename, char *buf, size_t buf_size) | 26 | void *lc_open(const char *filename, unsigned char *buf, size_t buf_size) |
27 | { | 27 | { |
28 | return _lc_open(filename, buf, buf_size); | 28 | return _lc_open(filename, buf, buf_size); |
29 | } | 29 | } |