forked from len0rd/rockbox
Extend lc_open() to also being able to load overlay plugins.
For this it needs to look at the plugin header. Since lc_open() doesn't know it's a plugin, the header needs to be changed slightly to include the new lc_header (which needs to be the first element in plugin_header so it can be casted savely). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28054 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
cec7c99613
commit
0d4585b28f
10 changed files with 167 additions and 105 deletions
|
@ -181,7 +181,8 @@ void codec_get_full_path(char *path, const char *codec_root_fn)
|
||||||
|
|
||||||
static int codec_load_ram(void *handle, struct codec_api *api)
|
static int codec_load_ram(void *handle, struct codec_api *api)
|
||||||
{
|
{
|
||||||
struct codec_header *hdr = lc_get_header(handle);
|
struct codec_header *c_hdr = lc_get_header(handle);
|
||||||
|
struct lc_header *hdr = c_hdr ? &c_hdr->lc_hdr : NULL;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
if (hdr == NULL
|
if (hdr == NULL
|
||||||
|
@ -215,8 +216,8 @@ static int codec_load_ram(void *handle, struct codec_api *api)
|
||||||
codec_size = 0;
|
codec_size = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
*(hdr->api) = api;
|
*(c_hdr->api) = api;
|
||||||
status = hdr->entry_point();
|
status = c_hdr->entry_point();
|
||||||
|
|
||||||
lc_close(handle);
|
lc_close(handle);
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
#include "gcc_extensions.h"
|
#include "gcc_extensions.h"
|
||||||
|
#include "load_code.h"
|
||||||
|
|
||||||
#ifdef CODEC
|
#ifdef CODEC
|
||||||
#if defined(DEBUG) || defined(SIMULATOR)
|
#if defined(DEBUG) || defined(SIMULATOR)
|
||||||
|
@ -240,11 +241,7 @@ struct codec_api {
|
||||||
|
|
||||||
/* codec header */
|
/* codec header */
|
||||||
struct codec_header {
|
struct codec_header {
|
||||||
unsigned long magic; /* RCOD or RENC */
|
struct lc_header lc_hdr; /* must be first */
|
||||||
unsigned short target_id;
|
|
||||||
unsigned short api_version;
|
|
||||||
unsigned char *load_addr;
|
|
||||||
unsigned char *end_addr;
|
|
||||||
enum codec_status(*entry_point)(void);
|
enum codec_status(*entry_point)(void);
|
||||||
struct codec_api **api;
|
struct codec_api **api;
|
||||||
};
|
};
|
||||||
|
@ -261,27 +258,27 @@ extern unsigned char plugin_end_addr[];
|
||||||
#define CODEC_HEADER \
|
#define CODEC_HEADER \
|
||||||
const struct codec_header __header \
|
const struct codec_header __header \
|
||||||
__attribute__ ((section (".header")))= { \
|
__attribute__ ((section (".header")))= { \
|
||||||
CODEC_MAGIC, TARGET_ID, CODEC_API_VERSION, \
|
{ CODEC_MAGIC, TARGET_ID, CODEC_API_VERSION, \
|
||||||
plugin_start_addr, plugin_end_addr, codec_start, &ci };
|
plugin_start_addr, plugin_end_addr }, codec_start, &ci };
|
||||||
/* encoders */
|
/* encoders */
|
||||||
#define CODEC_ENC_HEADER \
|
#define CODEC_ENC_HEADER \
|
||||||
const struct codec_header __header \
|
const struct codec_header __header \
|
||||||
__attribute__ ((section (".header")))= { \
|
__attribute__ ((section (".header")))= { \
|
||||||
CODEC_ENC_MAGIC, TARGET_ID, CODEC_API_VERSION, \
|
{ CODEC_ENC_MAGIC, TARGET_ID, CODEC_API_VERSION, \
|
||||||
plugin_start_addr, plugin_end_addr, codec_start, &ci };
|
plugin_start_addr, plugin_end_addr }, codec_start, &ci };
|
||||||
|
|
||||||
#else /* def SIMULATOR */
|
#else /* def SIMULATOR */
|
||||||
/* decoders */
|
/* decoders */
|
||||||
#define CODEC_HEADER \
|
#define CODEC_HEADER \
|
||||||
const struct codec_header __header \
|
const struct codec_header __header \
|
||||||
__attribute__((visibility("default"))) = { \
|
__attribute__((visibility("default"))) = { \
|
||||||
CODEC_MAGIC, TARGET_ID, CODEC_API_VERSION, \
|
{ CODEC_MAGIC, TARGET_ID, CODEC_API_VERSION, NULL, NULL }, \
|
||||||
NULL, NULL, codec_start, &ci };
|
codec_start, &ci };
|
||||||
/* encoders */
|
/* encoders */
|
||||||
#define CODEC_ENC_HEADER \
|
#define CODEC_ENC_HEADER \
|
||||||
const struct codec_header __header = { \
|
const struct codec_header __header = { \
|
||||||
CODEC_ENC_MAGIC, TARGET_ID, CODEC_API_VERSION, \
|
{ CODEC_ENC_MAGIC, TARGET_ID, CODEC_API_VERSION, NULL, NULL }, \
|
||||||
NULL, NULL, codec_start, &ci };
|
codec_start, &ci };
|
||||||
#endif /* SIMULATOR */
|
#endif /* SIMULATOR */
|
||||||
#endif /* CODEC */
|
#endif /* CODEC */
|
||||||
|
|
||||||
|
|
|
@ -20,15 +20,10 @@
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "codeclib.h"
|
#include "codecs.h"
|
||||||
|
|
||||||
struct codec_api *ci DATA_ATTR;
|
struct codec_api *ci DATA_ATTR;
|
||||||
|
|
||||||
extern unsigned char iramcopy[];
|
|
||||||
extern unsigned char iramstart[];
|
|
||||||
extern unsigned char iramend[];
|
|
||||||
extern unsigned char iedata[];
|
|
||||||
extern unsigned char iend[];
|
|
||||||
extern unsigned char plugin_bss_start[];
|
extern unsigned char plugin_bss_start[];
|
||||||
extern unsigned char plugin_end_addr[];
|
extern unsigned char plugin_end_addr[];
|
||||||
|
|
||||||
|
@ -42,14 +37,23 @@ enum codec_status codec_start(void)
|
||||||
{
|
{
|
||||||
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
|
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
|
||||||
#ifdef USE_IRAM
|
#ifdef USE_IRAM
|
||||||
ci->memcpy(iramstart, iramcopy, iramend - iramstart);
|
extern char iramcopy[], iramstart[], iramend[], iedata[], iend[];
|
||||||
ci->memset(iedata, 0, iend - iedata);
|
size_t iram_size = iramend - iramstart;
|
||||||
#endif
|
size_t ibss_size = iend - iedata;
|
||||||
|
if (iram_size > 0 || ibss_size > 0)
|
||||||
|
{
|
||||||
|
ci->memcpy(iramstart, iramcopy, iram_size);
|
||||||
|
ci->memset(iedata, 0, ibss_size);
|
||||||
|
/* make the icache (if it exists) up to date with the new code */
|
||||||
|
ci->cpucache_invalidate();
|
||||||
|
/* barrier to prevent reordering iram copy and BSS clearing,
|
||||||
|
* because the BSS segment alias the IRAM copy.
|
||||||
|
*/
|
||||||
|
asm volatile ("" ::: "memory");
|
||||||
|
}
|
||||||
|
#endif /* PLUGIN_USE_IRAM */
|
||||||
ci->memset(plugin_bss_start, 0, plugin_end_addr - plugin_bss_start);
|
ci->memset(plugin_bss_start, 0, plugin_end_addr - plugin_bss_start);
|
||||||
#endif
|
#endif
|
||||||
/* writeback cleared iedata and bss areas, invalidate icache for
|
|
||||||
* copied code */
|
|
||||||
ci->cpucache_invalidate();
|
|
||||||
|
|
||||||
return codec_main();
|
return codec_main();
|
||||||
}
|
}
|
||||||
|
|
|
@ -723,12 +723,18 @@ static const struct plugin_api rockbox_api = {
|
||||||
/* new stuff at the end, sort into place next time
|
/* new stuff at the end, sort into place next time
|
||||||
the API gets incompatible */
|
the API gets incompatible */
|
||||||
dir_get_info,
|
dir_get_info,
|
||||||
|
|
||||||
|
lc_open,
|
||||||
|
lc_open_from_mem,
|
||||||
|
lc_get_header,
|
||||||
|
lc_close,
|
||||||
};
|
};
|
||||||
|
|
||||||
int plugin_load(const char* plugin, const void* parameter)
|
int plugin_load(const char* plugin, const void* parameter)
|
||||||
{
|
{
|
||||||
int rc, i;
|
int rc, i;
|
||||||
struct plugin_header *hdr;
|
struct plugin_header *p_hdr;
|
||||||
|
struct lc_header *hdr;
|
||||||
|
|
||||||
#if LCD_DEPTH > 1
|
#if LCD_DEPTH > 1
|
||||||
fb_data* old_backdrop;
|
fb_data* old_backdrop;
|
||||||
|
@ -754,7 +760,10 @@ int plugin_load(const char* plugin, const void* parameter)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
hdr = lc_get_header(current_plugin_handle);
|
p_hdr = lc_get_header(current_plugin_handle);
|
||||||
|
|
||||||
|
hdr = p_hdr ? &p_hdr->lc_hdr : NULL;
|
||||||
|
|
||||||
|
|
||||||
if (hdr == NULL
|
if (hdr == NULL
|
||||||
|| hdr->magic != PLUGIN_MAGIC
|
|| hdr->magic != PLUGIN_MAGIC
|
||||||
|
@ -782,7 +791,7 @@ int plugin_load(const char* plugin, const void* parameter)
|
||||||
plugin_size = 0;
|
plugin_size = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
*(hdr->api) = &rockbox_api;
|
*(p_hdr->api) = &rockbox_api;
|
||||||
|
|
||||||
#if defined HAVE_LCD_BITMAP && LCD_DEPTH > 1
|
#if defined HAVE_LCD_BITMAP && LCD_DEPTH > 1
|
||||||
old_backdrop = lcd_get_backdrop();
|
old_backdrop = lcd_get_backdrop();
|
||||||
|
@ -806,7 +815,7 @@ int plugin_load(const char* plugin, const void* parameter)
|
||||||
open_files = 0;
|
open_files = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rc = hdr->entry_point(parameter);
|
rc = p_hdr->entry_point(parameter);
|
||||||
|
|
||||||
if (!pfn_tsr_exit)
|
if (!pfn_tsr_exit)
|
||||||
{ /* close handle if plugin is no tsr one */
|
{ /* close handle if plugin is no tsr one */
|
||||||
|
|
|
@ -53,6 +53,7 @@ void* plugin_get_buffer(size_t *buffer_size);
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "button.h"
|
#include "button.h"
|
||||||
#include "action.h"
|
#include "action.h"
|
||||||
|
#include "load_code.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
#include "lcd.h"
|
#include "lcd.h"
|
||||||
|
@ -895,15 +896,17 @@ struct plugin_api {
|
||||||
/* new stuff at the end, sort into place next time
|
/* new stuff at the end, sort into place next time
|
||||||
the API gets incompatible */
|
the API gets incompatible */
|
||||||
struct dirinfo (*dir_get_info)(DIR* parent, struct dirent *entry);
|
struct dirinfo (*dir_get_info)(DIR* parent, struct dirent *entry);
|
||||||
|
|
||||||
|
/* load code api for overlay */
|
||||||
|
void* (*lc_open)(const char *filename, unsigned char *buf, size_t buf_size);
|
||||||
|
void* (*lc_open_from_mem)(void* addr, size_t blob_size);
|
||||||
|
void* (*lc_get_header)(void *handle);
|
||||||
|
void (*lc_close)(void *handle);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* plugin header */
|
/* plugin header */
|
||||||
struct plugin_header {
|
struct plugin_header {
|
||||||
unsigned long magic;
|
struct lc_header lc_hdr; /* must be the first */
|
||||||
unsigned short target_id;
|
|
||||||
unsigned short api_version;
|
|
||||||
unsigned char *load_addr;
|
|
||||||
unsigned char *end_addr;
|
|
||||||
enum plugin_status(*entry_point)(const void*);
|
enum plugin_status(*entry_point)(const void*);
|
||||||
const struct plugin_api **api;
|
const struct plugin_api **api;
|
||||||
};
|
};
|
||||||
|
@ -916,15 +919,15 @@ extern unsigned char plugin_end_addr[];
|
||||||
const struct plugin_api *rb DATA_ATTR; \
|
const struct plugin_api *rb DATA_ATTR; \
|
||||||
const struct plugin_header __header \
|
const struct plugin_header __header \
|
||||||
__attribute__ ((section (".header")))= { \
|
__attribute__ ((section (".header")))= { \
|
||||||
PLUGIN_MAGIC, TARGET_ID, PLUGIN_API_VERSION, \
|
{ PLUGIN_MAGIC, TARGET_ID, PLUGIN_API_VERSION, \
|
||||||
plugin_start_addr, plugin_end_addr, plugin__start, &rb };
|
plugin_start_addr, plugin_end_addr }, plugin__start, &rb };
|
||||||
#else /* PLATFORM_HOSTED */
|
#else /* PLATFORM_HOSTED */
|
||||||
#define PLUGIN_HEADER \
|
#define PLUGIN_HEADER \
|
||||||
const struct plugin_api *rb DATA_ATTR; \
|
const struct plugin_api *rb DATA_ATTR; \
|
||||||
const struct plugin_header __header \
|
const struct plugin_header __header \
|
||||||
__attribute__((visibility("default"))) = { \
|
__attribute__((visibility("default"))) = { \
|
||||||
PLUGIN_MAGIC, TARGET_ID, PLUGIN_API_VERSION, \
|
{ PLUGIN_MAGIC, TARGET_ID, PLUGIN_API_VERSION, NULL, NULL },
|
||||||
NULL, NULL, plugin__start, &rb };
|
plugin__start, &rb };
|
||||||
#endif /* CONFIG_PLATFORM */
|
#endif /* CONFIG_PLATFORM */
|
||||||
#endif /* PLUGIN */
|
#endif /* PLUGIN */
|
||||||
|
|
||||||
|
|
|
@ -47,64 +47,56 @@
|
||||||
enum plugin_status run_overlay(const void* parameter,
|
enum plugin_status run_overlay(const void* parameter,
|
||||||
unsigned char *filename, unsigned char *name)
|
unsigned char *filename, unsigned char *name)
|
||||||
{
|
{
|
||||||
int fd, readsize;
|
|
||||||
size_t audiobuf_size;
|
size_t audiobuf_size;
|
||||||
unsigned char *audiobuf;
|
unsigned char *audiobuf;
|
||||||
static struct plugin_header header;
|
void *handle;
|
||||||
|
struct plugin_header *p_hdr;
|
||||||
fd = rb->open(filename, O_RDONLY);
|
struct lc_header *hdr;
|
||||||
if (fd < 0)
|
|
||||||
{
|
|
||||||
rb->splashf(2*HZ, "Can't open %s", filename);
|
|
||||||
return PLUGIN_ERROR;
|
|
||||||
}
|
|
||||||
readsize = rb->read(fd, &header, sizeof(header));
|
|
||||||
rb->close(fd);
|
|
||||||
/* Close for now. Less code than doing it in all error checks.
|
|
||||||
* Would need to seek back anyway. */
|
|
||||||
|
|
||||||
if (readsize != sizeof(header))
|
|
||||||
{
|
|
||||||
rb->splashf(2*HZ, "Reading %s overlay failed.", name);
|
|
||||||
return PLUGIN_ERROR;
|
|
||||||
}
|
|
||||||
if (header.magic != PLUGIN_MAGIC || header.target_id != TARGET_ID)
|
|
||||||
{
|
|
||||||
rb->splashf(2*HZ, "%s overlay: Incompatible model.", name);
|
|
||||||
return PLUGIN_ERROR;
|
|
||||||
}
|
|
||||||
if (header.api_version != PLUGIN_API_VERSION)
|
|
||||||
{
|
|
||||||
rb->splashf(2*HZ, "%s overlay: Incompatible version.", name);
|
|
||||||
return PLUGIN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
audiobuf = rb->plugin_get_audio_buffer(&audiobuf_size);
|
audiobuf = rb->plugin_get_audio_buffer(&audiobuf_size);
|
||||||
if (header.load_addr < audiobuf ||
|
if (!audiobuf)
|
||||||
header.end_addr > audiobuf + audiobuf_size)
|
|
||||||
{
|
{
|
||||||
rb->splashf(2*HZ, "%s overlay doesn't fit into memory.", name);
|
rb->splash(2*HZ, "Can't optain memory");
|
||||||
return PLUGIN_ERROR;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = rb->open(filename, O_RDONLY);
|
handle = rb->lc_open(filename, audiobuf, audiobuf_size);
|
||||||
if (fd < 0)
|
if (!handle)
|
||||||
{
|
{
|
||||||
rb->splashf(2*HZ, "Can't open %s", filename);
|
rb->splashf(2*HZ, "Can't open %s", filename);
|
||||||
return PLUGIN_ERROR;
|
goto error;
|
||||||
}
|
}
|
||||||
readsize = rb->read(fd, header.load_addr, header.end_addr - header.load_addr);
|
|
||||||
rb->close(fd);
|
|
||||||
|
|
||||||
if (readsize < 0)
|
p_hdr = rb->lc_get_header(handle);
|
||||||
|
if (!p_hdr)
|
||||||
{
|
{
|
||||||
rb->splashf(2*HZ, "Reading %s overlay failed.", name);
|
rb->splash(2*HZ, "Can't get header");
|
||||||
return PLUGIN_ERROR;
|
goto error_close;
|
||||||
}
|
}
|
||||||
/* Zero out bss area */
|
else
|
||||||
rb->memset(header.load_addr + readsize, 0,
|
hdr = &p_hdr->lc_hdr;
|
||||||
header.end_addr - (header.load_addr + readsize));
|
|
||||||
|
|
||||||
*(header.api) = rb;
|
if (hdr->magic != PLUGIN_MAGIC || hdr->target_id != TARGET_ID)
|
||||||
return header.entry_point(parameter);
|
{
|
||||||
|
rb->splashf(2*HZ, "%s overlay: Incompatible model.", name);
|
||||||
|
goto error_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (hdr->api_version > PLUGIN_API_VERSION
|
||||||
|
|| hdr->api_version < PLUGIN_MIN_API_VERSION)
|
||||||
|
{
|
||||||
|
rb->splashf(2*HZ, "%s overlay: Incompatible version.", name);
|
||||||
|
goto error_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
rb->lc_close(handle);
|
||||||
|
|
||||||
|
*(p_hdr->api) = rb;
|
||||||
|
return p_hdr->entry_point(parameter);
|
||||||
|
|
||||||
|
error_close:
|
||||||
|
rb->lc_close(handle);
|
||||||
|
error:
|
||||||
|
return PLUGIN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,17 +20,21 @@
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __LOAD_CODE_H__
|
||||||
|
#define __LOAD_CODE_H__
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
|
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
|
||||||
extern void *lc_open(const char *filename, char *buf, size_t buf_size);
|
extern void *lc_open(const char *filename, unsigned char *buf, size_t buf_size);
|
||||||
/* header is always at the beginning of the blob, and handle actually points
|
/* header is always at the beginning of the blob, and handle actually points
|
||||||
* to the start of the blob */
|
* to the start of the blob (the header is there) */
|
||||||
static inline void *lc_open_from_mem(void* addr, size_t blob_size)
|
static inline void *lc_open_from_mem(void* addr, size_t blob_size)
|
||||||
{
|
{
|
||||||
(void)blob_size;
|
(void)blob_size;
|
||||||
|
/* commit dcache and discard icache */
|
||||||
cpucache_invalidate();
|
cpucache_invalidate();
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
@ -48,14 +52,27 @@ static inline void lc_close(void *handle) { (void)handle; }
|
||||||
#else
|
#else
|
||||||
#define _lc_open_char char
|
#define _lc_open_char char
|
||||||
#endif
|
#endif
|
||||||
extern void *_lc_open(const _lc_open_char *filename, char *buf, size_t buf_size);
|
extern void *_lc_open(const _lc_open_char *filename, unsigned char *buf, size_t buf_size);
|
||||||
extern void *_lc_get_header(void *handle);
|
extern void *_lc_get_header(void *handle);
|
||||||
extern void _lc_close(void *handle);
|
extern void _lc_close(void *handle);
|
||||||
|
|
||||||
extern void *lc_open(const char *filename, char *buf, size_t buf_size);
|
extern void *lc_open(const char *filename, unsigned char *buf, size_t buf_size);
|
||||||
/* not possiible on hosted platforms */
|
|
||||||
extern void *lc_open_from_mem(void *addr, size_t blob_size);
|
extern void *lc_open_from_mem(void *addr, size_t blob_size);
|
||||||
extern void *lc_get_header(void *handle);
|
extern void *lc_get_header(void *handle);
|
||||||
extern void lc_close(void *handle);
|
extern void lc_close(void *handle);
|
||||||
extern const char* lc_last_error(void);
|
extern const char* lc_last_error(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* this struct needs to be the first part of other headers
|
||||||
|
* (lc_open() casts the other header to this one to load to the correct
|
||||||
|
* address)
|
||||||
|
*/
|
||||||
|
struct lc_header {
|
||||||
|
unsigned long magic;
|
||||||
|
unsigned short target_id;
|
||||||
|
unsigned short api_version;
|
||||||
|
unsigned char *load_addr;
|
||||||
|
unsigned char *end_addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __LOAD_CODE_H__ */
|
||||||
|
|
|
@ -26,37 +26,77 @@
|
||||||
#include "load_code.h"
|
#include "load_code.h"
|
||||||
|
|
||||||
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
|
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
|
||||||
|
|
||||||
/* load binary blob from disk to memory, returning a handle */
|
/* load binary blob from disk to memory, returning a handle */
|
||||||
void * lc_open(const char *filename, char *buf, size_t buf_size)
|
void * lc_open(const char *filename, unsigned char *buf, size_t buf_size)
|
||||||
{
|
{
|
||||||
int fd = open(filename, O_RDONLY);
|
int fd = open(filename, O_RDONLY);
|
||||||
ssize_t read_size;
|
ssize_t read_size;
|
||||||
|
struct lc_header hdr;
|
||||||
|
unsigned char *buf_end = buf+buf_size;
|
||||||
|
off_t copy_size;
|
||||||
|
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
DEBUGF("Could not open file");
|
DEBUGF("Could not open file");
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NUM_CORES > 1
|
#if NUM_CORES > 1
|
||||||
/* Make sure COP cache is flushed and invalidated before loading */
|
/* Make sure COP cache is flushed and invalidated before loading */
|
||||||
{
|
{
|
||||||
int my_core = switch_core(CURRENT_CORE ^ 1);
|
int my_core = switch_core(CURRENT_CORE ^ 1);
|
||||||
cpucache_invalidate();
|
cpucache_commit_discard();
|
||||||
switch_core(my_core);
|
switch_core(my_core);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
read_size = read(fd, buf, buf_size);
|
/* read the header to obtain the load address */
|
||||||
close(fd);
|
read_size = read(fd, &hdr, sizeof(hdr));
|
||||||
cpucache_invalidate();
|
|
||||||
|
|
||||||
if (read_size < 0)
|
if (read_size < 0)
|
||||||
{
|
{
|
||||||
DEBUGF("Could not read from file");
|
DEBUGF("Could not read from file");
|
||||||
return NULL;
|
goto error_fd;
|
||||||
}
|
}
|
||||||
return buf;
|
|
||||||
|
/* hdr.end_addr points to the end of the bss section,
|
||||||
|
* but there might be idata/icode behind that so the bytes to copy
|
||||||
|
* can be larger */
|
||||||
|
copy_size = MAX(filesize(fd), hdr.end_addr - hdr.load_addr);
|
||||||
|
|
||||||
|
if (hdr.load_addr < buf || (hdr.load_addr+copy_size) > buf_end)
|
||||||
|
{
|
||||||
|
DEBUGF("Binary doesn't fit into memory");
|
||||||
|
goto error_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* go back to beginning to load the whole thing (incl. header) */
|
||||||
|
if (lseek(fd, 0, SEEK_SET) < 0)
|
||||||
|
{
|
||||||
|
DEBUGF("lseek failed");
|
||||||
|
goto error_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the header has the addresses where the code is linked at */
|
||||||
|
read_size = read(fd, hdr.load_addr, copy_size);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
if (read_size < 0)
|
||||||
|
{
|
||||||
|
DEBUGF("Could not read from file");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* commit dcache and discard icache */
|
||||||
|
cpucache_commit_discard();
|
||||||
|
/* return a pointer the header, reused by lc_get_header() */
|
||||||
|
return hdr.load_addr;
|
||||||
|
|
||||||
|
error_fd:
|
||||||
|
close(fd);
|
||||||
|
error:
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif (CONFIG_PLATFORM & PLATFORM_HOSTED)
|
#elif (CONFIG_PLATFORM & PLATFORM_HOSTED)
|
||||||
|
@ -85,12 +125,11 @@ static inline char *_dlerror(void)
|
||||||
#include "rbpaths.h"
|
#include "rbpaths.h"
|
||||||
#include "general.h"
|
#include "general.h"
|
||||||
|
|
||||||
void * _lc_open(const _lc_open_char *filename, char *buf, size_t buf_size)
|
void * _lc_open(const _lc_open_char *filename, unsigned char *buf, size_t buf_size)
|
||||||
{
|
{
|
||||||
(void)buf;
|
(void)buf;
|
||||||
(void)buf_size;
|
(void)buf_size;
|
||||||
void* dl_handle = dlopen(filename, RTLD_NOW);
|
return dlopen(filename, RTLD_NOW);
|
||||||
return dl_handle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *lc_open_from_mem(void *addr, size_t blob_size)
|
void *lc_open_from_mem(void *addr, size_t blob_size)
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#include "load_code.h"
|
#include "load_code.h"
|
||||||
|
|
||||||
/* the load_code wrappers simply wrap, nothing to do */
|
/* the load_code wrappers simply wrap, nothing to do */
|
||||||
void *lc_open(const char *filename, char *buf, size_t buf_size)
|
void *lc_open(const char *filename, unsigned char *buf, size_t buf_size)
|
||||||
{
|
{
|
||||||
return _lc_open(filename, buf, buf_size);
|
return _lc_open(filename, buf, buf_size);
|
||||||
}
|
}
|
||||||
|
|
|
@ -526,7 +526,7 @@ int sim_fsync(int fd)
|
||||||
|
|
||||||
#ifndef __PCTOOL__
|
#ifndef __PCTOOL__
|
||||||
|
|
||||||
void *lc_open(const char *filename, char *buf, size_t buf_size)
|
void *lc_open(const char *filename, unsigned char *buf, size_t buf_size)
|
||||||
{
|
{
|
||||||
const char *sim_path = get_sim_pathname(filename);
|
const char *sim_path = get_sim_pathname(filename);
|
||||||
void *handle = _lc_open(UTF8_TO_OS(sim_path), buf, buf_size);
|
void *handle = _lc_open(UTF8_TO_OS(sim_path), buf, buf_size);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue