diff options
-rw-r--r-- | apps/codecs.c | 7 | ||||
-rw-r--r-- | apps/codecs.h | 23 | ||||
-rw-r--r-- | apps/codecs/codec_crt0.c | 28 | ||||
-rw-r--r-- | apps/plugin.c | 17 | ||||
-rw-r--r-- | apps/plugin.h | 21 | ||||
-rw-r--r-- | apps/plugins/lib/overlay.c | 76 | ||||
-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 | ||||
-rw-r--r-- | uisimulator/common/io.c | 2 |
10 files changed, 162 insertions, 100 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) | |||
181 | 181 | ||
182 | static int codec_load_ram(void *handle, struct codec_api *api) | 182 | static int codec_load_ram(void *handle, struct codec_api *api) |
183 | { | 183 | { |
184 | struct codec_header *hdr = lc_get_header(handle); | 184 | struct codec_header *c_hdr = lc_get_header(handle); |
185 | struct lc_header *hdr = c_hdr ? &c_hdr->lc_hdr : NULL; | ||
185 | int status; | 186 | int status; |
186 | 187 | ||
187 | if (hdr == NULL | 188 | if (hdr == NULL |
@@ -215,8 +216,8 @@ static int codec_load_ram(void *handle, struct codec_api *api) | |||
215 | codec_size = 0; | 216 | codec_size = 0; |
216 | #endif | 217 | #endif |
217 | 218 | ||
218 | *(hdr->api) = api; | 219 | *(c_hdr->api) = api; |
219 | status = hdr->entry_point(); | 220 | status = c_hdr->entry_point(); |
220 | 221 | ||
221 | lc_close(handle); | 222 | lc_close(handle); |
222 | 223 | ||
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 @@ | |||
51 | #include "settings.h" | 51 | #include "settings.h" |
52 | 52 | ||
53 | #include "gcc_extensions.h" | 53 | #include "gcc_extensions.h" |
54 | #include "load_code.h" | ||
54 | 55 | ||
55 | #ifdef CODEC | 56 | #ifdef CODEC |
56 | #if defined(DEBUG) || defined(SIMULATOR) | 57 | #if defined(DEBUG) || defined(SIMULATOR) |
@@ -240,11 +241,7 @@ struct codec_api { | |||
240 | 241 | ||
241 | /* codec header */ | 242 | /* codec header */ |
242 | struct codec_header { | 243 | struct codec_header { |
243 | unsigned long magic; /* RCOD or RENC */ | 244 | struct lc_header lc_hdr; /* must be first */ |
244 | unsigned short target_id; | ||
245 | unsigned short api_version; | ||
246 | unsigned char *load_addr; | ||
247 | unsigned char *end_addr; | ||
248 | enum codec_status(*entry_point)(void); | 245 | enum codec_status(*entry_point)(void); |
249 | struct codec_api **api; | 246 | struct codec_api **api; |
250 | }; | 247 | }; |
@@ -261,27 +258,27 @@ extern unsigned char plugin_end_addr[]; | |||
261 | #define CODEC_HEADER \ | 258 | #define CODEC_HEADER \ |
262 | const struct codec_header __header \ | 259 | const struct codec_header __header \ |
263 | __attribute__ ((section (".header")))= { \ | 260 | __attribute__ ((section (".header")))= { \ |
264 | CODEC_MAGIC, TARGET_ID, CODEC_API_VERSION, \ | 261 | { CODEC_MAGIC, TARGET_ID, CODEC_API_VERSION, \ |
265 | plugin_start_addr, plugin_end_addr, codec_start, &ci }; | 262 | plugin_start_addr, plugin_end_addr }, codec_start, &ci }; |
266 | /* encoders */ | 263 | /* encoders */ |
267 | #define CODEC_ENC_HEADER \ | 264 | #define CODEC_ENC_HEADER \ |
268 | const struct codec_header __header \ | 265 | const struct codec_header __header \ |
269 | __attribute__ ((section (".header")))= { \ | 266 | __attribute__ ((section (".header")))= { \ |
270 | CODEC_ENC_MAGIC, TARGET_ID, CODEC_API_VERSION, \ | 267 | { CODEC_ENC_MAGIC, TARGET_ID, CODEC_API_VERSION, \ |
271 | plugin_start_addr, plugin_end_addr, codec_start, &ci }; | 268 | plugin_start_addr, plugin_end_addr }, codec_start, &ci }; |
272 | 269 | ||
273 | #else /* def SIMULATOR */ | 270 | #else /* def SIMULATOR */ |
274 | /* decoders */ | 271 | /* decoders */ |
275 | #define CODEC_HEADER \ | 272 | #define CODEC_HEADER \ |
276 | const struct codec_header __header \ | 273 | const struct codec_header __header \ |
277 | __attribute__((visibility("default"))) = { \ | 274 | __attribute__((visibility("default"))) = { \ |
278 | CODEC_MAGIC, TARGET_ID, CODEC_API_VERSION, \ | 275 | { CODEC_MAGIC, TARGET_ID, CODEC_API_VERSION, NULL, NULL }, \ |
279 | NULL, NULL, codec_start, &ci }; | 276 | codec_start, &ci }; |
280 | /* encoders */ | 277 | /* encoders */ |
281 | #define CODEC_ENC_HEADER \ | 278 | #define CODEC_ENC_HEADER \ |
282 | const struct codec_header __header = { \ | 279 | const struct codec_header __header = { \ |
283 | CODEC_ENC_MAGIC, TARGET_ID, CODEC_API_VERSION, \ | 280 | { CODEC_ENC_MAGIC, TARGET_ID, CODEC_API_VERSION, NULL, NULL }, \ |
284 | NULL, NULL, codec_start, &ci }; | 281 | codec_start, &ci }; |
285 | #endif /* SIMULATOR */ | 282 | #endif /* SIMULATOR */ |
286 | #endif /* CODEC */ | 283 | #endif /* CODEC */ |
287 | 284 | ||
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 @@ | |||
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | 21 | ||
22 | #include "config.h" | 22 | #include "config.h" |
23 | #include "codeclib.h" | 23 | #include "codecs.h" |
24 | 24 | ||
25 | struct codec_api *ci DATA_ATTR; | 25 | struct codec_api *ci DATA_ATTR; |
26 | 26 | ||
27 | extern unsigned char iramcopy[]; | ||
28 | extern unsigned char iramstart[]; | ||
29 | extern unsigned char iramend[]; | ||
30 | extern unsigned char iedata[]; | ||
31 | extern unsigned char iend[]; | ||
32 | extern unsigned char plugin_bss_start[]; | 27 | extern unsigned char plugin_bss_start[]; |
33 | extern unsigned char plugin_end_addr[]; | 28 | extern unsigned char plugin_end_addr[]; |
34 | 29 | ||
@@ -42,14 +37,23 @@ enum codec_status codec_start(void) | |||
42 | { | 37 | { |
43 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | 38 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) |
44 | #ifdef USE_IRAM | 39 | #ifdef USE_IRAM |
45 | ci->memcpy(iramstart, iramcopy, iramend - iramstart); | 40 | extern char iramcopy[], iramstart[], iramend[], iedata[], iend[]; |
46 | ci->memset(iedata, 0, iend - iedata); | 41 | size_t iram_size = iramend - iramstart; |
47 | #endif | 42 | size_t ibss_size = iend - iedata; |
43 | if (iram_size > 0 || ibss_size > 0) | ||
44 | { | ||
45 | ci->memcpy(iramstart, iramcopy, iram_size); | ||
46 | ci->memset(iedata, 0, ibss_size); | ||
47 | /* make the icache (if it exists) up to date with the new code */ | ||
48 | ci->cpucache_invalidate(); | ||
49 | /* barrier to prevent reordering iram copy and BSS clearing, | ||
50 | * because the BSS segment alias the IRAM copy. | ||
51 | */ | ||
52 | asm volatile ("" ::: "memory"); | ||
53 | } | ||
54 | #endif /* PLUGIN_USE_IRAM */ | ||
48 | ci->memset(plugin_bss_start, 0, plugin_end_addr - plugin_bss_start); | 55 | ci->memset(plugin_bss_start, 0, plugin_end_addr - plugin_bss_start); |
49 | #endif | 56 | #endif |
50 | /* writeback cleared iedata and bss areas, invalidate icache for | ||
51 | * copied code */ | ||
52 | ci->cpucache_invalidate(); | ||
53 | 57 | ||
54 | return codec_main(); | 58 | return codec_main(); |
55 | } | 59 | } |
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 = { | |||
723 | /* new stuff at the end, sort into place next time | 723 | /* new stuff at the end, sort into place next time |
724 | the API gets incompatible */ | 724 | the API gets incompatible */ |
725 | dir_get_info, | 725 | dir_get_info, |
726 | |||
727 | lc_open, | ||
728 | lc_open_from_mem, | ||
729 | lc_get_header, | ||
730 | lc_close, | ||
726 | }; | 731 | }; |
727 | 732 | ||
728 | int plugin_load(const char* plugin, const void* parameter) | 733 | int plugin_load(const char* plugin, const void* parameter) |
729 | { | 734 | { |
730 | int rc, i; | 735 | int rc, i; |
731 | struct plugin_header *hdr; | 736 | struct plugin_header *p_hdr; |
737 | struct lc_header *hdr; | ||
732 | 738 | ||
733 | #if LCD_DEPTH > 1 | 739 | #if LCD_DEPTH > 1 |
734 | fb_data* old_backdrop; | 740 | fb_data* old_backdrop; |
@@ -754,7 +760,10 @@ int plugin_load(const char* plugin, const void* parameter) | |||
754 | return -1; | 760 | return -1; |
755 | } | 761 | } |
756 | 762 | ||
757 | hdr = lc_get_header(current_plugin_handle); | 763 | p_hdr = lc_get_header(current_plugin_handle); |
764 | |||
765 | hdr = p_hdr ? &p_hdr->lc_hdr : NULL; | ||
766 | |||
758 | 767 | ||
759 | if (hdr == NULL | 768 | if (hdr == NULL |
760 | || hdr->magic != PLUGIN_MAGIC | 769 | || hdr->magic != PLUGIN_MAGIC |
@@ -782,7 +791,7 @@ int plugin_load(const char* plugin, const void* parameter) | |||
782 | plugin_size = 0; | 791 | plugin_size = 0; |
783 | #endif | 792 | #endif |
784 | 793 | ||
785 | *(hdr->api) = &rockbox_api; | 794 | *(p_hdr->api) = &rockbox_api; |
786 | 795 | ||
787 | #if defined HAVE_LCD_BITMAP && LCD_DEPTH > 1 | 796 | #if defined HAVE_LCD_BITMAP && LCD_DEPTH > 1 |
788 | old_backdrop = lcd_get_backdrop(); | 797 | old_backdrop = lcd_get_backdrop(); |
@@ -806,7 +815,7 @@ int plugin_load(const char* plugin, const void* parameter) | |||
806 | open_files = 0; | 815 | open_files = 0; |
807 | #endif | 816 | #endif |
808 | 817 | ||
809 | rc = hdr->entry_point(parameter); | 818 | rc = p_hdr->entry_point(parameter); |
810 | 819 | ||
811 | if (!pfn_tsr_exit) | 820 | if (!pfn_tsr_exit) |
812 | { /* close handle if plugin is no tsr one */ | 821 | { /* 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); | |||
53 | #include "thread.h" | 53 | #include "thread.h" |
54 | #include "button.h" | 54 | #include "button.h" |
55 | #include "action.h" | 55 | #include "action.h" |
56 | #include "load_code.h" | ||
56 | #include "usb.h" | 57 | #include "usb.h" |
57 | #include "font.h" | 58 | #include "font.h" |
58 | #include "lcd.h" | 59 | #include "lcd.h" |
@@ -895,15 +896,17 @@ struct plugin_api { | |||
895 | /* new stuff at the end, sort into place next time | 896 | /* new stuff at the end, sort into place next time |
896 | the API gets incompatible */ | 897 | the API gets incompatible */ |
897 | struct dirinfo (*dir_get_info)(DIR* parent, struct dirent *entry); | 898 | struct dirinfo (*dir_get_info)(DIR* parent, struct dirent *entry); |
899 | |||
900 | /* load code api for overlay */ | ||
901 | void* (*lc_open)(const char *filename, unsigned char *buf, size_t buf_size); | ||
902 | void* (*lc_open_from_mem)(void* addr, size_t blob_size); | ||
903 | void* (*lc_get_header)(void *handle); | ||
904 | void (*lc_close)(void *handle); | ||
898 | }; | 905 | }; |
899 | 906 | ||
900 | /* plugin header */ | 907 | /* plugin header */ |
901 | struct plugin_header { | 908 | struct plugin_header { |
902 | unsigned long magic; | 909 | struct lc_header lc_hdr; /* must be the first */ |
903 | unsigned short target_id; | ||
904 | unsigned short api_version; | ||
905 | unsigned char *load_addr; | ||
906 | unsigned char *end_addr; | ||
907 | enum plugin_status(*entry_point)(const void*); | 910 | enum plugin_status(*entry_point)(const void*); |
908 | const struct plugin_api **api; | 911 | const struct plugin_api **api; |
909 | }; | 912 | }; |
@@ -916,15 +919,15 @@ extern unsigned char plugin_end_addr[]; | |||
916 | const struct plugin_api *rb DATA_ATTR; \ | 919 | const struct plugin_api *rb DATA_ATTR; \ |
917 | const struct plugin_header __header \ | 920 | const struct plugin_header __header \ |
918 | __attribute__ ((section (".header")))= { \ | 921 | __attribute__ ((section (".header")))= { \ |
919 | PLUGIN_MAGIC, TARGET_ID, PLUGIN_API_VERSION, \ | 922 | { PLUGIN_MAGIC, TARGET_ID, PLUGIN_API_VERSION, \ |
920 | plugin_start_addr, plugin_end_addr, plugin__start, &rb }; | 923 | plugin_start_addr, plugin_end_addr }, plugin__start, &rb }; |
921 | #else /* PLATFORM_HOSTED */ | 924 | #else /* PLATFORM_HOSTED */ |
922 | #define PLUGIN_HEADER \ | 925 | #define PLUGIN_HEADER \ |
923 | const struct plugin_api *rb DATA_ATTR; \ | 926 | const struct plugin_api *rb DATA_ATTR; \ |
924 | const struct plugin_header __header \ | 927 | const struct plugin_header __header \ |
925 | __attribute__((visibility("default"))) = { \ | 928 | __attribute__((visibility("default"))) = { \ |
926 | PLUGIN_MAGIC, TARGET_ID, PLUGIN_API_VERSION, \ | 929 | { PLUGIN_MAGIC, TARGET_ID, PLUGIN_API_VERSION, NULL, NULL }, |
927 | NULL, NULL, plugin__start, &rb }; | 930 | plugin__start, &rb }; |
928 | #endif /* CONFIG_PLATFORM */ | 931 | #endif /* CONFIG_PLATFORM */ |
929 | #endif /* PLUGIN */ | 932 | #endif /* PLUGIN */ |
930 | 933 | ||
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 @@ | |||
47 | enum plugin_status run_overlay(const void* parameter, | 47 | enum plugin_status run_overlay(const void* parameter, |
48 | unsigned char *filename, unsigned char *name) | 48 | unsigned char *filename, unsigned char *name) |
49 | { | 49 | { |
50 | int fd, readsize; | ||
51 | size_t audiobuf_size; | 50 | size_t audiobuf_size; |
52 | unsigned char *audiobuf; | 51 | unsigned char *audiobuf; |
53 | static struct plugin_header header; | 52 | void *handle; |
53 | struct plugin_header *p_hdr; | ||
54 | struct lc_header *hdr; | ||
54 | 55 | ||
55 | fd = rb->open(filename, O_RDONLY); | 56 | audiobuf = rb->plugin_get_audio_buffer(&audiobuf_size); |
56 | if (fd < 0) | 57 | if (!audiobuf) |
57 | { | 58 | { |
58 | rb->splashf(2*HZ, "Can't open %s", filename); | 59 | rb->splash(2*HZ, "Can't optain memory"); |
59 | return PLUGIN_ERROR; | 60 | goto error; |
60 | } | 61 | } |
61 | readsize = rb->read(fd, &header, sizeof(header)); | ||
62 | rb->close(fd); | ||
63 | /* Close for now. Less code than doing it in all error checks. | ||
64 | * Would need to seek back anyway. */ | ||
65 | 62 | ||
66 | if (readsize != sizeof(header)) | 63 | handle = rb->lc_open(filename, audiobuf, audiobuf_size); |
67 | { | 64 | if (!handle) |
68 | rb->splashf(2*HZ, "Reading %s overlay failed.", name); | ||
69 | return PLUGIN_ERROR; | ||
70 | } | ||
71 | if (header.magic != PLUGIN_MAGIC || header.target_id != TARGET_ID) | ||
72 | { | 65 | { |
73 | rb->splashf(2*HZ, "%s overlay: Incompatible model.", name); | 66 | rb->splashf(2*HZ, "Can't open %s", filename); |
74 | return PLUGIN_ERROR; | 67 | goto error; |
75 | } | ||
76 | if (header.api_version != PLUGIN_API_VERSION) | ||
77 | { | ||
78 | rb->splashf(2*HZ, "%s overlay: Incompatible version.", name); | ||
79 | return PLUGIN_ERROR; | ||
80 | } | 68 | } |
81 | 69 | ||
82 | audiobuf = rb->plugin_get_audio_buffer(&audiobuf_size); | 70 | p_hdr = rb->lc_get_header(handle); |
83 | if (header.load_addr < audiobuf || | 71 | if (!p_hdr) |
84 | header.end_addr > audiobuf + audiobuf_size) | ||
85 | { | 72 | { |
86 | rb->splashf(2*HZ, "%s overlay doesn't fit into memory.", name); | 73 | rb->splash(2*HZ, "Can't get header"); |
87 | return PLUGIN_ERROR; | 74 | goto error_close; |
88 | } | 75 | } |
76 | else | ||
77 | hdr = &p_hdr->lc_hdr; | ||
89 | 78 | ||
90 | fd = rb->open(filename, O_RDONLY); | 79 | if (hdr->magic != PLUGIN_MAGIC || hdr->target_id != TARGET_ID) |
91 | if (fd < 0) | ||
92 | { | 80 | { |
93 | rb->splashf(2*HZ, "Can't open %s", filename); | 81 | rb->splashf(2*HZ, "%s overlay: Incompatible model.", name); |
94 | return PLUGIN_ERROR; | 82 | goto error_close; |
95 | } | 83 | } |
96 | readsize = rb->read(fd, header.load_addr, header.end_addr - header.load_addr); | ||
97 | rb->close(fd); | ||
98 | 84 | ||
99 | if (readsize < 0) | 85 | |
86 | if (hdr->api_version > PLUGIN_API_VERSION | ||
87 | || hdr->api_version < PLUGIN_MIN_API_VERSION) | ||
100 | { | 88 | { |
101 | rb->splashf(2*HZ, "Reading %s overlay failed.", name); | 89 | rb->splashf(2*HZ, "%s overlay: Incompatible version.", name); |
102 | return PLUGIN_ERROR; | 90 | goto error_close; |
103 | } | 91 | } |
104 | /* Zero out bss area */ | ||
105 | rb->memset(header.load_addr + readsize, 0, | ||
106 | header.end_addr - (header.load_addr + readsize)); | ||
107 | 92 | ||
108 | *(header.api) = rb; | 93 | rb->lc_close(handle); |
109 | return header.entry_point(parameter); | 94 | |
95 | *(p_hdr->api) = rb; | ||
96 | return p_hdr->entry_point(parameter); | ||
97 | |||
98 | error_close: | ||
99 | rb->lc_close(handle); | ||
100 | error: | ||
101 | return PLUGIN_ERROR; | ||
110 | } | 102 | } |
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 | } |
diff --git a/uisimulator/common/io.c b/uisimulator/common/io.c index 56f1339fbc..3591905e32 100644 --- a/uisimulator/common/io.c +++ b/uisimulator/common/io.c | |||
@@ -526,7 +526,7 @@ int sim_fsync(int fd) | |||
526 | 526 | ||
527 | #ifndef __PCTOOL__ | 527 | #ifndef __PCTOOL__ |
528 | 528 | ||
529 | void *lc_open(const char *filename, char *buf, size_t buf_size) | 529 | void *lc_open(const char *filename, unsigned char *buf, size_t buf_size) |
530 | { | 530 | { |
531 | const char *sim_path = get_sim_pathname(filename); | 531 | const char *sim_path = get_sim_pathname(filename); |
532 | void *handle = _lc_open(UTF8_TO_OS(sim_path), buf, buf_size); | 532 | void *handle = _lc_open(UTF8_TO_OS(sim_path), buf, buf_size); |