4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
6 * This module implements DSP code management for the DSP/BIOS Bridge
7 * environment. It is mostly a thin wrapper.
9 * This module provides an interface for loading both static and
10 * dynamic code objects onto DSP systems.
12 * Copyright (C) 2005-2006 Texas Instruments, Inc.
14 * This package is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
18 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23 #include <linux/types.h>
25 /* ----------------------------------- Host OS */
26 #include <dspbridge/host_os.h>
28 #include <linux/uaccess.h>
30 /* ----------------------------------- DSP/BIOS Bridge */
31 #include <dspbridge/dbdefs.h>
33 /* ----------------------------------- Trace & Debug */
34 #include <dspbridge/dbc.h>
36 /* ----------------------------------- OS Adaptation Layer */
37 #include <dspbridge/ldr.h>
39 /* ----------------------------------- Platform Manager */
40 /* Include appropriate loader header file */
41 #include <dspbridge/dbll.h>
43 /* ----------------------------------- This */
44 #include <dspbridge/cod.h>
46 /* magic number for handle validation */
47 #define MAGIC 0xc001beef
49 /* macro to validate COD manager handles */
50 #define IS_VALID(h) ((h) != NULL && (h)->ul_magic == MAGIC)
53 * ======== cod_manager ========
56 struct dbll_tar_obj
*target
;
57 struct dbll_library_obj
*base_lib
;
58 bool loaded
; /* Base library loaded? */
60 struct ldr_module
*dll_obj
;
61 struct dbll_fxns fxns
;
62 struct dbll_attrs attrs
;
63 char sz_zl_file
[COD_MAXPATHLENGTH
];
68 * ======== cod_libraryobj ========
70 struct cod_libraryobj
{
71 struct dbll_library_obj
*dbll_lib
;
72 struct cod_manager
*cod_mgr
;
77 static struct dbll_fxns ldr_fxns
= {
78 (dbll_close_fxn
) dbll_close
,
79 (dbll_create_fxn
) dbll_create
,
80 (dbll_delete_fxn
) dbll_delete
,
81 (dbll_exit_fxn
) dbll_exit
,
82 (dbll_get_attrs_fxn
) dbll_get_attrs
,
83 (dbll_get_addr_fxn
) dbll_get_addr
,
84 (dbll_get_c_addr_fxn
) dbll_get_c_addr
,
85 (dbll_get_sect_fxn
) dbll_get_sect
,
86 (dbll_init_fxn
) dbll_init
,
87 (dbll_load_fxn
) dbll_load
,
88 (dbll_load_sect_fxn
) dbll_load_sect
,
89 (dbll_open_fxn
) dbll_open
,
90 (dbll_read_sect_fxn
) dbll_read_sect
,
91 (dbll_set_attrs_fxn
) dbll_set_attrs
,
92 (dbll_unload_fxn
) dbll_unload
,
93 (dbll_unload_sect_fxn
) dbll_unload_sect
,
96 static bool no_op(void);
99 * File operations (originally were under kfile.c)
101 static s32
cod_f_close(struct file
*filp
)
103 /* Check for valid handle */
107 filp_close(filp
, NULL
);
109 /* we can't use 0 here */
113 static struct file
*cod_f_open(const char *psz_file_name
, const char *sz_mode
)
121 /* ignore given mode and open file as read-only */
122 filp
= filp_open(psz_file_name
, O_RDONLY
, 0);
132 static s32
cod_f_read(void __user
*pbuffer
, s32 size
, s32 count
,
135 /* check for valid file handle */
139 if ((size
> 0) && (count
> 0) && pbuffer
) {
146 dw_bytes_read
= filp
->f_op
->read(filp
, pbuffer
, size
* count
,
153 return dw_bytes_read
/ size
;
159 static s32
cod_f_seek(struct file
*filp
, s32 offset
, s32 origin
)
163 /* check for valid file handle */
167 /* based on the origin flag, move the internal pointer */
168 dw_cur_pos
= filp
->f_op
->llseek(filp
, offset
, origin
);
170 if ((s32
) dw_cur_pos
< 0)
173 /* we can't use 0 here */
177 static s32
cod_f_tell(struct file
*filp
)
184 /* Get current position */
185 dw_cur_pos
= filp
->f_op
->llseek(filp
, 0, SEEK_CUR
);
187 if ((s32
) dw_cur_pos
< 0)
194 * ======== cod_close ========
196 void cod_close(struct cod_libraryobj
*lib
)
198 struct cod_manager
*hmgr
;
200 DBC_REQUIRE(refs
> 0);
201 DBC_REQUIRE(lib
!= NULL
);
202 DBC_REQUIRE(IS_VALID(((struct cod_libraryobj
*)lib
)->cod_mgr
));
205 hmgr
->fxns
.close_fxn(lib
->dbll_lib
);
211 * ======== cod_create ========
213 * Create an object to manage code on a DSP system.
214 * This object can be used to load an initial program image with
215 * arguments that can later be expanded with
216 * dynamically loaded object files.
219 int cod_create(OUT
struct cod_manager
**mgr
, char *str_zl_file
,
220 const struct cod_attrs
*attrs
)
222 struct cod_manager
*mgr_new
;
223 struct dbll_attrs zl_attrs
;
226 DBC_REQUIRE(refs
> 0);
227 DBC_REQUIRE(mgr
!= NULL
);
232 /* we don't support non-default attrs yet */
236 mgr_new
= kzalloc(sizeof(struct cod_manager
), GFP_KERNEL
);
240 mgr_new
->ul_magic
= MAGIC
;
242 /* Set up loader functions */
243 mgr_new
->fxns
= ldr_fxns
;
245 /* initialize the ZL module */
246 mgr_new
->fxns
.init_fxn();
248 zl_attrs
.alloc
= (dbll_alloc_fxn
) no_op
;
249 zl_attrs
.free
= (dbll_free_fxn
) no_op
;
250 zl_attrs
.fread
= (dbll_read_fxn
) cod_f_read
;
251 zl_attrs
.fseek
= (dbll_seek_fxn
) cod_f_seek
;
252 zl_attrs
.ftell
= (dbll_tell_fxn
) cod_f_tell
;
253 zl_attrs
.fclose
= (dbll_f_close_fxn
) cod_f_close
;
254 zl_attrs
.fopen
= (dbll_f_open_fxn
) cod_f_open
;
255 zl_attrs
.sym_lookup
= NULL
;
256 zl_attrs
.base_image
= true;
257 zl_attrs
.log_write
= NULL
;
258 zl_attrs
.log_write_handle
= NULL
;
259 zl_attrs
.write
= NULL
;
260 zl_attrs
.rmm_handle
= NULL
;
261 zl_attrs
.input_params
= NULL
;
262 zl_attrs
.sym_handle
= NULL
;
263 zl_attrs
.sym_arg
= NULL
;
265 mgr_new
->attrs
= zl_attrs
;
267 status
= mgr_new
->fxns
.create_fxn(&mgr_new
->target
, &zl_attrs
);
269 if (DSP_FAILED(status
)) {
274 /* return the new manager */
281 * ======== cod_delete ========
283 * Delete a code manager object.
285 void cod_delete(struct cod_manager
*cod_mgr_obj
)
287 DBC_REQUIRE(refs
> 0);
288 DBC_REQUIRE(IS_VALID(cod_mgr_obj
));
290 if (cod_mgr_obj
->base_lib
) {
291 if (cod_mgr_obj
->loaded
)
292 cod_mgr_obj
->fxns
.unload_fxn(cod_mgr_obj
->base_lib
,
293 &cod_mgr_obj
->attrs
);
295 cod_mgr_obj
->fxns
.close_fxn(cod_mgr_obj
->base_lib
);
297 if (cod_mgr_obj
->target
) {
298 cod_mgr_obj
->fxns
.delete_fxn(cod_mgr_obj
->target
);
299 cod_mgr_obj
->fxns
.exit_fxn();
301 cod_mgr_obj
->ul_magic
= ~MAGIC
;
306 * ======== cod_exit ========
308 * Discontinue usage of the COD module.
313 DBC_REQUIRE(refs
> 0);
317 DBC_ENSURE(refs
>= 0);
321 * ======== cod_get_base_lib ========
323 * Get handle to the base image DBL library.
325 int cod_get_base_lib(struct cod_manager
*cod_mgr_obj
,
326 struct dbll_library_obj
**plib
)
330 DBC_REQUIRE(refs
> 0);
331 DBC_REQUIRE(IS_VALID(cod_mgr_obj
));
332 DBC_REQUIRE(plib
!= NULL
);
334 *plib
= (struct dbll_library_obj
*)cod_mgr_obj
->base_lib
;
340 * ======== cod_get_base_name ========
342 int cod_get_base_name(struct cod_manager
*cod_mgr_obj
, char *sz_name
,
347 DBC_REQUIRE(refs
> 0);
348 DBC_REQUIRE(IS_VALID(cod_mgr_obj
));
349 DBC_REQUIRE(sz_name
!= NULL
);
351 if (usize
<= COD_MAXPATHLENGTH
)
352 strncpy(sz_name
, cod_mgr_obj
->sz_zl_file
, usize
);
360 * ======== cod_get_entry ========
362 * Retrieve the entry point of a loaded DSP program image
365 int cod_get_entry(struct cod_manager
*cod_mgr_obj
, u32
*entry_pt
)
367 DBC_REQUIRE(refs
> 0);
368 DBC_REQUIRE(IS_VALID(cod_mgr_obj
));
369 DBC_REQUIRE(entry_pt
!= NULL
);
371 *entry_pt
= cod_mgr_obj
->ul_entry
;
377 * ======== cod_get_loader ========
379 * Get handle to the DBLL loader.
381 int cod_get_loader(struct cod_manager
*cod_mgr_obj
,
382 struct dbll_tar_obj
**loader
)
386 DBC_REQUIRE(refs
> 0);
387 DBC_REQUIRE(IS_VALID(cod_mgr_obj
));
388 DBC_REQUIRE(loader
!= NULL
);
390 *loader
= (struct dbll_tar_obj
*)cod_mgr_obj
->target
;
396 * ======== cod_get_section ========
398 * Retrieve the starting address and length of a section in the COFF file
399 * given the section name.
401 int cod_get_section(struct cod_libraryobj
*lib
, char *str_sect
,
402 OUT u32
*addr
, OUT u32
*len
)
404 struct cod_manager
*cod_mgr_obj
;
407 DBC_REQUIRE(refs
> 0);
408 DBC_REQUIRE(lib
!= NULL
);
409 DBC_REQUIRE(IS_VALID(lib
->cod_mgr
));
410 DBC_REQUIRE(str_sect
!= NULL
);
411 DBC_REQUIRE(addr
!= NULL
);
412 DBC_REQUIRE(len
!= NULL
);
417 cod_mgr_obj
= lib
->cod_mgr
;
418 status
= cod_mgr_obj
->fxns
.get_sect_fxn(lib
->dbll_lib
, str_sect
,
424 DBC_ENSURE(DSP_SUCCEEDED(status
) || ((*addr
== 0) && (*len
== 0)));
430 * ======== cod_get_sym_value ========
432 * Retrieve the value for the specified symbol. The symbol is first
433 * searched for literally and then, if not found, searched for as a
437 int cod_get_sym_value(struct cod_manager
*cod_mgr_obj
, char *str_sym
,
440 struct dbll_sym_val
*dbll_sym
;
442 DBC_REQUIRE(refs
> 0);
443 DBC_REQUIRE(IS_VALID(cod_mgr_obj
));
444 DBC_REQUIRE(str_sym
!= NULL
);
445 DBC_REQUIRE(pul_value
!= NULL
);
447 dev_dbg(bridge
, "%s: cod_mgr_obj: %p str_sym: %s pul_value: %p\n",
448 __func__
, cod_mgr_obj
, str_sym
, pul_value
);
449 if (cod_mgr_obj
->base_lib
) {
450 if (!cod_mgr_obj
->fxns
.
451 get_addr_fxn(cod_mgr_obj
->base_lib
, str_sym
, &dbll_sym
)) {
452 if (!cod_mgr_obj
->fxns
.
453 get_c_addr_fxn(cod_mgr_obj
->base_lib
, str_sym
,
461 *pul_value
= dbll_sym
->value
;
467 * ======== cod_init ========
469 * Initialize the COD module's private state.
476 DBC_REQUIRE(refs
>= 0);
481 DBC_ENSURE((ret
&& refs
> 0) || (!ret
&& refs
>= 0));
486 * ======== cod_load_base ========
488 * Load the initial program image, optionally with command-line arguments,
489 * on the DSP system managed by the supplied handle. The program to be
490 * loaded must be the first element of the args array and must be a fully
491 * qualified pathname.
493 * if num_argc doesn't match the number of arguments in the args array, the
494 * args array is searched for a NULL terminating entry, and argc is
495 * recalculated to reflect this. In this way, we can support NULL
496 * terminating args arrays, if num_argc is very large.
498 int cod_load_base(struct cod_manager
*cod_mgr_obj
, u32 num_argc
, char *args
[],
499 cod_writefxn pfn_write
, void *arb
, char *envp
[])
502 struct dbll_attrs save_attrs
;
503 struct dbll_attrs new_attrs
;
507 DBC_REQUIRE(refs
> 0);
508 DBC_REQUIRE(IS_VALID(cod_mgr_obj
));
509 DBC_REQUIRE(num_argc
> 0);
510 DBC_REQUIRE(args
!= NULL
);
511 DBC_REQUIRE(args
[0] != NULL
);
512 DBC_REQUIRE(pfn_write
!= NULL
);
513 DBC_REQUIRE(cod_mgr_obj
->base_lib
!= NULL
);
516 * Make sure every argv[] stated in argc has a value, or change argc to
517 * reflect true number in NULL terminated argv array.
519 for (i
= 0; i
< num_argc
; i
++) {
520 if (args
[i
] == NULL
) {
526 /* set the write function for this operation */
527 cod_mgr_obj
->fxns
.get_attrs_fxn(cod_mgr_obj
->target
, &save_attrs
);
529 new_attrs
= save_attrs
;
530 new_attrs
.write
= (dbll_write_fxn
) pfn_write
;
531 new_attrs
.input_params
= arb
;
532 new_attrs
.alloc
= (dbll_alloc_fxn
) no_op
;
533 new_attrs
.free
= (dbll_free_fxn
) no_op
;
534 new_attrs
.log_write
= NULL
;
535 new_attrs
.log_write_handle
= NULL
;
538 flags
= DBLL_CODE
| DBLL_DATA
| DBLL_SYMB
;
539 status
= cod_mgr_obj
->fxns
.load_fxn(cod_mgr_obj
->base_lib
, flags
,
541 &cod_mgr_obj
->ul_entry
);
542 if (DSP_FAILED(status
))
543 cod_mgr_obj
->fxns
.close_fxn(cod_mgr_obj
->base_lib
);
545 if (DSP_SUCCEEDED(status
))
546 cod_mgr_obj
->loaded
= true;
548 cod_mgr_obj
->base_lib
= NULL
;
554 * ======== cod_open ========
555 * Open library for reading sections.
557 int cod_open(struct cod_manager
*hmgr
, char *sz_coff_path
,
558 u32 flags
, struct cod_libraryobj
**lib_obj
)
561 struct cod_libraryobj
*lib
= NULL
;
563 DBC_REQUIRE(refs
> 0);
564 DBC_REQUIRE(IS_VALID(hmgr
));
565 DBC_REQUIRE(sz_coff_path
!= NULL
);
566 DBC_REQUIRE(flags
== COD_NOLOAD
|| flags
== COD_SYMB
);
567 DBC_REQUIRE(lib_obj
!= NULL
);
571 lib
= kzalloc(sizeof(struct cod_libraryobj
), GFP_KERNEL
);
575 if (DSP_SUCCEEDED(status
)) {
577 status
= hmgr
->fxns
.open_fxn(hmgr
->target
, sz_coff_path
, flags
,
579 if (DSP_SUCCEEDED(status
))
583 if (DSP_FAILED(status
))
584 pr_err("%s: error status 0x%x, sz_coff_path: %s flags: 0x%x\n",
585 __func__
, status
, sz_coff_path
, flags
);
590 * ======== cod_open_base ========
592 * Open base image for reading sections.
594 int cod_open_base(struct cod_manager
*hmgr
, char *sz_coff_path
,
598 struct dbll_library_obj
*lib
;
600 DBC_REQUIRE(refs
> 0);
601 DBC_REQUIRE(IS_VALID(hmgr
));
602 DBC_REQUIRE(sz_coff_path
!= NULL
);
604 /* if we previously opened a base image, close it now */
605 if (hmgr
->base_lib
) {
607 hmgr
->fxns
.unload_fxn(hmgr
->base_lib
, &hmgr
->attrs
);
608 hmgr
->loaded
= false;
610 hmgr
->fxns
.close_fxn(hmgr
->base_lib
);
611 hmgr
->base_lib
= NULL
;
613 status
= hmgr
->fxns
.open_fxn(hmgr
->target
, sz_coff_path
, flags
, &lib
);
614 if (DSP_SUCCEEDED(status
)) {
615 /* hang onto the library for subsequent sym table usage */
616 hmgr
->base_lib
= lib
;
617 strncpy(hmgr
->sz_zl_file
, sz_coff_path
, COD_MAXPATHLENGTH
- 1);
618 hmgr
->sz_zl_file
[COD_MAXPATHLENGTH
- 1] = '\0';
621 if (DSP_FAILED(status
))
622 pr_err("%s: error status 0x%x sz_coff_path: %s\n", __func__
,
623 status
, sz_coff_path
);
628 * ======== cod_read_section ========
630 * Retrieve the content of a code section given the section name.
632 int cod_read_section(struct cod_libraryobj
*lib
, char *str_sect
,
633 OUT
char *str_content
, u32 content_size
)
637 DBC_REQUIRE(refs
> 0);
638 DBC_REQUIRE(lib
!= NULL
);
639 DBC_REQUIRE(IS_VALID(lib
->cod_mgr
));
640 DBC_REQUIRE(str_sect
!= NULL
);
641 DBC_REQUIRE(str_content
!= NULL
);
645 lib
->cod_mgr
->fxns
.read_sect_fxn(lib
->dbll_lib
, str_sect
,
646 str_content
, content_size
);
654 * ======== no_op ========
659 static bool no_op(void)