diff options
-rw-r--r-- | apps/codecs.c | 101 | ||||
-rw-r--r-- | apps/plugin.c | 102 | ||||
-rw-r--r-- | apps/plugins/plugin_crt0.c | 6 | ||||
-rw-r--r-- | firmware/SOURCES | 1 | ||||
-rw-r--r-- | firmware/export/load_code.h | 55 | ||||
-rw-r--r-- | firmware/load_code.c | 165 | ||||
-rw-r--r-- | uisimulator/common/io.c | 113 |
7 files changed, 308 insertions, 235 deletions
diff --git a/apps/codecs.c b/apps/codecs.c index 9e77dd9099..b072c65f40 100644 --- a/apps/codecs.c +++ b/apps/codecs.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <ctype.h> | 28 | #include <ctype.h> |
29 | #include <stdarg.h> | 29 | #include <stdarg.h> |
30 | #include "string-extra.h" | 30 | #include "string-extra.h" |
31 | #include "load_code.h" | ||
31 | #include "debug.h" | 32 | #include "debug.h" |
32 | #include "button.h" | 33 | #include "button.h" |
33 | #include "dir.h" | 34 | #include "dir.h" |
@@ -74,26 +75,13 @@ size_t codec_size; | |||
74 | 75 | ||
75 | extern void* plugin_get_audio_buffer(size_t *buffer_size); | 76 | extern void* plugin_get_audio_buffer(size_t *buffer_size); |
76 | 77 | ||
78 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) && defined(HAVE_RECORDING) | ||
77 | #undef open | 79 | #undef open |
78 | static int open(const char* pathname, int flags, ...) | 80 | static int open(const char* pathname, int flags, ...) |
79 | { | 81 | { |
80 | #if (CONFIG_PLATFORM & PLATFORM_HOSTED) | ||
81 | int fd; | ||
82 | if (flags & O_CREAT) | ||
83 | { | ||
84 | va_list ap; | ||
85 | va_start(ap, flags); | ||
86 | fd = sim_open(pathname, flags, va_arg(ap, unsigned int)); | ||
87 | va_end(ap); | ||
88 | } | ||
89 | else | ||
90 | fd = sim_open(pathname, flags); | ||
91 | |||
92 | return fd; | ||
93 | #else | ||
94 | return file_open(pathname, flags); | 82 | return file_open(pathname, flags); |
95 | #endif | ||
96 | } | 83 | } |
84 | #endif | ||
97 | struct codec_api ci = { | 85 | struct codec_api ci = { |
98 | 86 | ||
99 | 0, /* filesize */ | 87 | 0, /* filesize */ |
@@ -197,62 +185,46 @@ void codec_get_full_path(char *path, const char *codec_root_fn) | |||
197 | CODECS_DIR, codec_root_fn); | 185 | CODECS_DIR, codec_root_fn); |
198 | } | 186 | } |
199 | 187 | ||
200 | static int codec_load_ram(int size, struct codec_api *api) | 188 | static int codec_load_ram(void *handle, struct codec_api *api) |
201 | { | 189 | { |
202 | struct codec_header *hdr; | 190 | struct codec_header *hdr = lc_get_header(handle); |
203 | int status; | 191 | int status; |
204 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | 192 | |
205 | hdr = (struct codec_header *)codecbuf; | 193 | if (hdr == NULL |
206 | |||
207 | if (size <= (signed)sizeof(struct codec_header) | ||
208 | || (hdr->magic != CODEC_MAGIC | 194 | || (hdr->magic != CODEC_MAGIC |
209 | #ifdef HAVE_RECORDING | 195 | #ifdef HAVE_RECORDING |
210 | && hdr->magic != CODEC_ENC_MAGIC | 196 | && hdr->magic != CODEC_ENC_MAGIC |
211 | #endif | 197 | #endif |
212 | ) | 198 | ) |
213 | || hdr->target_id != TARGET_ID | 199 | || hdr->target_id != TARGET_ID |
200 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | ||
214 | || hdr->load_addr != codecbuf | 201 | || hdr->load_addr != codecbuf |
215 | || hdr->end_addr > codecbuf + CODEC_SIZE) | 202 | || hdr->end_addr > codecbuf + CODEC_SIZE |
203 | #endif | ||
204 | ) | ||
216 | { | 205 | { |
217 | logf("codec header error"); | 206 | logf("codec header error"); |
207 | lc_close(handle); | ||
218 | return CODEC_ERROR; | 208 | return CODEC_ERROR; |
219 | } | 209 | } |
220 | 210 | ||
221 | codec_size = hdr->end_addr - codecbuf; | ||
222 | |||
223 | #elif (CONFIG_PLATFORM & PLATFORM_HOSTED) | ||
224 | void *pd; | ||
225 | |||
226 | hdr = sim_codec_load_ram(codecbuf, size, &pd); | ||
227 | |||
228 | if (pd == NULL) | ||
229 | return CODEC_ERROR; | ||
230 | |||
231 | if (hdr == NULL | ||
232 | || (hdr->magic != CODEC_MAGIC | ||
233 | #ifdef HAVE_RECORDING | ||
234 | && hdr->magic != CODEC_ENC_MAGIC | ||
235 | #endif | ||
236 | ) | ||
237 | || hdr->target_id != TARGET_ID) { | ||
238 | sim_codec_close(pd); | ||
239 | return CODEC_ERROR; | ||
240 | } | ||
241 | |||
242 | codec_size = codecbuf - codecbuf; | ||
243 | |||
244 | #endif /* CONFIG_PLATFORM */ | ||
245 | if (hdr->api_version > CODEC_API_VERSION | 211 | if (hdr->api_version > CODEC_API_VERSION |
246 | || hdr->api_version < CODEC_MIN_API_VERSION) { | 212 | || hdr->api_version < CODEC_MIN_API_VERSION) { |
247 | sim_codec_close(pd); | 213 | logf("codec api version error"); |
214 | lc_close(handle); | ||
248 | return CODEC_ERROR; | 215 | return CODEC_ERROR; |
249 | } | 216 | } |
250 | 217 | ||
218 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | ||
219 | codec_size = hdr->end_addr - codecbuf; | ||
220 | #else | ||
221 | codec_size = 0; | ||
222 | #endif | ||
223 | |||
251 | *(hdr->api) = api; | 224 | *(hdr->api) = api; |
252 | cpucache_invalidate(); | ||
253 | status = hdr->entry_point(); | 225 | status = hdr->entry_point(); |
254 | 226 | ||
255 | sim_codec_close(pd); | 227 | lc_close(handle); |
256 | 228 | ||
257 | return status; | 229 | return status; |
258 | } | 230 | } |
@@ -260,36 +232,37 @@ static int codec_load_ram(int size, struct codec_api *api) | |||
260 | int codec_load_buf(unsigned int hid, struct codec_api *api) | 232 | int codec_load_buf(unsigned int hid, struct codec_api *api) |
261 | { | 233 | { |
262 | int rc; | 234 | int rc; |
235 | void *handle; | ||
263 | rc = bufread(hid, CODEC_SIZE, codecbuf); | 236 | rc = bufread(hid, CODEC_SIZE, codecbuf); |
264 | if (rc < 0) { | 237 | if (rc < 0) { |
265 | logf("error loading codec"); | 238 | logf("error loading codec"); |
266 | return CODEC_ERROR; | 239 | return CODEC_ERROR; |
267 | } | 240 | } |
241 | handle = lc_open_from_mem(codecbuf, rc); | ||
242 | if (handle == NULL) | ||
243 | { | ||
244 | logf("error loading codec"); | ||
245 | return CODEC_ERROR; | ||
246 | } | ||
247 | |||
268 | api->discard_codec(); | 248 | api->discard_codec(); |
269 | return codec_load_ram(rc, api); | 249 | return codec_load_ram(handle, api); |
270 | } | 250 | } |
271 | 251 | ||
272 | int codec_load_file(const char *plugin, struct codec_api *api) | 252 | int codec_load_file(const char *plugin, struct codec_api *api) |
273 | { | 253 | { |
274 | char path[MAX_PATH]; | 254 | char path[MAX_PATH]; |
275 | int fd; | 255 | void *handle; |
276 | int rc; | ||
277 | 256 | ||
278 | codec_get_full_path(path, plugin); | 257 | codec_get_full_path(path, plugin); |
279 | 258 | ||
280 | fd = open(path, O_RDONLY); | 259 | handle = lc_open(path, codecbuf, CODEC_SIZE); |
281 | if (fd < 0) { | 260 | |
282 | logf("Codec load error:%d", fd); | 261 | if (handle == NULL) { |
262 | logf("Codec load error"); | ||
283 | splashf(HZ*2, "Couldn't load codec: %s", path); | 263 | splashf(HZ*2, "Couldn't load codec: %s", path); |
284 | return fd; | ||
285 | } | ||
286 | |||
287 | rc = read(fd, &codecbuf[0], CODEC_SIZE); | ||
288 | close(fd); | ||
289 | if (rc <= 0) { | ||
290 | logf("Codec read error"); | ||
291 | return CODEC_ERROR; | 264 | return CODEC_ERROR; |
292 | } | 265 | } |
293 | 266 | ||
294 | return codec_load_ram((size_t)rc, api); | 267 | return codec_load_ram(handle, api); |
295 | } | 268 | } |
diff --git a/apps/plugin.c b/apps/plugin.c index cc540cd988..53a05bf527 100644 --- a/apps/plugin.c +++ b/apps/plugin.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include "errno.h" | 42 | #include "errno.h" |
43 | #include "diacritic.h" | 43 | #include "diacritic.h" |
44 | #include "filefuncs.h" | 44 | #include "filefuncs.h" |
45 | #include "load_code.h" | ||
45 | 46 | ||
46 | #if CONFIG_CHARGING | 47 | #if CONFIG_CHARGING |
47 | #include "power.h" | 48 | #include "power.h" |
@@ -75,21 +76,19 @@ static unsigned int open_files; | |||
75 | 76 | ||
76 | #if (CONFIG_PLATFORM & PLATFORM_HOSTED) | 77 | #if (CONFIG_PLATFORM & PLATFORM_HOSTED) |
77 | static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE]; | 78 | static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE]; |
78 | void *sim_plugin_load(char *plugin, void **pd); | ||
79 | void sim_plugin_close(void *pd); | ||
80 | void sim_lcd_ex_init(unsigned long (*getpixel)(int, int)); | 79 | void sim_lcd_ex_init(unsigned long (*getpixel)(int, int)); |
81 | void sim_lcd_ex_update_rect(int x, int y, int width, int height); | 80 | void sim_lcd_ex_update_rect(int x, int y, int width, int height); |
82 | #else | 81 | #else |
83 | #define sim_plugin_close(x) | ||
84 | extern unsigned char pluginbuf[]; | 82 | extern unsigned char pluginbuf[]; |
85 | #include "bitswap.h" | 83 | #include "bitswap.h" |
86 | #endif | 84 | #endif |
87 | 85 | ||
88 | /* for actual plugins only, not for codecs */ | 86 | /* for actual plugins only, not for codecs */ |
89 | static bool plugin_loaded = false; | ||
90 | static int plugin_size = 0; | 87 | static int plugin_size = 0; |
91 | static bool (*pfn_tsr_exit)(bool reenter) = NULL; /* TSR exit callback */ | 88 | static bool (*pfn_tsr_exit)(bool reenter) = NULL; /* TSR exit callback */ |
92 | static char current_plugin[MAX_PATH]; | 89 | static char current_plugin[MAX_PATH]; |
90 | /* NULL if no plugin is loaded, otherwise the handle that lc_open() returned */ | ||
91 | static void *current_plugin_handle; | ||
93 | 92 | ||
94 | char *plugin_get_current_filename(void); | 93 | char *plugin_get_current_filename(void); |
95 | 94 | ||
@@ -728,98 +727,60 @@ int plugin_load(const char* plugin, const void* parameter) | |||
728 | { | 727 | { |
729 | int rc, i; | 728 | int rc, i; |
730 | struct plugin_header *hdr; | 729 | struct plugin_header *hdr; |
731 | #if (CONFIG_PLATFORM & PLATFORM_HOSTED) | ||
732 | void *pd; | ||
733 | #else /* PLATFOR_NATIVE */ | ||
734 | int fd; | ||
735 | ssize_t readsize; | ||
736 | #if NUM_CORES > 1 | ||
737 | unsigned my_core; | ||
738 | #endif | ||
739 | #endif /* CONFIG_PLATFORM */ | ||
740 | 730 | ||
741 | #if LCD_DEPTH > 1 | 731 | #if LCD_DEPTH > 1 |
742 | fb_data* old_backdrop; | 732 | fb_data* old_backdrop; |
743 | #endif | 733 | #endif |
744 | 734 | ||
745 | if (pfn_tsr_exit != NULL) /* if we have a resident old plugin: */ | 735 | if (current_plugin_handle && pfn_tsr_exit) |
746 | { | 736 | { /* if we have a resident old plugin and a callback */ |
747 | if (pfn_tsr_exit(!strcmp(current_plugin, plugin)) == false ) | 737 | if (pfn_tsr_exit(!strcmp(current_plugin, plugin)) == false ) |
748 | { | 738 | { |
749 | /* not allowing another plugin to load */ | 739 | /* not allowing another plugin to load */ |
750 | return PLUGIN_OK; | 740 | return PLUGIN_OK; |
751 | } | 741 | } |
752 | pfn_tsr_exit = NULL; | 742 | lc_close(current_plugin_handle); |
753 | plugin_loaded = false; | 743 | current_plugin_handle = pfn_tsr_exit = NULL; |
754 | } | 744 | } |
755 | 745 | ||
756 | splash(0, ID2P(LANG_WAIT)); | 746 | splash(0, ID2P(LANG_WAIT)); |
757 | strcpy(current_plugin, plugin); | 747 | strcpy(current_plugin, plugin); |
758 | 748 | ||
759 | #if (CONFIG_PLATFORM & PLATFORM_HOSTED) | 749 | current_plugin_handle = lc_open(plugin, pluginbuf, PLUGIN_BUFFER_SIZE); |
760 | hdr = sim_plugin_load((char *)plugin, &pd); | 750 | if (current_plugin_handle == NULL) { |
761 | if (pd == NULL) { | ||
762 | splashf(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin); | 751 | splashf(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin); |
763 | return -1; | 752 | return -1; |
764 | } | 753 | } |
765 | if (hdr == NULL | ||
766 | || hdr->magic != PLUGIN_MAGIC | ||
767 | || hdr->target_id != TARGET_ID) { | ||
768 | sim_plugin_close(pd); | ||
769 | splash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL)); | ||
770 | return -1; | ||
771 | } | ||
772 | if (hdr->api_version > PLUGIN_API_VERSION | ||
773 | || hdr->api_version < PLUGIN_MIN_API_VERSION) { | ||
774 | sim_plugin_close(pd); | ||
775 | splash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION)); | ||
776 | return -1; | ||
777 | } | ||
778 | #else | ||
779 | fd = open(plugin, O_RDONLY); | ||
780 | if (fd < 0) { | ||
781 | splashf(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin); | ||
782 | return fd; | ||
783 | } | ||
784 | #if NUM_CORES > 1 | ||
785 | /* Make sure COP cache is flushed and invalidated before loading */ | ||
786 | my_core = switch_core(CURRENT_CORE ^ 1); | ||
787 | cpucache_invalidate(); | ||
788 | switch_core(my_core); | ||
789 | #endif | ||
790 | 754 | ||
791 | readsize = read(fd, pluginbuf, PLUGIN_BUFFER_SIZE); | 755 | hdr = lc_get_header(current_plugin_handle); |
792 | close(fd); | ||
793 | 756 | ||
794 | if (readsize < 0) { | 757 | if (hdr == NULL |
795 | splashf(HZ*2, str(LANG_READ_FAILED), plugin); | ||
796 | return -1; | ||
797 | } | ||
798 | hdr = (struct plugin_header *)pluginbuf; | ||
799 | |||
800 | if ((unsigned)readsize <= sizeof(struct plugin_header) | ||
801 | || hdr->magic != PLUGIN_MAGIC | 758 | || hdr->magic != PLUGIN_MAGIC |
802 | || hdr->target_id != TARGET_ID | 759 | || hdr->target_id != TARGET_ID |
760 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | ||
803 | || hdr->load_addr != pluginbuf | 761 | || hdr->load_addr != pluginbuf |
804 | || hdr->end_addr > pluginbuf + PLUGIN_BUFFER_SIZE) { | 762 | || hdr->end_addr > pluginbuf + PLUGIN_BUFFER_SIZE |
763 | #endif | ||
764 | ) | ||
765 | { | ||
766 | lc_close(current_plugin_handle); | ||
805 | splash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL)); | 767 | splash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL)); |
806 | return -1; | 768 | return -1; |
807 | } | 769 | } |
808 | if (hdr->api_version > PLUGIN_API_VERSION | 770 | if (hdr->api_version > PLUGIN_API_VERSION |
809 | || hdr->api_version < PLUGIN_MIN_API_VERSION) { | 771 | || hdr->api_version < PLUGIN_MIN_API_VERSION) |
772 | { | ||
773 | lc_close(current_plugin_handle); | ||
810 | splash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION)); | 774 | splash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION)); |
811 | return -1; | 775 | return -1; |
812 | } | 776 | } |
777 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | ||
813 | plugin_size = hdr->end_addr - pluginbuf; | 778 | plugin_size = hdr->end_addr - pluginbuf; |
814 | 779 | #else | |
815 | /* zero out bss area only, above guards end of pluginbuf */ | 780 | plugin_size = 0; |
816 | if (plugin_size > readsize) | ||
817 | memset(pluginbuf + readsize, 0, plugin_size - readsize); | ||
818 | #endif | 781 | #endif |
819 | 782 | ||
820 | *(hdr->api) = &rockbox_api; | 783 | *(hdr->api) = &rockbox_api; |
821 | plugin_loaded = true; | ||
822 | |||
823 | 784 | ||
824 | #if defined HAVE_LCD_BITMAP && LCD_DEPTH > 1 | 785 | #if defined HAVE_LCD_BITMAP && LCD_DEPTH > 1 |
825 | old_backdrop = lcd_get_backdrop(); | 786 | old_backdrop = lcd_get_backdrop(); |
@@ -834,8 +795,6 @@ int plugin_load(const char* plugin, const void* parameter) | |||
834 | 795 | ||
835 | FOR_NB_SCREENS(i) | 796 | FOR_NB_SCREENS(i) |
836 | viewportmanager_theme_enable(i, false, NULL); | 797 | viewportmanager_theme_enable(i, false, NULL); |
837 | |||
838 | cpucache_invalidate(); | ||
839 | 798 | ||
840 | #ifdef HAVE_TOUCHSCREEN | 799 | #ifdef HAVE_TOUCHSCREEN |
841 | touchscreen_set_mode(TOUCHSCREEN_BUTTON); | 800 | touchscreen_set_mode(TOUCHSCREEN_BUTTON); |
@@ -847,6 +806,12 @@ int plugin_load(const char* plugin, const void* parameter) | |||
847 | 806 | ||
848 | rc = hdr->entry_point(parameter); | 807 | rc = hdr->entry_point(parameter); |
849 | 808 | ||
809 | if (!pfn_tsr_exit) | ||
810 | { /* close handle if plugin is no tsr one */ | ||
811 | lc_close(current_plugin_handle); | ||
812 | current_plugin_handle = NULL; | ||
813 | } | ||
814 | |||
850 | /* Go back to the global setting in case the plugin changed it */ | 815 | /* Go back to the global setting in case the plugin changed it */ |
851 | #ifdef HAVE_TOUCHSCREEN | 816 | #ifdef HAVE_TOUCHSCREEN |
852 | touchscreen_set_mode(global_settings.touch_mode); | 817 | touchscreen_set_mode(global_settings.touch_mode); |
@@ -887,11 +852,8 @@ int plugin_load(const char* plugin, const void* parameter) | |||
887 | FOR_NB_SCREENS(i) | 852 | FOR_NB_SCREENS(i) |
888 | viewportmanager_theme_undo(i, false); | 853 | viewportmanager_theme_undo(i, false); |
889 | 854 | ||
890 | if (pfn_tsr_exit == NULL) | ||
891 | plugin_loaded = false; | ||
892 | |||
893 | #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE | 855 | #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE |
894 | if(open_files != 0 && !plugin_loaded) | 856 | if(open_files != 0 && !current_plugin_handle) |
895 | { | 857 | { |
896 | int fd; | 858 | int fd; |
897 | logf("Plugin '%s' leaks file handles", plugin); | 859 | logf("Plugin '%s' leaks file handles", plugin); |
@@ -909,8 +871,6 @@ int plugin_load(const char* plugin, const void* parameter) | |||
909 | } | 871 | } |
910 | #endif | 872 | #endif |
911 | 873 | ||
912 | sim_plugin_close(pd); | ||
913 | |||
914 | if (rc == PLUGIN_ERROR) | 874 | if (rc == PLUGIN_ERROR) |
915 | splash(HZ*2, str(LANG_PLUGIN_ERROR)); | 875 | splash(HZ*2, str(LANG_PLUGIN_ERROR)); |
916 | 876 | ||
@@ -923,7 +883,7 @@ void* plugin_get_buffer(size_t *buffer_size) | |||
923 | { | 883 | { |
924 | int buffer_pos; | 884 | int buffer_pos; |
925 | 885 | ||
926 | if (plugin_loaded) | 886 | if (current_plugin_handle) |
927 | { | 887 | { |
928 | if (plugin_size >= PLUGIN_BUFFER_SIZE) | 888 | if (plugin_size >= PLUGIN_BUFFER_SIZE) |
929 | return NULL; | 889 | return NULL; |
diff --git a/apps/plugins/plugin_crt0.c b/apps/plugins/plugin_crt0.c index 536eccaffa..e34124c5a2 100644 --- a/apps/plugins/plugin_crt0.c +++ b/apps/plugins/plugin_crt0.c | |||
@@ -32,6 +32,8 @@ PLUGIN_HEADER | |||
32 | #define EXIT_MAGIC 0x0CDEBABE | 32 | #define EXIT_MAGIC 0x0CDEBABE |
33 | 33 | ||
34 | extern enum plugin_status plugin_start(const void*); | 34 | extern enum plugin_status plugin_start(const void*); |
35 | extern unsigned char plugin_bss_start[]; | ||
36 | extern unsigned char plugin_end_addr[]; | ||
35 | 37 | ||
36 | static jmp_buf __exit_env; | 38 | static jmp_buf __exit_env; |
37 | /* only 1 atexit handler for now, chain in the exit handler if you need more */ | 39 | /* only 1 atexit handler for now, chain in the exit handler if you need more */ |
@@ -61,6 +63,10 @@ enum plugin_status plugin__start(const void *param) | |||
61 | int exit_ret; | 63 | int exit_ret; |
62 | enum plugin_status ret; | 64 | enum plugin_status ret; |
63 | 65 | ||
66 | /* zero out the bss section */ | ||
67 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | ||
68 | rb->memset(plugin_bss_start, 0, plugin_end_addr - plugin_bss_start); | ||
69 | #endif | ||
64 | /* we come back here if exit() was called or the plugin returned normally */ | 70 | /* we come back here if exit() was called or the plugin returned normally */ |
65 | exit_ret = setjmp(__exit_env); | 71 | exit_ret = setjmp(__exit_env); |
66 | if (exit_ret == 0) | 72 | if (exit_ret == 0) |
diff --git a/firmware/SOURCES b/firmware/SOURCES index e6157fa7d0..f83b78970e 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES | |||
@@ -3,6 +3,7 @@ events.c | |||
3 | backlight.c | 3 | backlight.c |
4 | buffer.c | 4 | buffer.c |
5 | general.c | 5 | general.c |
6 | load_code.c | ||
6 | powermgmt.c | 7 | powermgmt.c |
7 | system.c | 8 | system.c |
8 | usb.c | 9 | usb.c |
diff --git a/firmware/export/load_code.h b/firmware/export/load_code.h new file mode 100644 index 0000000000..f4fa8f9b46 --- /dev/null +++ b/firmware/export/load_code.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 by Thomas Martitz | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | |||
23 | #include "config.h" | ||
24 | |||
25 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | ||
26 | #include "system.h" | ||
27 | |||
28 | extern void *lc_open(const char *filename, char *buf, size_t buf_size); | ||
29 | /* header is always at the beginning of the blob, and handle actually points | ||
30 | * to the start of the blob */ | ||
31 | static inline char *lc_open_from_mem(void* addr, size_t blob_size) | ||
32 | { | ||
33 | (void)blob_size; | ||
34 | cpucache_invalidate(); | ||
35 | return addr; | ||
36 | } | ||
37 | static inline void *lc_get_header(void *handle) { return handle; } | ||
38 | /* no need to do anything */ | ||
39 | static inline void lc_close(void *handle) { (void)handle; } | ||
40 | |||
41 | #elif (CONFIG_PLATFORM & PLATFORM_HOSTED) | ||
42 | |||
43 | /* don't call these directly for loading code | ||
44 | * they're to be wrapped by platform specific functions */ | ||
45 | extern void *_lc_open(const char *filename, char *buf, size_t buf_size); | ||
46 | extern void *_lc_get_header(void *handle); | ||
47 | extern void _lc_close(void *handle); | ||
48 | |||
49 | extern void *lc_open(const char *filename, char *buf, size_t buf_size); | ||
50 | /* not possiible on hosted platforms */ | ||
51 | extern void *lc_open_from_mem(void *addr, size_t blob_size); | ||
52 | extern void *lc_get_header(void *handle); | ||
53 | extern void lc_close(void *handle); | ||
54 | extern const char* lc_last_error(void); | ||
55 | #endif | ||
diff --git a/firmware/load_code.c b/firmware/load_code.c new file mode 100644 index 0000000000..9e8e71f9af --- /dev/null +++ b/firmware/load_code.c | |||
@@ -0,0 +1,165 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 by Thomas Martitz | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include "config.h" | ||
23 | #include "system.h" | ||
24 | #include "file.h" | ||
25 | #include "debug.h" | ||
26 | #include "load_code.h" | ||
27 | |||
28 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | ||
29 | /* load binary blob from disk to memory, returning a handle */ | ||
30 | void * lc_open(const char *filename, char *buf, size_t buf_size) | ||
31 | { | ||
32 | int fd = open(filename, O_RDONLY); | ||
33 | ssize_t read_size; | ||
34 | |||
35 | if (fd < 0) | ||
36 | { | ||
37 | DEBUGF("Could not open file"); | ||
38 | return NULL; | ||
39 | } | ||
40 | |||
41 | #if NUM_CORES > 1 | ||
42 | /* Make sure COP cache is flushed and invalidated before loading */ | ||
43 | { | ||
44 | int my_core = switch_core(CURRENT_CORE ^ 1); | ||
45 | cpucache_invalidate(); | ||
46 | switch_core(my_core); | ||
47 | } | ||
48 | #endif | ||
49 | |||
50 | read_size = read(fd, buf, buf_size); | ||
51 | close(fd); | ||
52 | cpucache_invalidate(); | ||
53 | |||
54 | if (read_size < 0) | ||
55 | { | ||
56 | DEBUGF("Could not read from file"); | ||
57 | return NULL; | ||
58 | } | ||
59 | return buf; | ||
60 | } | ||
61 | |||
62 | #elif (CONFIG_PLATFORM & PLATFORM_HOSTED) | ||
63 | /* libdl wrappers */ | ||
64 | |||
65 | |||
66 | #ifdef WIN32 | ||
67 | /* win32 */ | ||
68 | #include <windows.h> | ||
69 | #define dlopen(_x_, _y_) LoadLibraryW(_x_) | ||
70 | #define dlsym(_x_, _y_) (void *)GetProcAddress(_x_, _y_) | ||
71 | #define dlclose(_x_) FreeLibrary(_x_) | ||
72 | static inline char *_dlerror(void) | ||
73 | { | ||
74 | static char err_buf[64]; | ||
75 | FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, | ||
76 | err_buf, sizeof(err_buf), NULL); | ||
77 | return err_buf; | ||
78 | } | ||
79 | #define dlerror _dlerror | ||
80 | #else | ||
81 | /* unix */ | ||
82 | #include <dlfcn.h> | ||
83 | #define O_BINARY 0 | ||
84 | #endif | ||
85 | #include <stdio.h> | ||
86 | #include "rbpaths.h" | ||
87 | #include "general.h" | ||
88 | |||
89 | void * _lc_open(const char *filename, char *buf, size_t buf_size) | ||
90 | { | ||
91 | (void)buf; | ||
92 | (void)buf_size; | ||
93 | void* dl_handle = dlopen(filename, RTLD_NOW); | ||
94 | return dl_handle; | ||
95 | } | ||
96 | |||
97 | void *lc_open_from_mem(void *addr, size_t blob_size) | ||
98 | { | ||
99 | int fd, i; | ||
100 | char temp_filename[MAX_PATH]; | ||
101 | |||
102 | /* We have to create the dynamic link library file from ram so we | ||
103 | can simulate the codec loading. With voice and crossfade, | ||
104 | multiple codecs may be loaded at the same time, so we need | ||
105 | to find an unused filename */ | ||
106 | for (i = 0; i < 10; i++) | ||
107 | { | ||
108 | #if (CONFIG_PLATFORM & PLATFORM_ANDROID) | ||
109 | /* we need that path fixed, since get_user_file_path() | ||
110 | * gives us the folder on the sdcard where we cannot load libraries | ||
111 | * from (no exec permissions) | ||
112 | */ | ||
113 | snprintf(temp_filename, sizeof(temp_filename), | ||
114 | "/data/data/org.rockbox/app_rockbox/libtemp_binary_%d.so", i); | ||
115 | #else | ||
116 | char name[MAX_PATH]; | ||
117 | const char *_name = get_user_file_path(ROCKBOX_DIR, NEED_WRITE, name, sizeof(name)); | ||
118 | snprintf(temp_filename, sizeof(temp_filename), | ||
119 | "%slibtemp_binary_%d.dll", _name, i); | ||
120 | #endif | ||
121 | fd = open(temp_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0766); | ||
122 | if (fd >= 0) | ||
123 | break; /* Created a file ok */ | ||
124 | } | ||
125 | |||
126 | DEBUGF("Creating %s\n", temp_filename); | ||
127 | if (fd < 0) | ||
128 | { | ||
129 | DEBUGF("open failed\n"); | ||
130 | return NULL; | ||
131 | } | ||
132 | |||
133 | if (write(fd, addr, blob_size) < (ssize_t)blob_size) | ||
134 | { | ||
135 | DEBUGF("Write failed\n"); | ||
136 | close(fd); | ||
137 | remove(temp_filename); | ||
138 | return NULL; | ||
139 | } | ||
140 | |||
141 | close(fd); | ||
142 | return lc_open(temp_filename, NULL, 0); | ||
143 | } | ||
144 | |||
145 | |||
146 | void *_lc_get_header(void *handle) | ||
147 | { | ||
148 | char *ret = dlsym(handle, "__header"); | ||
149 | if (ret == NULL) | ||
150 | ret = dlsym(handle, "___header"); | ||
151 | |||
152 | return ret; | ||
153 | } | ||
154 | |||
155 | void _lc_close(void *handle) | ||
156 | { | ||
157 | if (handle) | ||
158 | dlclose(handle); | ||
159 | } | ||
160 | |||
161 | const char *lc_last_error(void) | ||
162 | { | ||
163 | return dlerror(); | ||
164 | } | ||
165 | #endif | ||
diff --git a/uisimulator/common/io.c b/uisimulator/common/io.c index 4c0fa33be5..c8d6a8a67d 100644 --- a/uisimulator/common/io.c +++ b/uisimulator/common/io.c | |||
@@ -58,6 +58,7 @@ | |||
58 | #include "debug.h" | 58 | #include "debug.h" |
59 | #include "ata.h" /* for IF_MV2 et al. */ | 59 | #include "ata.h" /* for IF_MV2 et al. */ |
60 | #include "rbpaths.h" | 60 | #include "rbpaths.h" |
61 | #include "load_code.h" | ||
61 | 62 | ||
62 | /* keep this in sync with file.h! */ | 63 | /* keep this in sync with file.h! */ |
63 | #undef MAX_PATH /* this avoids problems when building simulator */ | 64 | #undef MAX_PATH /* this avoids problems when building simulator */ |
@@ -530,116 +531,28 @@ int sim_fsync(int fd) | |||
530 | #include <dlfcn.h> | 531 | #include <dlfcn.h> |
531 | #endif | 532 | #endif |
532 | 533 | ||
533 | void *sim_codec_load_ram(char* codecptr, int size, void **pd) | ||
534 | { | ||
535 | void *hdr; | ||
536 | char path[MAX_PATH]; | ||
537 | int fd; | ||
538 | int codec_count; | ||
539 | #ifdef WIN32 | ||
540 | char buf[MAX_PATH]; | ||
541 | #endif | ||
542 | 534 | ||
543 | *pd = NULL; | 535 | void *lc_open(const char *filename, char *buf, size_t buf_size) |
544 | 536 | { | |
545 | /* We have to create the dynamic link library file from ram so we | 537 | const char *sim_path = get_sim_pathname(filename); |
546 | can simulate the codec loading. With voice and crossfade, | 538 | void *handle = _lc_open((const char*)UTF8_TO_OS(sim_path), buf, buf_size); |
547 | multiple codecs may be loaded at the same time, so we need | ||
548 | to find an unused filename */ | ||
549 | for (codec_count = 0; codec_count < 10; codec_count++) | ||
550 | { | ||
551 | #if (CONFIG_PLATFORM & PLATFORM_ANDROID) | ||
552 | /* we need that path fixed, since get_user_file_path() | ||
553 | * gives us the folder on the sdcard where we cannot load libraries | ||
554 | * from (no exec permissions) | ||
555 | */ | ||
556 | snprintf(path, sizeof(path), | ||
557 | "/data/data/org.rockbox/app_rockbox/libtemp_codec_%d.so", | ||
558 | codec_count); | ||
559 | #else | ||
560 | char name[MAX_PATH]; | ||
561 | const char *_name = get_user_file_path(ROCKBOX_DIR, 0, name, sizeof(name)); | ||
562 | snprintf(path, sizeof(path), "%s/_temp_codec%d.dll", get_sim_pathname(_name), codec_count); | ||
563 | #endif | ||
564 | fd = OPEN(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRWXU); | ||
565 | if (fd >= 0) | ||
566 | break; /* Created a file ok */ | ||
567 | } | ||
568 | if (fd < 0) | ||
569 | { | ||
570 | DEBUGF("failed to open for write: %s\n", path); | ||
571 | return NULL; | ||
572 | } | ||
573 | |||
574 | if (write(fd, codecptr, size) != size) | ||
575 | { | ||
576 | DEBUGF("write failed"); | ||
577 | return NULL; | ||
578 | } | ||
579 | close(fd); | ||
580 | 539 | ||
581 | /* Now load the library. */ | 540 | if (handle == NULL) |
582 | *pd = dlopen(path, RTLD_NOW); | ||
583 | if (*pd == NULL) | ||
584 | { | 541 | { |
585 | DEBUGF("failed to load %s\n", path); | 542 | DEBUGF("failed to load %s\n", filename); |
586 | #ifdef WIN32 | 543 | DEBUGF("lc_open(%s): %s\n", filename, lc_last_error()); |
587 | FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, | ||
588 | buf, sizeof buf, NULL); | ||
589 | DEBUGF("dlopen(%s): %s\n", path, buf); | ||
590 | #else | ||
591 | DEBUGF("dlopen(%s): %s\n", path, dlerror()); | ||
592 | #endif | ||
593 | return NULL; | ||
594 | } | 544 | } |
595 | 545 | return handle; | |
596 | hdr = dlsym(*pd, "__header"); | ||
597 | if (!hdr) | ||
598 | hdr = dlsym(*pd, "___header"); | ||
599 | |||
600 | return hdr; /* maybe NULL if symbol not present */ | ||
601 | } | ||
602 | |||
603 | void sim_codec_close(void *pd) | ||
604 | { | ||
605 | dlclose(pd); | ||
606 | } | 546 | } |
607 | 547 | ||
608 | void *sim_plugin_load(char *plugin, void **pd) | 548 | void *lc_get_header(void *handle) |
609 | { | 549 | { |
610 | void *hdr; | 550 | return _lc_get_header(handle); |
611 | char path[MAX_PATH]; | ||
612 | #ifdef WIN32 | ||
613 | char buf[MAX_PATH]; | ||
614 | #endif | ||
615 | |||
616 | snprintf(path, sizeof(path), "%s", get_sim_pathname(plugin)); | ||
617 | |||
618 | *pd = NULL; | ||
619 | |||
620 | *pd = dlopen(path, RTLD_NOW); | ||
621 | if (*pd == NULL) { | ||
622 | DEBUGF("failed to load %s\n", plugin); | ||
623 | #ifdef WIN32 | ||
624 | FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, | ||
625 | buf, sizeof(buf), NULL); | ||
626 | DEBUGF("dlopen(%s): %s\n", path, buf); | ||
627 | #else | ||
628 | DEBUGF("dlopen(%s): %s\n", path, dlerror()); | ||
629 | #endif | ||
630 | return NULL; | ||
631 | } | ||
632 | |||
633 | hdr = dlsym(*pd, "__header"); | ||
634 | if (!hdr) | ||
635 | hdr = dlsym(*pd, "___header"); | ||
636 | |||
637 | return hdr; /* maybe NULL if symbol not present */ | ||
638 | } | 551 | } |
639 | 552 | ||
640 | void sim_plugin_close(void *pd) | 553 | void lc_close(void *handle) |
641 | { | 554 | { |
642 | dlclose(pd); | 555 | _lc_close(handle); |
643 | } | 556 | } |
644 | 557 | ||
645 | #ifdef WIN32 | 558 | #ifdef WIN32 |