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 /* ----------------------------------- Platform Manager */
37 /* Include appropriate loader header file */
38 #include <dspbridge/dbll.h>
40 /* ----------------------------------- This */
41 #include <dspbridge/cod.h>
44 * ======== cod_manager ========
47 struct dbll_tar_obj
*target
;
48 struct dbll_library_obj
*base_lib
;
49 bool loaded
; /* Base library loaded? */
51 struct dbll_fxns fxns
;
52 struct dbll_attrs attrs
;
53 char sz_zl_file
[COD_MAXPATHLENGTH
];
57 * ======== cod_libraryobj ========
59 struct cod_libraryobj
{
60 struct dbll_library_obj
*dbll_lib
;
61 struct cod_manager
*cod_mgr
;
66 static struct dbll_fxns ldr_fxns
= {
67 (dbll_close_fxn
) dbll_close
,
68 (dbll_create_fxn
) dbll_create
,
69 (dbll_delete_fxn
) dbll_delete
,
70 (dbll_exit_fxn
) dbll_exit
,
71 (dbll_get_attrs_fxn
) dbll_get_attrs
,
72 (dbll_get_addr_fxn
) dbll_get_addr
,
73 (dbll_get_c_addr_fxn
) dbll_get_c_addr
,
74 (dbll_get_sect_fxn
) dbll_get_sect
,
75 (dbll_init_fxn
) dbll_init
,
76 (dbll_load_fxn
) dbll_load
,
77 (dbll_open_fxn
) dbll_open
,
78 (dbll_read_sect_fxn
) dbll_read_sect
,
79 (dbll_unload_fxn
) dbll_unload
,
82 static bool no_op(void);
85 * File operations (originally were under kfile.c)
87 static s32
cod_f_close(struct file
*filp
)
89 /* Check for valid handle */
93 filp_close(filp
, NULL
);
95 /* we can't use 0 here */
99 static struct file
*cod_f_open(const char *psz_file_name
, const char *sz_mode
)
107 /* ignore given mode and open file as read-only */
108 filp
= filp_open(psz_file_name
, O_RDONLY
, 0);
118 static s32
cod_f_read(void __user
*pbuffer
, s32 size
, s32 count
,
121 /* check for valid file handle */
125 if ((size
> 0) && (count
> 0) && pbuffer
) {
132 dw_bytes_read
= filp
->f_op
->read(filp
, pbuffer
, size
* count
,
139 return dw_bytes_read
/ size
;
145 static s32
cod_f_seek(struct file
*filp
, s32 offset
, s32 origin
)
149 /* check for valid file handle */
153 /* based on the origin flag, move the internal pointer */
154 dw_cur_pos
= filp
->f_op
->llseek(filp
, offset
, origin
);
156 if ((s32
) dw_cur_pos
< 0)
159 /* we can't use 0 here */
163 static s32
cod_f_tell(struct file
*filp
)
170 /* Get current position */
171 dw_cur_pos
= filp
->f_op
->llseek(filp
, 0, SEEK_CUR
);
173 if ((s32
) dw_cur_pos
< 0)
180 * ======== cod_close ========
182 void cod_close(struct cod_libraryobj
*lib
)
184 struct cod_manager
*hmgr
;
186 DBC_REQUIRE(refs
> 0);
187 DBC_REQUIRE(lib
!= NULL
);
188 DBC_REQUIRE(lib
->cod_mgr
);
191 hmgr
->fxns
.close_fxn(lib
->dbll_lib
);
197 * ======== cod_create ========
199 * Create an object to manage code on a DSP system.
200 * This object can be used to load an initial program image with
201 * arguments that can later be expanded with
202 * dynamically loaded object files.
205 int cod_create(struct cod_manager
**mgr
, char *str_zl_file
)
207 struct cod_manager
*mgr_new
;
208 struct dbll_attrs zl_attrs
;
211 DBC_REQUIRE(refs
> 0);
212 DBC_REQUIRE(mgr
!= NULL
);
217 mgr_new
= kzalloc(sizeof(struct cod_manager
), GFP_KERNEL
);
221 /* Set up loader functions */
222 mgr_new
->fxns
= ldr_fxns
;
224 /* initialize the ZL module */
225 mgr_new
->fxns
.init_fxn();
227 zl_attrs
.alloc
= (dbll_alloc_fxn
) no_op
;
228 zl_attrs
.free
= (dbll_free_fxn
) no_op
;
229 zl_attrs
.fread
= (dbll_read_fxn
) cod_f_read
;
230 zl_attrs
.fseek
= (dbll_seek_fxn
) cod_f_seek
;
231 zl_attrs
.ftell
= (dbll_tell_fxn
) cod_f_tell
;
232 zl_attrs
.fclose
= (dbll_f_close_fxn
) cod_f_close
;
233 zl_attrs
.fopen
= (dbll_f_open_fxn
) cod_f_open
;
234 zl_attrs
.sym_lookup
= NULL
;
235 zl_attrs
.base_image
= true;
236 zl_attrs
.log_write
= NULL
;
237 zl_attrs
.log_write_handle
= NULL
;
238 zl_attrs
.write
= NULL
;
239 zl_attrs
.rmm_handle
= NULL
;
240 zl_attrs
.input_params
= NULL
;
241 zl_attrs
.sym_handle
= NULL
;
242 zl_attrs
.sym_arg
= NULL
;
244 mgr_new
->attrs
= zl_attrs
;
246 status
= mgr_new
->fxns
.create_fxn(&mgr_new
->target
, &zl_attrs
);
253 /* return the new manager */
260 * ======== cod_delete ========
262 * Delete a code manager object.
264 void cod_delete(struct cod_manager
*cod_mgr_obj
)
266 DBC_REQUIRE(refs
> 0);
267 DBC_REQUIRE(cod_mgr_obj
);
269 if (cod_mgr_obj
->base_lib
) {
270 if (cod_mgr_obj
->loaded
)
271 cod_mgr_obj
->fxns
.unload_fxn(cod_mgr_obj
->base_lib
,
272 &cod_mgr_obj
->attrs
);
274 cod_mgr_obj
->fxns
.close_fxn(cod_mgr_obj
->base_lib
);
276 if (cod_mgr_obj
->target
) {
277 cod_mgr_obj
->fxns
.delete_fxn(cod_mgr_obj
->target
);
278 cod_mgr_obj
->fxns
.exit_fxn();
284 * ======== cod_exit ========
286 * Discontinue usage of the COD module.
291 DBC_REQUIRE(refs
> 0);
295 DBC_ENSURE(refs
>= 0);
299 * ======== cod_get_base_lib ========
301 * Get handle to the base image DBL library.
303 int cod_get_base_lib(struct cod_manager
*cod_mgr_obj
,
304 struct dbll_library_obj
**plib
)
308 DBC_REQUIRE(refs
> 0);
309 DBC_REQUIRE(cod_mgr_obj
);
310 DBC_REQUIRE(plib
!= NULL
);
312 *plib
= (struct dbll_library_obj
*)cod_mgr_obj
->base_lib
;
318 * ======== cod_get_base_name ========
320 int cod_get_base_name(struct cod_manager
*cod_mgr_obj
, char *sz_name
,
325 DBC_REQUIRE(refs
> 0);
326 DBC_REQUIRE(cod_mgr_obj
);
327 DBC_REQUIRE(sz_name
!= NULL
);
329 if (usize
<= COD_MAXPATHLENGTH
)
330 strncpy(sz_name
, cod_mgr_obj
->sz_zl_file
, usize
);
338 * ======== cod_get_entry ========
340 * Retrieve the entry point of a loaded DSP program image
343 int cod_get_entry(struct cod_manager
*cod_mgr_obj
, u32
*entry_pt
)
345 DBC_REQUIRE(refs
> 0);
346 DBC_REQUIRE(cod_mgr_obj
);
347 DBC_REQUIRE(entry_pt
!= NULL
);
349 *entry_pt
= cod_mgr_obj
->entry
;
355 * ======== cod_get_loader ========
357 * Get handle to the DBLL loader.
359 int cod_get_loader(struct cod_manager
*cod_mgr_obj
,
360 struct dbll_tar_obj
**loader
)
364 DBC_REQUIRE(refs
> 0);
365 DBC_REQUIRE(cod_mgr_obj
);
366 DBC_REQUIRE(loader
!= NULL
);
368 *loader
= (struct dbll_tar_obj
*)cod_mgr_obj
->target
;
374 * ======== cod_get_section ========
376 * Retrieve the starting address and length of a section in the COFF file
377 * given the section name.
379 int cod_get_section(struct cod_libraryobj
*lib
, char *str_sect
,
382 struct cod_manager
*cod_mgr_obj
;
385 DBC_REQUIRE(refs
> 0);
386 DBC_REQUIRE(lib
!= NULL
);
387 DBC_REQUIRE(lib
->cod_mgr
);
388 DBC_REQUIRE(str_sect
!= NULL
);
389 DBC_REQUIRE(addr
!= NULL
);
390 DBC_REQUIRE(len
!= NULL
);
395 cod_mgr_obj
= lib
->cod_mgr
;
396 status
= cod_mgr_obj
->fxns
.get_sect_fxn(lib
->dbll_lib
, str_sect
,
402 DBC_ENSURE(!status
|| ((*addr
== 0) && (*len
== 0)));
408 * ======== cod_get_sym_value ========
410 * Retrieve the value for the specified symbol. The symbol is first
411 * searched for literally and then, if not found, searched for as a
415 int cod_get_sym_value(struct cod_manager
*cod_mgr_obj
, char *str_sym
,
418 struct dbll_sym_val
*dbll_sym
;
420 DBC_REQUIRE(refs
> 0);
421 DBC_REQUIRE(cod_mgr_obj
);
422 DBC_REQUIRE(str_sym
!= NULL
);
423 DBC_REQUIRE(pul_value
!= NULL
);
425 dev_dbg(bridge
, "%s: cod_mgr_obj: %p str_sym: %s pul_value: %p\n",
426 __func__
, cod_mgr_obj
, str_sym
, pul_value
);
427 if (cod_mgr_obj
->base_lib
) {
428 if (!cod_mgr_obj
->fxns
.
429 get_addr_fxn(cod_mgr_obj
->base_lib
, str_sym
, &dbll_sym
)) {
430 if (!cod_mgr_obj
->fxns
.
431 get_c_addr_fxn(cod_mgr_obj
->base_lib
, str_sym
,
439 *pul_value
= dbll_sym
->value
;
445 * ======== cod_init ========
447 * Initialize the COD module's private state.
454 DBC_REQUIRE(refs
>= 0);
459 DBC_ENSURE((ret
&& refs
> 0) || (!ret
&& refs
>= 0));
464 * ======== cod_load_base ========
466 * Load the initial program image, optionally with command-line arguments,
467 * on the DSP system managed by the supplied handle. The program to be
468 * loaded must be the first element of the args array and must be a fully
469 * qualified pathname.
471 * if num_argc doesn't match the number of arguments in the args array, the
472 * args array is searched for a NULL terminating entry, and argc is
473 * recalculated to reflect this. In this way, we can support NULL
474 * terminating args arrays, if num_argc is very large.
476 int cod_load_base(struct cod_manager
*cod_mgr_obj
, u32 num_argc
, char *args
[],
477 cod_writefxn pfn_write
, void *arb
, char *envp
[])
480 struct dbll_attrs save_attrs
;
481 struct dbll_attrs new_attrs
;
485 DBC_REQUIRE(refs
> 0);
486 DBC_REQUIRE(cod_mgr_obj
);
487 DBC_REQUIRE(num_argc
> 0);
488 DBC_REQUIRE(args
!= NULL
);
489 DBC_REQUIRE(args
[0] != NULL
);
490 DBC_REQUIRE(pfn_write
!= NULL
);
491 DBC_REQUIRE(cod_mgr_obj
->base_lib
!= NULL
);
494 * Make sure every argv[] stated in argc has a value, or change argc to
495 * reflect true number in NULL terminated argv array.
497 for (i
= 0; i
< num_argc
; i
++) {
498 if (args
[i
] == NULL
) {
504 /* set the write function for this operation */
505 cod_mgr_obj
->fxns
.get_attrs_fxn(cod_mgr_obj
->target
, &save_attrs
);
507 new_attrs
= save_attrs
;
508 new_attrs
.write
= (dbll_write_fxn
) pfn_write
;
509 new_attrs
.input_params
= arb
;
510 new_attrs
.alloc
= (dbll_alloc_fxn
) no_op
;
511 new_attrs
.free
= (dbll_free_fxn
) no_op
;
512 new_attrs
.log_write
= NULL
;
513 new_attrs
.log_write_handle
= NULL
;
516 flags
= DBLL_CODE
| DBLL_DATA
| DBLL_SYMB
;
517 status
= cod_mgr_obj
->fxns
.load_fxn(cod_mgr_obj
->base_lib
, flags
,
519 &cod_mgr_obj
->entry
);
521 cod_mgr_obj
->fxns
.close_fxn(cod_mgr_obj
->base_lib
);
524 cod_mgr_obj
->loaded
= true;
526 cod_mgr_obj
->base_lib
= NULL
;
532 * ======== cod_open ========
533 * Open library for reading sections.
535 int cod_open(struct cod_manager
*hmgr
, char *sz_coff_path
,
536 u32 flags
, struct cod_libraryobj
**lib_obj
)
539 struct cod_libraryobj
*lib
= NULL
;
541 DBC_REQUIRE(refs
> 0);
543 DBC_REQUIRE(sz_coff_path
!= NULL
);
544 DBC_REQUIRE(flags
== COD_NOLOAD
|| flags
== COD_SYMB
);
545 DBC_REQUIRE(lib_obj
!= NULL
);
549 lib
= kzalloc(sizeof(struct cod_libraryobj
), GFP_KERNEL
);
555 status
= hmgr
->fxns
.open_fxn(hmgr
->target
, sz_coff_path
, flags
,
562 pr_err("%s: error status 0x%x, sz_coff_path: %s flags: 0x%x\n",
563 __func__
, status
, sz_coff_path
, flags
);
568 * ======== cod_open_base ========
570 * Open base image for reading sections.
572 int cod_open_base(struct cod_manager
*hmgr
, char *sz_coff_path
,
576 struct dbll_library_obj
*lib
;
578 DBC_REQUIRE(refs
> 0);
580 DBC_REQUIRE(sz_coff_path
!= NULL
);
582 /* if we previously opened a base image, close it now */
583 if (hmgr
->base_lib
) {
585 hmgr
->fxns
.unload_fxn(hmgr
->base_lib
, &hmgr
->attrs
);
586 hmgr
->loaded
= false;
588 hmgr
->fxns
.close_fxn(hmgr
->base_lib
);
589 hmgr
->base_lib
= NULL
;
591 status
= hmgr
->fxns
.open_fxn(hmgr
->target
, sz_coff_path
, flags
, &lib
);
593 /* hang onto the library for subsequent sym table usage */
594 hmgr
->base_lib
= lib
;
595 strncpy(hmgr
->sz_zl_file
, sz_coff_path
, COD_MAXPATHLENGTH
- 1);
596 hmgr
->sz_zl_file
[COD_MAXPATHLENGTH
- 1] = '\0';
600 pr_err("%s: error status 0x%x sz_coff_path: %s\n", __func__
,
601 status
, sz_coff_path
);
606 * ======== cod_read_section ========
608 * Retrieve the content of a code section given the section name.
610 int cod_read_section(struct cod_libraryobj
*lib
, char *str_sect
,
611 char *str_content
, u32 content_size
)
615 DBC_REQUIRE(refs
> 0);
616 DBC_REQUIRE(lib
!= NULL
);
617 DBC_REQUIRE(lib
->cod_mgr
);
618 DBC_REQUIRE(str_sect
!= NULL
);
619 DBC_REQUIRE(str_content
!= NULL
);
623 lib
->cod_mgr
->fxns
.read_sect_fxn(lib
->dbll_lib
, str_sect
,
624 str_content
, content_size
);
632 * ======== no_op ========
637 static bool no_op(void)