summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2010-08-26 23:20:02 +0000
committerThomas Martitz <kugel@rockbox.org>2010-08-26 23:20:02 +0000
commit73f057be6fcb849d5379073267e21e9526576ccd (patch)
treeb2b239517ba89f4e9969918642006a3d15faa062
parent55dc25fe7273bf9aa71cdaea9a68c39fa3a22f50 (diff)
downloadrockbox-73f057be6fcb849d5379073267e21e9526576ccd.tar.gz
rockbox-73f057be6fcb849d5379073267e21e9526576ccd.zip
Introduce a small api for loading code (codecs,plugins) from disk/memory.
It's a used by codec/plugin loading and vastly reduces code duplication. It's also a step forward in getting rid of libuisimulator in the application ports. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27900 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/codecs.c101
-rw-r--r--apps/plugin.c102
-rw-r--r--apps/plugins/plugin_crt0.c6
-rw-r--r--firmware/SOURCES1
-rw-r--r--firmware/export/load_code.h55
-rw-r--r--firmware/load_code.c165
-rw-r--r--uisimulator/common/io.c113
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
75extern void* plugin_get_audio_buffer(size_t *buffer_size); 76extern 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
78static int open(const char* pathname, int flags, ...) 80static 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
97struct codec_api ci = { 85struct 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
200static int codec_load_ram(int size, struct codec_api *api) 188static 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)
260int codec_load_buf(unsigned int hid, struct codec_api *api) 232int 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
272int codec_load_file(const char *plugin, struct codec_api *api) 252int 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)
77static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE]; 78static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE];
78void *sim_plugin_load(char *plugin, void **pd);
79void sim_plugin_close(void *pd);
80void sim_lcd_ex_init(unsigned long (*getpixel)(int, int)); 79void sim_lcd_ex_init(unsigned long (*getpixel)(int, int));
81void sim_lcd_ex_update_rect(int x, int y, int width, int height); 80void sim_lcd_ex_update_rect(int x, int y, int width, int height);
82#else 81#else
83#define sim_plugin_close(x)
84extern unsigned char pluginbuf[]; 82extern 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 */
89static bool plugin_loaded = false;
90static int plugin_size = 0; 87static int plugin_size = 0;
91static bool (*pfn_tsr_exit)(bool reenter) = NULL; /* TSR exit callback */ 88static bool (*pfn_tsr_exit)(bool reenter) = NULL; /* TSR exit callback */
92static char current_plugin[MAX_PATH]; 89static char current_plugin[MAX_PATH];
90/* NULL if no plugin is loaded, otherwise the handle that lc_open() returned */
91static void *current_plugin_handle;
93 92
94char *plugin_get_current_filename(void); 93char *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
34extern enum plugin_status plugin_start(const void*); 34extern enum plugin_status plugin_start(const void*);
35extern unsigned char plugin_bss_start[];
36extern unsigned char plugin_end_addr[];
35 37
36static jmp_buf __exit_env; 38static 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
3backlight.c 3backlight.c
4buffer.c 4buffer.c
5general.c 5general.c
6load_code.c
6powermgmt.c 7powermgmt.c
7system.c 8system.c
8usb.c 9usb.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
28extern 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 */
31static inline char *lc_open_from_mem(void* addr, size_t blob_size)
32{
33 (void)blob_size;
34 cpucache_invalidate();
35 return addr;
36}
37static inline void *lc_get_header(void *handle) { return handle; }
38/* no need to do anything */
39static 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 */
45extern void *_lc_open(const char *filename, char *buf, size_t buf_size);
46extern void *_lc_get_header(void *handle);
47extern void _lc_close(void *handle);
48
49extern void *lc_open(const char *filename, char *buf, size_t buf_size);
50/* not possiible on hosted platforms */
51extern void *lc_open_from_mem(void *addr, size_t blob_size);
52extern void *lc_get_header(void *handle);
53extern void lc_close(void *handle);
54extern 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 */
30void * 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_)
72static 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
89void * _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
97void *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
146void *_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
155void _lc_close(void *handle)
156{
157 if (handle)
158 dlclose(handle);
159}
160
161const 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
533void *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; 535void *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
603void sim_codec_close(void *pd)
604{
605 dlclose(pd);
606} 546}
607 547
608void *sim_plugin_load(char *plugin, void **pd) 548void *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
640void sim_plugin_close(void *pd) 553void lc_close(void *handle)
641{ 554{
642 dlclose(pd); 555 _lc_close(handle);
643} 556}
644 557
645#ifdef WIN32 558#ifdef WIN32