@@ -126,16 +126,6 @@ struct dbl_attrs {
dbl_sym_lookup sym_lookup;
void *sym_handle;
void *sym_arg;
-
- /*
- * These file manipulation functions should be compatible with the
- * "C" run time library functions of the same name.
- */
- s32(*fread) (void *, size_t, size_t, void *);
- s32(*fseek) (void *, long, int);
- s32(*ftell) (void *);
- s32(*fclose) (void *);
- void *(*fopen) (const char *, const char *);
};
#endif /* DBLDEFS_ */
@@ -20,9 +20,16 @@
#ifndef DBLL_
#define DBLL_
+#include <linux/firmware.h>
#include <dspbridge/dbdefs.h>
#include <dspbridge/dblldefs.h>
+struct dsp_fw {
+ const struct firmware *img;
+ const char *name;
+ const u8 *pos;
+};
+
extern bool symbols_reloaded;
extern void dbll_close(struct dbll_library_obj *zl_lib);
@@ -79,11 +79,6 @@ typedef s32(*dbll_alloc_fxn) (void *hdl, s32 space, u32 size, u32 align,
bool reserved);
/*
- * ======== dbll_close_fxn ========
- */
-typedef s32(*dbll_f_close_fxn) (void *);
-
-/*
* ======== dbll_free_fxn ========
* Free memory function. Free, or unreserve (if reserved == TRUE) "size"
* bytes of memory from segment "space"
@@ -92,11 +87,6 @@ typedef bool(*dbll_free_fxn) (void *hdl, u32 addr, s32 space, u32 size,
bool reserved);
/*
- * ======== dbll_f_open_fxn ========
- */
-typedef void *(*dbll_f_open_fxn) (const char *, const char *);
-
-/*
* ======== dbll_log_write_fxn ========
* Function to call when writing data from a section, to log the info.
* Can be NULL if no logging is required.
@@ -106,16 +96,6 @@ typedef int(*dbll_log_write_fxn) (void *handle,
u32 bytes);
/*
- * ======== dbll_read_fxn ========
- */
-typedef s32(*dbll_read_fxn) (void *, size_t, size_t, void *);
-
-/*
- * ======== dbll_seek_fxn ========
- */
-typedef s32(*dbll_seek_fxn) (void *, long, int);
-
-/*
* ======== dbll_sym_lookup ========
* Symbol lookup function - Find the symbol name and return its value.
*
@@ -133,11 +113,6 @@ typedef bool(*dbll_sym_lookup) (void *handle, void *parg, void *rmm_handle,
const char *name, struct dbll_sym_val ** sym);
/*
- * ======== dbll_tell_fxn ========
- */
-typedef s32(*dbll_tell_fxn) (void *);
-
-/*
* ======== dbll_write_fxn ========
* Write memory function. Write "n" HOST bytes of memory to segment "mtype"
* starting at address "dsp_address" from the buffer "buf". The buffer is
@@ -163,16 +138,6 @@ struct dbll_attrs {
dbll_sym_lookup sym_lookup;
void *sym_handle;
void *sym_arg;
-
- /*
- * These file manipulation functions should be compatible with the
- * "C" run time library functions of the same name.
- */
- s32(*fread) (void *, size_t, size_t, void *);
- s32(*fseek) (void *, long, int);
- s32(*ftell) (void *);
- s32(*fclose) (void *);
- void *(*fopen) (const char *, const char *);
};
/*
@@ -89,101 +89,6 @@ static struct dbll_fxns ldr_fxns = {
static bool no_op(void);
/*
- * File operations (originally were under kfile.c)
- */
-static s32 cod_f_close(struct file *filp)
-{
- /* Check for valid handle */
- if (!filp)
- return -EFAULT;
-
- filp_close(filp, NULL);
-
- /* we can't use 0 here */
- return 0;
-}
-
-static struct file *cod_f_open(const char *psz_file_name, const char *sz_mode)
-{
- mm_segment_t fs;
- struct file *filp;
-
- fs = get_fs();
- set_fs(get_ds());
-
- /* ignore given mode and open file as read-only */
- filp = filp_open(psz_file_name, O_RDONLY, 0);
-
- if (IS_ERR(filp))
- filp = NULL;
-
- set_fs(fs);
-
- return filp;
-}
-
-static s32 cod_f_read(void __user *pbuffer, s32 size, s32 count,
- struct file *filp)
-{
- /* check for valid file handle */
- if (!filp)
- return -EFAULT;
-
- if ((size > 0) && (count > 0) && pbuffer) {
- u32 dw_bytes_read;
- mm_segment_t fs;
-
- /* read from file */
- fs = get_fs();
- set_fs(get_ds());
- dw_bytes_read = filp->f_op->read(filp, pbuffer, size * count,
- &(filp->f_pos));
- set_fs(fs);
-
- if (!dw_bytes_read)
- return -EBADF;
-
- return dw_bytes_read / size;
- }
-
- return -EINVAL;
-}
-
-static s32 cod_f_seek(struct file *filp, s32 offset, s32 origin)
-{
- loff_t dw_cur_pos;
-
- /* check for valid file handle */
- if (!filp)
- return -EFAULT;
-
- /* based on the origin flag, move the internal pointer */
- dw_cur_pos = filp->f_op->llseek(filp, offset, origin);
-
- if ((s32) dw_cur_pos < 0)
- return -EPERM;
-
- /* we can't use 0 here */
- return 0;
-}
-
-static s32 cod_f_tell(struct file *filp)
-{
- loff_t dw_cur_pos;
-
- if (!filp)
- return -EFAULT;
-
- /* Get current position */
- dw_cur_pos = filp->f_op->llseek(filp, 0, SEEK_CUR);
-
- if ((s32) dw_cur_pos < 0)
- return -EPERM;
-
- return dw_cur_pos;
-}
-
-/*
* ======== cod_close ========
*/
void cod_close(struct cod_libraryobj *lib)
@@ -238,11 +143,6 @@ int cod_create(struct cod_manager **mgr, char *str_zl_file,
zl_attrs.alloc = (dbll_alloc_fxn) no_op;
zl_attrs.free = (dbll_free_fxn) no_op;
- zl_attrs.fread = (dbll_read_fxn) cod_f_read;
- zl_attrs.fseek = (dbll_seek_fxn) cod_f_seek;
- zl_attrs.ftell = (dbll_tell_fxn) cod_f_tell;
- zl_attrs.fclose = (dbll_f_close_fxn) cod_f_close;
- zl_attrs.fopen = (dbll_f_open_fxn) cod_f_open;
zl_attrs.sym_lookup = NULL;
zl_attrs.base_image = true;
zl_attrs.log_write = NULL;
@@ -117,7 +117,7 @@ struct dbll_library_obj {
void *dload_mod_obj;
char *file_name; /* COFF file name */
- void *fp; /* Opaque file handle */
+ struct dsp_fw *fp;
u32 entry; /* Entry point */
void *desc; /* desc of DOFF file loaded */
u32 open_ref; /* Number of times opened */
@@ -136,6 +136,8 @@ struct dbll_symbol {
static void dof_close(struct dbll_library_obj *zl_lib);
static int dof_open(struct dbll_library_obj *zl_lib);
+static u32 dof_get_posn(struct dsp_fw *fw);
+static int dof_set_posn(struct dsp_fw *fw, u32 pos);
static s32 no_op(struct dynamic_loader_initialize *thisptr, void *bufr,
ldr_addr locn, struct ldr_section_info *info,
unsigned bytsize);
@@ -397,9 +399,7 @@ int dbll_get_sect(struct dbll_library_obj *lib, char *name, u32 *paddr,
opened_doff = true;
} else {
- (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp,
- zl_lib->ul_pos,
- SEEK_SET);
+ dof_set_posn(zl_lib->fp, zl_lib->ul_pos);
}
} else {
status = -EFAULT;
@@ -522,12 +522,9 @@ int dbll_load(struct dbll_library_obj *lib, dbll_flags flags,
}
if (!status) {
- zl_lib->ul_pos = (*(zl_lib->target_obj->attrs.ftell))
- (zl_lib->fp);
- /* Reset file cursor */
- (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp,
- (long)0,
- SEEK_SET);
+ zl_lib->ul_pos = dof_get_posn(zl_lib->fp);
+ /* Reset firmware position */
+ dof_set_posn(zl_lib->fp, 0);
symbols_reloaded = true;
/* The 5th argument, DLOAD_INITBSS, tells the DLL
* module to zero-init all BSS sections. In general,
@@ -592,7 +589,6 @@ int dbll_open(struct dbll_tar_obj *target, char *file, dbll_flags flags,
DBC_REQUIRE(refs > 0);
DBC_REQUIRE(zl_target);
- DBC_REQUIRE(zl_target->attrs.fopen != NULL);
DBC_REQUIRE(file != NULL);
DBC_REQUIRE(lib_obj != NULL);
@@ -661,8 +657,8 @@ int dbll_open(struct dbll_tar_obj *target, char *file, dbll_flags flags,
if (!status && zl_lib->fp == NULL)
status = dof_open(zl_lib);
- zl_lib->ul_pos = (*(zl_lib->target_obj->attrs.ftell)) (zl_lib->fp);
- (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp, (long)0, SEEK_SET);
+ zl_lib->ul_pos = dof_get_posn(zl_lib->fp);
+ dof_set_posn(zl_lib->fp, 0);
/* Create a hash table for symbols if flag is set */
if (zl_lib->sym_tab != NULL || !(flags & DBLL_SYMB))
goto func_cont;
@@ -749,9 +745,7 @@ int dbll_read_sect(struct dbll_library_obj *lib, char *name,
opened_doff = true;
} else {
- (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp,
- zl_lib->ul_pos,
- SEEK_SET);
+ dof_set_posn(zl_lib->fp, zl_lib->ul_pos);
}
} else {
status = -EFAULT;
@@ -869,9 +863,10 @@ static void dof_close(struct dbll_library_obj *zl_lib)
dload_module_close(zl_lib->desc);
zl_lib->desc = NULL;
}
- /* close file */
+
if (zl_lib->fp) {
- (zl_lib->target_obj->attrs.fclose) (zl_lib->fp);
+ release_firmware(zl_lib->fp->img);
+ kfree(zl_lib->fp);
zl_lib->fp = NULL;
}
}
@@ -881,30 +876,52 @@ static void dof_close(struct dbll_library_obj *zl_lib)
*/
static int dof_open(struct dbll_library_obj *zl_lib)
{
- void *open = *(zl_lib->target_obj->attrs.fopen);
- int status = 0;
+ int err;
+
+ if (zl_lib->fp || zl_lib->desc)
+ return -EBADF;
+
+ zl_lib->fp = kzalloc(sizeof(struct dsp_fw), GFP_KERNEL);
+ if (!zl_lib->fp)
+ return -ENOMEM;
- /* First open the file for the dynamic loader, then open COF */
- zl_lib->fp =
- (void *)((dbll_f_open_fxn) (open)) (zl_lib->file_name, "rb");
+ err = request_firmware(&zl_lib->fp->img, zl_lib->file_name, bridge);
+ if (IS_ERR_VALUE(err)) {
+ kfree(zl_lib->fp);
+ return err;
+ }
+
+ zl_lib->fp->pos = zl_lib->fp->img->data;
/* Open DOFF module */
- if (zl_lib->fp && zl_lib->desc == NULL) {
- (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp, (long)0,
- SEEK_SET);
- zl_lib->desc =
- dload_module_open(&zl_lib->stream.dl_stream,
- &zl_lib->symbol.dl_symbol);
- if (zl_lib->desc == NULL) {
- (zl_lib->target_obj->attrs.fclose) (zl_lib->fp);
- zl_lib->fp = NULL;
- status = -EBADF;
- }
- } else {
- status = -EBADF;
+ zl_lib->desc = dload_module_open(&zl_lib->stream.dl_stream,
+ &zl_lib->symbol.dl_symbol);
+ if (!zl_lib->desc) {
+ dof_close(zl_lib);
+ return -EBADF;
}
- return status;
+ return 0;
+}
+
+static u32 dof_get_posn(struct dsp_fw *fw)
+{
+ /* check for valid file handle */
+ if (!fw || !fw->img)
+ return -EFAULT;
+
+ return fw->pos - fw->img->data;
+}
+
+static int dof_set_posn(struct dsp_fw *fw, u32 pos)
+{
+ /* check for valid file handle */
+ if (!fw || !fw->img)
+ return -EFAULT;
+
+ fw->pos = fw->img->data + pos;
+
+ return 0;
}
/*
@@ -978,18 +995,21 @@ static int dbll_read_buffer(struct dynamic_loader_stream *this, void *buffer,
{
struct dbll_stream *pstream = (struct dbll_stream *)this;
struct dbll_library_obj *lib;
- int bytes_read = 0;
DBC_REQUIRE(this != NULL);
lib = pstream->lib;
DBC_REQUIRE(lib);
- if (lib != NULL) {
- bytes_read =
- (*(lib->target_obj->attrs.fread)) (buffer, 1, bufsize,
- lib->fp);
- }
- return bytes_read;
+ if (!lib || !lib->fp)
+ return -EFAULT;
+
+ if (!buffer || bufsize <= 0)
+ return -EINVAL;
+
+ memcpy(buffer, lib->fp->pos, bufsize);
+ lib->fp->pos += bufsize;
+
+ return bufsize;
}
/*
@@ -1006,10 +1026,8 @@ static int dbll_set_file_posn(struct dynamic_loader_stream *this,
lib = pstream->lib;
DBC_REQUIRE(lib);
- if (lib != NULL) {
- status = (*(lib->target_obj->attrs.fseek)) (lib->fp, (long)pos,
- SEEK_SET);
- }
+ if (lib)
+ status = dof_set_posn(lib->fp, pos);
return status;
}