4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
6 * Copyright (C) 2005-2006 Texas Instruments, Inc.
8 * This package is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 #include <linux/types.h>
18 /* ----------------------------------- Host OS */
19 #include <dspbridge/host_os.h>
21 /* ----------------------------------- DSP/BIOS Bridge */
22 #include <dspbridge/dbdefs.h>
24 #include <dspbridge/gh.h>
26 /* ----------------------------------- OS Adaptation Layer */
28 /* Dynamic loader library interface */
29 #include <dspbridge/dynamic_loader.h>
30 #include <dspbridge/getsection.h>
32 /* ----------------------------------- This */
33 #include <dspbridge/dbll.h>
34 #include <dspbridge/rmm.h>
36 /* Number of buckets for symbol hash table */
37 #define MAXBUCKETS 211
39 /* Max buffer length */
42 #define DOFF_ALIGN(x) (((x) + 3) & ~3UL)
45 * ======== struct dbll_tar_obj* ========
46 * A target may have one or more libraries of symbols/code/data loaded
47 * onto it, where a library is simply the symbols/code/data contained
51 * ======== dbll_tar_obj ========
54 struct dbll_attrs attrs
;
55 struct dbll_library_obj
*head
; /* List of all opened libraries */
59 * The following 4 typedefs are "super classes" of the dynamic loader
60 * library types used in dynamic loader functions (dynamic_loader.h).
63 * ======== dbll_stream ========
64 * Contains dynamic_loader_stream
67 struct dynamic_loader_stream dl_stream
;
68 struct dbll_library_obj
*lib
;
72 * ======== ldr_symbol ========
75 struct dynamic_loader_sym dl_symbol
;
76 struct dbll_library_obj
*lib
;
80 * ======== dbll_alloc ========
83 struct dynamic_loader_allocate dl_alloc
;
84 struct dbll_library_obj
*lib
;
88 * ======== dbll_init_obj ========
90 struct dbll_init_obj
{
91 struct dynamic_loader_initialize dl_init
;
92 struct dbll_library_obj
*lib
;
96 * ======== DBLL_Library ========
97 * A library handle is returned by DBLL_Open() and is passed to dbll_load()
98 * to load symbols/code/data, and to dbll_unload(), to remove the
99 * symbols/code/data loaded by dbll_load().
103 * ======== dbll_library_obj ========
105 struct dbll_library_obj
{
106 struct dbll_library_obj
*next
; /* Next library in target's list */
107 struct dbll_library_obj
*prev
; /* Previous in the list */
108 struct dbll_tar_obj
*target_obj
; /* target for this library */
110 /* Objects needed by dynamic loader */
111 struct dbll_stream stream
;
112 struct ldr_symbol symbol
;
113 struct dbll_alloc allocate
;
114 struct dbll_init_obj init
;
117 char *file_name
; /* COFF file name */
118 void *fp
; /* Opaque file handle */
119 u32 entry
; /* Entry point */
120 void *desc
; /* desc of DOFF file loaded */
121 u32 open_ref
; /* Number of times opened */
122 u32 load_ref
; /* Number of times loaded */
123 struct gh_t_hash_tab
*sym_tab
; /* Hash table of symbols */
128 * ======== dbll_symbol ========
131 struct dbll_sym_val value
;
135 static void dof_close(struct dbll_library_obj
*zl_lib
);
136 static int dof_open(struct dbll_library_obj
*zl_lib
);
137 static s32
no_op(struct dynamic_loader_initialize
*thisptr
, void *bufr
,
138 ldr_addr locn
, struct ldr_section_info
*info
,
142 * Functions called by dynamic loader
145 /* dynamic_loader_stream */
146 static int dbll_read_buffer(struct dynamic_loader_stream
*this, void *buffer
,
148 static int dbll_set_file_posn(struct dynamic_loader_stream
*this,
150 /* dynamic_loader_sym */
151 static struct dynload_symbol
*dbll_find_symbol(struct dynamic_loader_sym
*this,
153 static struct dynload_symbol
*dbll_add_to_symbol_table(struct dynamic_loader_sym
154 *this, const char *name
,
156 static struct dynload_symbol
*find_in_symbol_table(struct dynamic_loader_sym
157 *this, const char *name
,
159 static void dbll_purge_symbol_table(struct dynamic_loader_sym
*this,
161 static void *allocate(struct dynamic_loader_sym
*this, unsigned memsize
);
162 static void deallocate(struct dynamic_loader_sym
*this, void *mem_ptr
);
163 static void dbll_err_report(struct dynamic_loader_sym
*this, const char *errstr
,
165 /* dynamic_loader_allocate */
166 static int dbll_rmm_alloc(struct dynamic_loader_allocate
*this,
167 struct ldr_section_info
*info
, unsigned align
);
168 static void rmm_dealloc(struct dynamic_loader_allocate
*this,
169 struct ldr_section_info
*info
);
171 /* dynamic_loader_initialize */
172 static int connect(struct dynamic_loader_initialize
*this);
173 static int read_mem(struct dynamic_loader_initialize
*this, void *buf
,
174 ldr_addr addr
, struct ldr_section_info
*info
,
176 static int write_mem(struct dynamic_loader_initialize
*this, void *buf
,
177 ldr_addr addr
, struct ldr_section_info
*info
,
179 static int fill_mem(struct dynamic_loader_initialize
*this, ldr_addr addr
,
180 struct ldr_section_info
*info
, unsigned bytes
,
182 static int execute(struct dynamic_loader_initialize
*this, ldr_addr start
);
183 static void release(struct dynamic_loader_initialize
*this);
185 /* symbol table hash functions */
186 static u16
name_hash(void *key
, u16 max_bucket
);
187 static bool name_match(void *key
, void *sp
);
188 static void sym_delete(void *value
);
190 /* Symbol Redefinition */
191 static int redefined_symbol
;
192 static int gbl_search
= 1;
195 * ======== dbll_close ========
197 void dbll_close(struct dbll_library_obj
*zl_lib
)
199 struct dbll_tar_obj
*zl_target
;
201 zl_target
= zl_lib
->target_obj
;
203 if (zl_lib
->open_ref
== 0) {
204 /* Remove library from list */
205 if (zl_target
->head
== zl_lib
)
206 zl_target
->head
= zl_lib
->next
;
209 (zl_lib
->prev
)->next
= zl_lib
->next
;
212 (zl_lib
->next
)->prev
= zl_lib
->prev
;
214 /* Free DOF resources */
216 kfree(zl_lib
->file_name
);
218 /* remove symbols from symbol table */
220 gh_delete(zl_lib
->sym_tab
);
222 /* remove the library object itself */
229 * ======== dbll_create ========
231 int dbll_create(struct dbll_tar_obj
**target_obj
,
232 struct dbll_attrs
*pattrs
)
234 struct dbll_tar_obj
*pzl_target
;
237 /* Allocate DBL target object */
238 pzl_target
= kzalloc(sizeof(struct dbll_tar_obj
), GFP_KERNEL
);
239 if (target_obj
!= NULL
) {
240 if (pzl_target
== NULL
) {
244 pzl_target
->attrs
= *pattrs
;
245 *target_obj
= (struct dbll_tar_obj
*)pzl_target
;
253 * ======== dbll_delete ========
255 void dbll_delete(struct dbll_tar_obj
*target
)
257 struct dbll_tar_obj
*zl_target
= (struct dbll_tar_obj
*)target
;
264 * ======== dbll_exit ========
265 * Discontinue usage of DBL module.
273 * ======== dbll_get_addr ========
274 * Get address of name in the specified library.
276 bool dbll_get_addr(struct dbll_library_obj
*zl_lib
, char *name
,
277 struct dbll_sym_val
**sym_val
)
279 struct dbll_symbol
*sym
;
282 sym
= (struct dbll_symbol
*)gh_find(zl_lib
->sym_tab
, name
);
284 *sym_val
= &sym
->value
;
288 dev_dbg(bridge
, "%s: lib: %p name: %s paddr: %p, status 0x%x\n",
289 __func__
, zl_lib
, name
, sym_val
, status
);
294 * ======== dbll_get_attrs ========
295 * Retrieve the attributes of the target.
297 void dbll_get_attrs(struct dbll_tar_obj
*target
, struct dbll_attrs
*pattrs
)
299 struct dbll_tar_obj
*zl_target
= (struct dbll_tar_obj
*)target
;
301 if ((pattrs
!= NULL
) && (zl_target
!= NULL
))
302 *pattrs
= zl_target
->attrs
;
307 * ======== dbll_get_c_addr ========
308 * Get address of a "C" name in the specified library.
310 bool dbll_get_c_addr(struct dbll_library_obj
*zl_lib
, char *name
,
311 struct dbll_sym_val
**sym_val
)
313 struct dbll_symbol
*sym
;
314 char cname
[MAXEXPR
+ 1];
319 strncpy(cname
+ 1, name
, sizeof(cname
) - 2);
320 cname
[MAXEXPR
] = '\0'; /* insure '\0' string termination */
322 /* Check for C name, if not found */
323 sym
= (struct dbll_symbol
*)gh_find(zl_lib
->sym_tab
, cname
);
326 *sym_val
= &sym
->value
;
334 * ======== dbll_get_sect ========
335 * Get the base address and size (in bytes) of a COFF section.
337 int dbll_get_sect(struct dbll_library_obj
*lib
, char *name
, u32
*paddr
,
341 bool opened_doff
= false;
342 const struct ldr_section_info
*sect
= NULL
;
343 struct dbll_library_obj
*zl_lib
= (struct dbll_library_obj
*)lib
;
346 /* If DOFF file is not open, we open it. */
347 if (zl_lib
!= NULL
) {
348 if (zl_lib
->fp
== NULL
) {
349 status
= dof_open(zl_lib
);
354 (*(zl_lib
->target_obj
->attrs
.fseek
)) (zl_lib
->fp
,
363 if (dload_get_section_info(zl_lib
->desc
, name
, §
)) {
364 *paddr
= sect
->load_addr
;
365 *psize
= sect
->size
* byte_size
;
366 /* Make sure size is even for good swap */
371 *psize
= DOFF_ALIGN(*psize
);
381 dev_dbg(bridge
, "%s: lib: %p name: %s paddr: %p psize: %p, "
382 "status 0x%x\n", __func__
, lib
, name
, paddr
, psize
, status
);
388 * ======== dbll_init ========
398 * ======== dbll_load ========
400 int dbll_load(struct dbll_library_obj
*lib
, dbll_flags flags
,
401 struct dbll_attrs
*attrs
, u32
*entry
)
403 struct dbll_library_obj
*zl_lib
= (struct dbll_library_obj
*)lib
;
404 struct dbll_tar_obj
*dbzl
;
405 bool got_symbols
= true;
408 bool opened_doff
= false;
411 * Load if not already loaded.
413 if (zl_lib
->load_ref
== 0 || !(flags
& DBLL_DYNAMIC
)) {
414 dbzl
= zl_lib
->target_obj
;
415 dbzl
->attrs
= *attrs
;
416 /* Create a hash table for symbols if not already created */
417 if (zl_lib
->sym_tab
== NULL
) {
419 zl_lib
->sym_tab
= gh_create(MAXBUCKETS
,
420 sizeof(struct dbll_symbol
),
422 name_match
, sym_delete
);
423 if (zl_lib
->sym_tab
== NULL
)
428 * Set up objects needed by the dynamic loader
431 zl_lib
->stream
.dl_stream
.read_buffer
= dbll_read_buffer
;
432 zl_lib
->stream
.dl_stream
.set_file_posn
= dbll_set_file_posn
;
433 zl_lib
->stream
.lib
= zl_lib
;
435 zl_lib
->symbol
.dl_symbol
.find_matching_symbol
=
438 zl_lib
->symbol
.dl_symbol
.add_to_symbol_table
=
439 find_in_symbol_table
;
441 zl_lib
->symbol
.dl_symbol
.add_to_symbol_table
=
442 dbll_add_to_symbol_table
;
444 zl_lib
->symbol
.dl_symbol
.purge_symbol_table
=
445 dbll_purge_symbol_table
;
446 zl_lib
->symbol
.dl_symbol
.dload_allocate
= allocate
;
447 zl_lib
->symbol
.dl_symbol
.dload_deallocate
= deallocate
;
448 zl_lib
->symbol
.dl_symbol
.error_report
= dbll_err_report
;
449 zl_lib
->symbol
.lib
= zl_lib
;
451 zl_lib
->allocate
.dl_alloc
.dload_allocate
= dbll_rmm_alloc
;
452 zl_lib
->allocate
.dl_alloc
.dload_deallocate
= rmm_dealloc
;
453 zl_lib
->allocate
.lib
= zl_lib
;
455 zl_lib
->init
.dl_init
.connect
= connect
;
456 zl_lib
->init
.dl_init
.readmem
= read_mem
;
457 zl_lib
->init
.dl_init
.writemem
= write_mem
;
458 zl_lib
->init
.dl_init
.fillmem
= fill_mem
;
459 zl_lib
->init
.dl_init
.execute
= execute
;
460 zl_lib
->init
.dl_init
.release
= release
;
461 zl_lib
->init
.lib
= zl_lib
;
462 /* If COFF file is not open, we open it. */
463 if (zl_lib
->fp
== NULL
) {
464 status
= dof_open(zl_lib
);
470 zl_lib
->pos
= (*(zl_lib
->target_obj
->attrs
.ftell
))
472 /* Reset file cursor */
473 (*(zl_lib
->target_obj
->attrs
.fseek
)) (zl_lib
->fp
,
476 symbols_reloaded
= true;
477 /* The 5th argument, DLOAD_INITBSS, tells the DLL
478 * module to zero-init all BSS sections. In general,
479 * this is not necessary and also increases load time.
480 * We may want to make this configurable by the user */
481 err
= dynamic_load_module(&zl_lib
->stream
.dl_stream
,
482 &zl_lib
->symbol
.dl_symbol
,
483 &zl_lib
->allocate
.dl_alloc
,
484 &zl_lib
->init
.dl_init
,
486 &zl_lib
->dload_mod_obj
);
490 } else if (redefined_symbol
) {
492 dbll_unload(zl_lib
, (struct dbll_attrs
*)attrs
);
493 redefined_symbol
= false;
496 *entry
= zl_lib
->entry
;
503 /* Clean up DOFF resources */
507 dev_dbg(bridge
, "%s: lib: %p flags: 0x%x entry: %p, status 0x%x\n",
508 __func__
, lib
, flags
, entry
, status
);
514 * ======== dbll_open ========
516 int dbll_open(struct dbll_tar_obj
*target
, char *file
, dbll_flags flags
,
517 struct dbll_library_obj
**lib_obj
)
519 struct dbll_tar_obj
*zl_target
= (struct dbll_tar_obj
*)target
;
520 struct dbll_library_obj
*zl_lib
= NULL
;
524 zl_lib
= zl_target
->head
;
525 while (zl_lib
!= NULL
) {
526 if (strcmp(zl_lib
->file_name
, file
) == 0) {
527 /* Library is already opened */
531 zl_lib
= zl_lib
->next
;
533 if (zl_lib
== NULL
) {
534 /* Allocate DBL library object */
535 zl_lib
= kzalloc(sizeof(struct dbll_library_obj
), GFP_KERNEL
);
536 if (zl_lib
== NULL
) {
540 /* Increment ref count to allow close on failure
543 zl_lib
->target_obj
= zl_target
;
544 /* Keep a copy of the file name */
545 zl_lib
->file_name
= kzalloc(strlen(file
) + 1,
547 if (zl_lib
->file_name
== NULL
) {
550 strncpy(zl_lib
->file_name
, file
,
553 zl_lib
->sym_tab
= NULL
;
557 * Set up objects needed by the dynamic loader
563 zl_lib
->stream
.dl_stream
.read_buffer
= dbll_read_buffer
;
564 zl_lib
->stream
.dl_stream
.set_file_posn
= dbll_set_file_posn
;
565 zl_lib
->stream
.lib
= zl_lib
;
567 zl_lib
->symbol
.dl_symbol
.add_to_symbol_table
= dbll_add_to_symbol_table
;
568 zl_lib
->symbol
.dl_symbol
.find_matching_symbol
= dbll_find_symbol
;
569 zl_lib
->symbol
.dl_symbol
.purge_symbol_table
= dbll_purge_symbol_table
;
570 zl_lib
->symbol
.dl_symbol
.dload_allocate
= allocate
;
571 zl_lib
->symbol
.dl_symbol
.dload_deallocate
= deallocate
;
572 zl_lib
->symbol
.dl_symbol
.error_report
= dbll_err_report
;
573 zl_lib
->symbol
.lib
= zl_lib
;
575 zl_lib
->allocate
.dl_alloc
.dload_allocate
= dbll_rmm_alloc
;
576 zl_lib
->allocate
.dl_alloc
.dload_deallocate
= rmm_dealloc
;
577 zl_lib
->allocate
.lib
= zl_lib
;
579 zl_lib
->init
.dl_init
.connect
= connect
;
580 zl_lib
->init
.dl_init
.readmem
= read_mem
;
581 zl_lib
->init
.dl_init
.writemem
= write_mem
;
582 zl_lib
->init
.dl_init
.fillmem
= fill_mem
;
583 zl_lib
->init
.dl_init
.execute
= execute
;
584 zl_lib
->init
.dl_init
.release
= release
;
585 zl_lib
->init
.lib
= zl_lib
;
586 if (!status
&& zl_lib
->fp
== NULL
)
587 status
= dof_open(zl_lib
);
589 zl_lib
->pos
= (*(zl_lib
->target_obj
->attrs
.ftell
)) (zl_lib
->fp
);
590 (*(zl_lib
->target_obj
->attrs
.fseek
)) (zl_lib
->fp
, (long)0, SEEK_SET
);
591 /* Create a hash table for symbols if flag is set */
592 if (zl_lib
->sym_tab
!= NULL
|| !(flags
& DBLL_SYMB
))
596 gh_create(MAXBUCKETS
, sizeof(struct dbll_symbol
), name_hash
,
597 name_match
, sym_delete
);
598 if (zl_lib
->sym_tab
== NULL
) {
601 /* Do a fake load to get symbols - set write func to no_op */
602 zl_lib
->init
.dl_init
.writemem
= no_op
;
603 err
= dynamic_open_module(&zl_lib
->stream
.dl_stream
,
604 &zl_lib
->symbol
.dl_symbol
,
605 &zl_lib
->allocate
.dl_alloc
,
606 &zl_lib
->init
.dl_init
, 0,
607 &zl_lib
->dload_mod_obj
);
611 /* Now that we have the symbol table, we can unload */
612 err
= dynamic_unload_module(zl_lib
->dload_mod_obj
,
613 &zl_lib
->symbol
.dl_symbol
,
614 &zl_lib
->allocate
.dl_alloc
,
615 &zl_lib
->init
.dl_init
);
619 zl_lib
->dload_mod_obj
= NULL
;
624 if (zl_lib
->open_ref
== 1) {
625 /* First time opened - insert in list */
627 (zl_target
->head
)->prev
= zl_lib
;
630 zl_lib
->next
= zl_target
->head
;
631 zl_target
->head
= zl_lib
;
633 *lib_obj
= (struct dbll_library_obj
*)zl_lib
;
637 dbll_close((struct dbll_library_obj
*)zl_lib
);
641 dev_dbg(bridge
, "%s: target: %p file: %s lib_obj: %p, status 0x%x\n",
642 __func__
, target
, file
, lib_obj
, status
);
648 * ======== dbll_read_sect ========
649 * Get the content of a COFF section.
651 int dbll_read_sect(struct dbll_library_obj
*lib
, char *name
,
654 struct dbll_library_obj
*zl_lib
= (struct dbll_library_obj
*)lib
;
655 bool opened_doff
= false;
656 u32 byte_size
; /* size of bytes */
657 u32 ul_sect_size
; /* size of section */
658 const struct ldr_section_info
*sect
= NULL
;
661 /* If DOFF file is not open, we open it. */
662 if (zl_lib
!= NULL
) {
663 if (zl_lib
->fp
== NULL
) {
664 status
= dof_open(zl_lib
);
669 (*(zl_lib
->target_obj
->attrs
.fseek
)) (zl_lib
->fp
,
680 if (!dload_get_section_info(zl_lib
->desc
, name
, §
)) {
685 * Ensure the supplied buffer size is sufficient to store
686 * the section buf to be read.
688 ul_sect_size
= sect
->size
* byte_size
;
689 /* Make sure size is even for good swap */
690 if (ul_sect_size
% 2)
694 ul_sect_size
= DOFF_ALIGN(ul_sect_size
);
695 if (ul_sect_size
> size
) {
698 if (!dload_get_section(zl_lib
->desc
, sect
, buf
))
708 dev_dbg(bridge
, "%s: lib: %p name: %s buf: %p size: 0x%x, "
709 "status 0x%x\n", __func__
, lib
, name
, buf
, size
, status
);
714 * ======== dbll_unload ========
716 void dbll_unload(struct dbll_library_obj
*lib
, struct dbll_attrs
*attrs
)
718 struct dbll_library_obj
*zl_lib
= (struct dbll_library_obj
*)lib
;
721 dev_dbg(bridge
, "%s: lib: %p\n", __func__
, lib
);
723 /* Unload only if reference count is 0 */
724 if (zl_lib
->load_ref
!= 0)
727 zl_lib
->target_obj
->attrs
= *attrs
;
728 if (zl_lib
->dload_mod_obj
) {
729 err
= dynamic_unload_module(zl_lib
->dload_mod_obj
,
730 &zl_lib
->symbol
.dl_symbol
,
731 &zl_lib
->allocate
.dl_alloc
,
732 &zl_lib
->init
.dl_init
);
734 dev_dbg(bridge
, "%s: failed: 0x%x\n", __func__
, err
);
736 /* remove symbols from symbol table */
737 if (zl_lib
->sym_tab
!= NULL
) {
738 gh_delete(zl_lib
->sym_tab
);
739 zl_lib
->sym_tab
= NULL
;
741 /* delete DOFF desc since it holds *lots* of host OS
747 * ======== dof_close ========
749 static void dof_close(struct dbll_library_obj
*zl_lib
)
752 dload_module_close(zl_lib
->desc
);
757 (zl_lib
->target_obj
->attrs
.fclose
) (zl_lib
->fp
);
763 * ======== dof_open ========
765 static int dof_open(struct dbll_library_obj
*zl_lib
)
767 void *open
= *(zl_lib
->target_obj
->attrs
.fopen
);
770 /* First open the file for the dynamic loader, then open COF */
772 (void *)((dbll_f_open_fxn
) (open
)) (zl_lib
->file_name
, "rb");
774 /* Open DOFF module */
775 if (zl_lib
->fp
&& zl_lib
->desc
== NULL
) {
776 (*(zl_lib
->target_obj
->attrs
.fseek
)) (zl_lib
->fp
, (long)0,
779 dload_module_open(&zl_lib
->stream
.dl_stream
,
780 &zl_lib
->symbol
.dl_symbol
);
781 if (zl_lib
->desc
== NULL
) {
782 (zl_lib
->target_obj
->attrs
.fclose
) (zl_lib
->fp
);
794 * ======== name_hash ========
796 static u16
name_hash(void *key
, u16 max_bucket
)
800 char *name
= (char *)key
;
809 ret
= hash
% max_bucket
;
815 * ======== name_match ========
817 static bool name_match(void *key
, void *sp
)
819 if ((key
!= NULL
) && (sp
!= NULL
)) {
820 if (strcmp((char *)key
, ((struct dbll_symbol
*)sp
)->name
) ==
828 * ======== no_op ========
830 static int no_op(struct dynamic_loader_initialize
*thisptr
, void *bufr
,
831 ldr_addr locn
, struct ldr_section_info
*info
, unsigned bytsize
)
837 * ======== sym_delete ========
839 static void sym_delete(void *value
)
841 struct dbll_symbol
*sp
= (struct dbll_symbol
*)value
;
847 * Dynamic Loader Functions
850 /* dynamic_loader_stream */
852 * ======== dbll_read_buffer ========
854 static int dbll_read_buffer(struct dynamic_loader_stream
*this, void *buffer
,
857 struct dbll_stream
*pstream
= (struct dbll_stream
*)this;
858 struct dbll_library_obj
*lib
;
864 (*(lib
->target_obj
->attrs
.fread
)) (buffer
, 1, bufsize
,
871 * ======== dbll_set_file_posn ========
873 static int dbll_set_file_posn(struct dynamic_loader_stream
*this,
876 struct dbll_stream
*pstream
= (struct dbll_stream
*)this;
877 struct dbll_library_obj
*lib
;
878 int status
= 0; /* Success */
882 status
= (*(lib
->target_obj
->attrs
.fseek
)) (lib
->fp
, (long)pos
,
889 /* dynamic_loader_sym */
892 * ======== dbll_find_symbol ========
894 static struct dynload_symbol
*dbll_find_symbol(struct dynamic_loader_sym
*this,
897 struct dynload_symbol
*ret_sym
;
898 struct ldr_symbol
*ldr_sym
= (struct ldr_symbol
*)this;
899 struct dbll_library_obj
*lib
;
900 struct dbll_sym_val
*dbll_sym
= NULL
;
901 bool status
= false; /* Symbol not found yet */
905 if (lib
->target_obj
->attrs
.sym_lookup
) {
906 /* Check current lib + base lib + dep lib +
908 status
= (*(lib
->target_obj
->attrs
.sym_lookup
))
909 (lib
->target_obj
->attrs
.sym_handle
,
910 lib
->target_obj
->attrs
.sym_arg
,
911 lib
->target_obj
->attrs
.rmm_handle
, name
,
914 /* Just check current lib for symbol */
915 status
= dbll_get_addr((struct dbll_library_obj
*)lib
,
916 (char *)name
, &dbll_sym
);
919 dbll_get_c_addr((struct dbll_library_obj
*)
926 if (!status
&& gbl_search
)
927 dev_dbg(bridge
, "%s: Symbol not found: %s\n", __func__
, name
);
929 ret_sym
= (struct dynload_symbol
*)dbll_sym
;
934 * ======== find_in_symbol_table ========
936 static struct dynload_symbol
*find_in_symbol_table(struct dynamic_loader_sym
937 *this, const char *name
,
940 struct dynload_symbol
*ret_sym
;
941 struct ldr_symbol
*ldr_sym
= (struct ldr_symbol
*)this;
942 struct dbll_library_obj
*lib
;
943 struct dbll_symbol
*sym
;
946 sym
= (struct dbll_symbol
*)gh_find(lib
->sym_tab
, (char *)name
);
948 ret_sym
= (struct dynload_symbol
*)&sym
->value
;
953 * ======== dbll_add_to_symbol_table ========
955 static struct dynload_symbol
*dbll_add_to_symbol_table(struct dynamic_loader_sym
956 *this, const char *name
,
959 struct dbll_symbol
*sym_ptr
= NULL
;
960 struct dbll_symbol symbol
;
961 struct dynload_symbol
*dbll_sym
= NULL
;
962 struct ldr_symbol
*ldr_sym
= (struct ldr_symbol
*)this;
963 struct dbll_library_obj
*lib
;
964 struct dynload_symbol
*ret
;
968 /* Check to see if symbol is already defined in symbol table */
969 if (!(lib
->target_obj
->attrs
.base_image
)) {
971 dbll_sym
= dbll_find_symbol(this, name
);
974 redefined_symbol
= true;
975 dev_dbg(bridge
, "%s already defined in symbol table\n",
980 /* Allocate string to copy symbol name */
981 symbol
.name
= kzalloc(strlen((char *const)name
) + 1, GFP_KERNEL
);
982 if (symbol
.name
== NULL
)
985 if (symbol
.name
!= NULL
) {
986 /* Just copy name (value will be filled in by dynamic loader) */
987 strncpy(symbol
.name
, (char *const)name
,
988 strlen((char *const)name
) + 1);
990 /* Add symbol to symbol table */
992 (struct dbll_symbol
*)gh_insert(lib
->sym_tab
, (void *)name
,
999 ret
= (struct dynload_symbol
*)&sym_ptr
->value
;
1007 * ======== dbll_purge_symbol_table ========
1009 static void dbll_purge_symbol_table(struct dynamic_loader_sym
*this,
1012 struct ldr_symbol
*ldr_sym
= (struct ldr_symbol
*)this;
1013 struct dbll_library_obj
*lib
;
1016 /* May not need to do anything */
1020 * ======== allocate ========
1022 static void *allocate(struct dynamic_loader_sym
*this, unsigned memsize
)
1024 struct ldr_symbol
*ldr_sym
= (struct ldr_symbol
*)this;
1025 struct dbll_library_obj
*lib
;
1030 buf
= kzalloc(memsize
, GFP_KERNEL
);
1036 * ======== deallocate ========
1038 static void deallocate(struct dynamic_loader_sym
*this, void *mem_ptr
)
1040 struct ldr_symbol
*ldr_sym
= (struct ldr_symbol
*)this;
1041 struct dbll_library_obj
*lib
;
1049 * ======== dbll_err_report ========
1051 static void dbll_err_report(struct dynamic_loader_sym
*this, const char *errstr
,
1054 struct ldr_symbol
*ldr_sym
= (struct ldr_symbol
*)this;
1055 struct dbll_library_obj
*lib
;
1056 char temp_buf
[MAXEXPR
];
1059 vsnprintf((char *)temp_buf
, MAXEXPR
, (char *)errstr
, args
);
1060 dev_dbg(bridge
, "%s\n", temp_buf
);
1063 /* dynamic_loader_allocate */
1066 * ======== dbll_rmm_alloc ========
1068 static int dbll_rmm_alloc(struct dynamic_loader_allocate
*this,
1069 struct ldr_section_info
*info
, unsigned align
)
1071 struct dbll_alloc
*dbll_alloc_obj
= (struct dbll_alloc
*)this;
1072 struct dbll_library_obj
*lib
;
1075 struct rmm_addr rmm_addr_obj
;
1077 unsigned stype
= DLOAD_SECTION_TYPE(info
->type
);
1079 char *sz_sec_last_token
= NULL
;
1080 char *sz_last_token
= NULL
;
1081 char *sz_sect_name
= NULL
;
1088 u32 run_addr_flag
= 0;
1090 lib
= dbll_alloc_obj
->lib
;
1093 (stype
== DLOAD_TEXT
) ? DBLL_CODE
: (stype
==
1094 DLOAD_BSS
) ? DBLL_BSS
:
1097 /* Attempt to extract the segment ID and requirement information from
1098 the name of the section */
1099 token_len
= strlen((char *)(info
->name
)) + 1;
1101 sz_sect_name
= kzalloc(token_len
, GFP_KERNEL
);
1102 sz_last_token
= kzalloc(token_len
, GFP_KERNEL
);
1103 sz_sec_last_token
= kzalloc(token_len
, GFP_KERNEL
);
1105 if (sz_sect_name
== NULL
|| sz_sec_last_token
== NULL
||
1106 sz_last_token
== NULL
) {
1110 strncpy(sz_sect_name
, (char *)(info
->name
), token_len
);
1111 psz_cur
= sz_sect_name
;
1112 while ((token
= strsep(&psz_cur
, ":")) && *token
!= '\0') {
1113 strncpy(sz_sec_last_token
, sz_last_token
,
1114 strlen(sz_last_token
) + 1);
1115 strncpy(sz_last_token
, token
, strlen(token
) + 1);
1116 token
= strsep(&psz_cur
, ":");
1117 count
++; /* optimizes processing */
1119 /* If token is 0 or 1, and sz_sec_last_token is DYN_DARAM or DYN_SARAM,
1120 or DYN_EXTERNAL, then mem granularity information is present
1121 within the section name - only process if there are at least three
1122 tokens within the section name (just a minor optimization) */
1124 status
= kstrtos32(sz_last_token
, 10, &req
);
1129 if ((req
== 0) || (req
== 1)) {
1130 if (strcmp(sz_sec_last_token
, "DYN_DARAM") == 0) {
1133 if (strcmp(sz_sec_last_token
, "DYN_SARAM") == 0) {
1136 if (strcmp(sz_sec_last_token
,
1137 "DYN_EXTERNAL") == 0)
1143 kfree(sz_sect_name
);
1144 sz_sect_name
= NULL
;
1145 kfree(sz_last_token
);
1146 sz_last_token
= NULL
;
1147 kfree(sz_sec_last_token
);
1148 sz_sec_last_token
= NULL
;
1150 if (mem_sect_type
== DBLL_CODE
)
1151 alloc_size
= info
->size
+ GEM_L1P_PREFETCH_SIZE
;
1153 alloc_size
= info
->size
;
1155 if (info
->load_addr
!= info
->run_addr
)
1157 /* TODO - ideally, we can pass the alignment requirement also
1161 (lib
->target_obj
->attrs
.alloc
) (lib
->target_obj
->attrs
.
1162 rmm_handle
, mem_sect_type
,
1164 (u32
*) &rmm_addr_obj
,
1165 seg_id
, req
, false);
1170 /* RMM gives word address. Need to convert to byte address */
1171 info
->load_addr
= rmm_addr_obj
.addr
* DSPWORDSIZE
;
1173 info
->run_addr
= info
->load_addr
;
1174 info
->context
= (u32
) rmm_addr_obj
.segid
;
1175 dev_dbg(bridge
, "%s: %s base = 0x%x len = 0x%x, "
1176 "info->run_addr 0x%x, info->load_addr 0x%x\n",
1177 __func__
, info
->name
, info
->load_addr
/ DSPWORDSIZE
,
1178 info
->size
/ DSPWORDSIZE
, info
->run_addr
,
1185 * ======== rmm_dealloc ========
1187 static void rmm_dealloc(struct dynamic_loader_allocate
*this,
1188 struct ldr_section_info
*info
)
1190 struct dbll_alloc
*dbll_alloc_obj
= (struct dbll_alloc
*)this;
1191 struct dbll_library_obj
*lib
;
1194 unsigned stype
= DLOAD_SECTION_TYPE(info
->type
);
1199 (stype
== DLOAD_TEXT
) ? DBLL_CODE
: (stype
==
1200 DLOAD_BSS
) ? DBLL_BSS
:
1202 lib
= dbll_alloc_obj
->lib
;
1203 /* segid was set by alloc function */
1204 segid
= (u32
) info
->context
;
1205 if (mem_sect_type
== DBLL_CODE
)
1206 free_size
= info
->size
+ GEM_L1P_PREFETCH_SIZE
;
1208 free_size
= info
->size
;
1211 (lib
->target_obj
->attrs
.free
) (lib
->target_obj
->attrs
.
1214 DSPWORDSIZE
, free_size
,
1219 /* dynamic_loader_initialize */
1221 * ======== connect ========
1223 static int connect(struct dynamic_loader_initialize
*this)
1229 * ======== read_mem ========
1230 * This function does not need to be implemented.
1232 static int read_mem(struct dynamic_loader_initialize
*this, void *buf
,
1233 ldr_addr addr
, struct ldr_section_info
*info
,
1236 struct dbll_init_obj
*init_obj
= (struct dbll_init_obj
*)this;
1237 struct dbll_library_obj
*lib
;
1240 lib
= init_obj
->lib
;
1241 /* Need bridge_brd_read function */
1246 * ======== write_mem ========
1248 static int write_mem(struct dynamic_loader_initialize
*this, void *buf
,
1249 ldr_addr addr
, struct ldr_section_info
*info
,
1252 struct dbll_init_obj
*init_obj
= (struct dbll_init_obj
*)this;
1253 struct dbll_library_obj
*lib
;
1254 struct dbll_tar_obj
*target_obj
;
1255 struct dbll_sect_info sect_info
;
1259 lib
= init_obj
->lib
;
1263 target_obj
= lib
->target_obj
;
1266 (DLOAD_SECTION_TYPE(info
->type
) ==
1267 DLOAD_TEXT
) ? DBLL_CODE
: DBLL_DATA
;
1268 if (target_obj
&& target_obj
->attrs
.write
) {
1270 (*target_obj
->attrs
.write
) (target_obj
->attrs
.input_params
,
1274 if (target_obj
->attrs
.log_write
) {
1275 sect_info
.name
= info
->name
;
1276 sect_info
.sect_run_addr
= info
->run_addr
;
1277 sect_info
.sect_load_addr
= info
->load_addr
;
1278 sect_info
.size
= info
->size
;
1279 sect_info
.type
= mem_sect_type
;
1280 /* Pass the information about what we've written to
1282 (*target_obj
->attrs
.log_write
) (target_obj
->attrs
.
1292 * ======== fill_mem ========
1293 * Fill bytes of memory at a given address with a given value by
1294 * writing from a buffer containing the given value. Write in
1295 * sets of MAXEXPR (128) bytes to avoid large stack buffer issues.
1297 static int fill_mem(struct dynamic_loader_initialize
*this, ldr_addr addr
,
1298 struct ldr_section_info
*info
, unsigned bytes
, unsigned val
)
1302 struct dbll_library_obj
*lib
;
1303 struct dbll_init_obj
*init_obj
= (struct dbll_init_obj
*)this;
1305 lib
= init_obj
->lib
;
1307 /* Pass the NULL pointer to write_mem to get the start address of Shared
1308 memory. This is a trick to just get the start address, there is no
1309 writing taking place with this Writemem
1311 if ((lib
->target_obj
->attrs
.write
) != (dbll_write_fxn
) no_op
)
1312 write_mem(this, &pbuf
, addr
, info
, 0);
1314 memset(pbuf
, val
, bytes
);
1320 * ======== execute ========
1322 static int execute(struct dynamic_loader_initialize
*this, ldr_addr start
)
1324 struct dbll_init_obj
*init_obj
= (struct dbll_init_obj
*)this;
1325 struct dbll_library_obj
*lib
;
1328 lib
= init_obj
->lib
;
1329 /* Save entry point */
1331 lib
->entry
= (u32
) start
;
1337 * ======== release ========
1339 static void release(struct dynamic_loader_initialize
*this)
1343 #ifdef CONFIG_TIDSPBRIDGE_BACKTRACE
1345 * find_symbol_context - Basic symbol context structure
1346 * @address: Symbol Address
1347 * @offset_range: Offset range where the search for the DSP symbol
1349 * @cur_best_offset: Best offset to start looking for the DSP symbol
1350 * @sym_addr: Address of the DSP symbol
1351 * @name: Symbol name
1354 struct find_symbol_context
{
1359 u32 cur_best_offset
;
1366 * find_symbol_callback() - Validates symbol address and copies the symbol name
1368 * @elem: dsp library context
1369 * @user_data: Find symbol context
1372 void find_symbol_callback(void *elem
, void *user_data
)
1374 struct dbll_symbol
*symbol
= elem
;
1375 struct find_symbol_context
*context
= user_data
;
1376 u32 symbol_addr
= symbol
->value
.value
;
1377 u32 offset
= context
->address
- symbol_addr
;
1380 * Address given should be greater than symbol address,
1381 * symbol address should be within specified range
1382 * and the offset should be better than previous one
1384 if (context
->address
>= symbol_addr
&& symbol_addr
< (u32
)-1 &&
1385 offset
< context
->cur_best_offset
) {
1386 context
->cur_best_offset
= offset
;
1387 context
->sym_addr
= symbol_addr
;
1388 strlcpy(context
->name
, symbol
->name
, sizeof(context
->name
));
1395 * dbll_find_dsp_symbol() - This function retrieves the dsp symbol from the dsp binary.
1396 * @zl_lib: DSP binary obj library pointer
1397 * @address: Given address to find the dsp symbol
1398 * @offset_range: offset range to look for dsp symbol
1399 * @sym_addr_output: Symbol Output address
1400 * @name_output: String with the dsp symbol
1402 * This function retrieves the dsp symbol from the dsp binary.
1404 bool dbll_find_dsp_symbol(struct dbll_library_obj
*zl_lib
, u32 address
,
1405 u32 offset_range
, u32
*sym_addr_output
,
1408 bool status
= false;
1409 struct find_symbol_context context
;
1411 context
.address
= address
;
1412 context
.offset_range
= offset_range
;
1413 context
.cur_best_offset
= offset_range
;
1414 context
.sym_addr
= 0;
1415 context
.name
[0] = '\0';
1417 gh_iterate(zl_lib
->sym_tab
, find_symbol_callback
, &context
);
1419 if (context
.name
[0]) {
1421 strcpy(name_output
, context
.name
);
1422 *sym_addr_output
= context
.sym_addr
;