diff options
author | Thomas Martitz <kugel@rockbox.org> | 2010-08-26 23:20:02 +0000 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2010-08-26 23:20:02 +0000 |
commit | 73f057be6fcb849d5379073267e21e9526576ccd (patch) | |
tree | b2b239517ba89f4e9969918642006a3d15faa062 /firmware | |
parent | 55dc25fe7273bf9aa71cdaea9a68c39fa3a22f50 (diff) | |
download | rockbox-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
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/SOURCES | 1 | ||||
-rw-r--r-- | firmware/export/load_code.h | 55 | ||||
-rw-r--r-- | firmware/load_code.c | 165 |
3 files changed, 221 insertions, 0 deletions
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 | ||