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 /* ----------------------------------- Trace & Debug */
25 #include <dspbridge/dbc.h>
26 #include <dspbridge/gh.h>
28 /* ----------------------------------- OS Adaptation Layer */
30 /* Dynamic loader library interface */
31 #include <dspbridge/dynamic_loader.h>
32 #include <dspbridge/getsection.h>
34 /* ----------------------------------- This */
35 #include <dspbridge/dbll.h>
36 #include <dspbridge/rmm.h>
38 /* Number of buckets for symbol hash table */
39 #define MAXBUCKETS 211
41 /* Max buffer length */
44 #define DOFF_ALIGN(x) (((x) + 3) & ~3UL)
47 * ======== struct dbll_tar_obj* ========
48 * A target may have one or more libraries of symbols/code/data loaded
49 * onto it, where a library is simply the symbols/code/data contained
53 * ======== dbll_tar_obj ========
56 struct dbll_attrs attrs
;
57 struct dbll_library_obj
*head
; /* List of all opened libraries */
61 * The following 4 typedefs are "super classes" of the dynamic loader
62 * library types used in dynamic loader functions (dynamic_loader.h).
65 * ======== dbll_stream ========
66 * Contains dynamic_loader_stream
69 struct dynamic_loader_stream dl_stream
;
70 struct dbll_library_obj
*lib
;
74 * ======== ldr_symbol ========
77 struct dynamic_loader_sym dl_symbol
;
78 struct dbll_library_obj
*lib
;
82 * ======== dbll_alloc ========
85 struct dynamic_loader_allocate dl_alloc
;
86 struct dbll_library_obj
*lib
;
90 * ======== dbll_init_obj ========
92 struct dbll_init_obj
{
93 struct dynamic_loader_initialize dl_init
;
94 struct dbll_library_obj
*lib
;
98 * ======== DBLL_Library ========
99 * A library handle is returned by DBLL_Open() and is passed to dbll_load()
100 * to load symbols/code/data, and to dbll_unload(), to remove the
101 * symbols/code/data loaded by dbll_load().
105 * ======== dbll_library_obj ========
107 struct dbll_library_obj
{
108 struct dbll_library_obj
*next
; /* Next library in target's list */
109 struct dbll_library_obj
*prev
; /* Previous in the list */
110 struct dbll_tar_obj
*target_obj
; /* target for this library */
112 /* Objects needed by dynamic loader */
113 struct dbll_stream stream
;
114 struct ldr_symbol symbol
;
115 struct dbll_alloc allocate
;
116 struct dbll_init_obj init
;
119 char *file_name
; /* COFF file name */
120 void *fp
; /* Opaque file handle */
121 u32 entry
; /* Entry point */
122 void *desc
; /* desc of DOFF file loaded */
123 u32 open_ref
; /* Number of times opened */
124 u32 load_ref
; /* Number of times loaded */
125 struct gh_t_hash_tab
*sym_tab
; /* Hash table of symbols */
130 * ======== dbll_symbol ========
133 struct dbll_sym_val value
;
137 static void dof_close(struct dbll_library_obj
*zl_lib
);
138 static int dof_open(struct dbll_library_obj
*zl_lib
);
139 static s32
no_op(struct dynamic_loader_initialize
*thisptr
, void *bufr
,
140 ldr_addr locn
, struct ldr_section_info
*info
,
144 * Functions called by dynamic loader
147 /* dynamic_loader_stream */
148 static int dbll_read_buffer(struct dynamic_loader_stream
*this, void *buffer
,
150 static int dbll_set_file_posn(struct dynamic_loader_stream
*this,
152 /* dynamic_loader_sym */
153 static struct dynload_symbol
*dbll_find_symbol(struct dynamic_loader_sym
*this,
155 static struct dynload_symbol
*dbll_add_to_symbol_table(struct dynamic_loader_sym
156 *this, const char *name
,
158 static struct dynload_symbol
*find_in_symbol_table(struct dynamic_loader_sym
159 *this, const char *name
,
161 static void dbll_purge_symbol_table(struct dynamic_loader_sym
*this,
163 static void *allocate(struct dynamic_loader_sym
*this, unsigned memsize
);
164 static void deallocate(struct dynamic_loader_sym
*this, void *mem_ptr
);
165 static void dbll_err_report(struct dynamic_loader_sym
*this, const char *errstr
,
167 /* dynamic_loader_allocate */
168 static int dbll_rmm_alloc(struct dynamic_loader_allocate
*this,
169 struct ldr_section_info
*info
, unsigned align
);
170 static void rmm_dealloc(struct dynamic_loader_allocate
*this,
171 struct ldr_section_info
*info
);
173 /* dynamic_loader_initialize */
174 static int connect(struct dynamic_loader_initialize
*this);
175 static int read_mem(struct dynamic_loader_initialize
*this, void *buf
,
176 ldr_addr addr
, struct ldr_section_info
*info
,
178 static int write_mem(struct dynamic_loader_initialize
*this, void *buf
,
179 ldr_addr addr
, struct ldr_section_info
*info
,
181 static int fill_mem(struct dynamic_loader_initialize
*this, ldr_addr addr
,
182 struct ldr_section_info
*info
, unsigned bytes
,
184 static int execute(struct dynamic_loader_initialize
*this, ldr_addr start
);
185 static void release(struct dynamic_loader_initialize
*this);
187 /* symbol table hash functions */
188 static u16
name_hash(void *key
, u16 max_bucket
);
189 static bool name_match(void *key
, void *sp
);
190 static void sym_delete(void *value
);
192 static u32 refs
; /* module reference count */
194 /* Symbol Redefinition */
195 static int redefined_symbol
;
196 static int gbl_search
= 1;
199 * ======== dbll_close ========
201 void dbll_close(struct dbll_library_obj
*zl_lib
)
203 struct dbll_tar_obj
*zl_target
;
205 DBC_REQUIRE(refs
> 0);
207 DBC_REQUIRE(zl_lib
->open_ref
> 0);
208 zl_target
= zl_lib
->target_obj
;
210 if (zl_lib
->open_ref
== 0) {
211 /* Remove library from list */
212 if (zl_target
->head
== zl_lib
)
213 zl_target
->head
= zl_lib
->next
;
216 (zl_lib
->prev
)->next
= zl_lib
->next
;
219 (zl_lib
->next
)->prev
= zl_lib
->prev
;
221 /* Free DOF resources */
223 kfree(zl_lib
->file_name
);
225 /* remove symbols from symbol table */
227 gh_delete(zl_lib
->sym_tab
);
229 /* remove the library object itself */
236 * ======== dbll_create ========
238 int dbll_create(struct dbll_tar_obj
**target_obj
,
239 struct dbll_attrs
*pattrs
)
241 struct dbll_tar_obj
*pzl_target
;
244 DBC_REQUIRE(refs
> 0);
245 DBC_REQUIRE(pattrs
!= NULL
);
246 DBC_REQUIRE(target_obj
!= NULL
);
248 /* Allocate DBL target object */
249 pzl_target
= kzalloc(sizeof(struct dbll_tar_obj
), GFP_KERNEL
);
250 if (target_obj
!= NULL
) {
251 if (pzl_target
== NULL
) {
255 pzl_target
->attrs
= *pattrs
;
256 *target_obj
= (struct dbll_tar_obj
*)pzl_target
;
258 DBC_ENSURE((!status
&& *target_obj
) ||
259 (status
&& *target_obj
== NULL
));
266 * ======== dbll_delete ========
268 void dbll_delete(struct dbll_tar_obj
*target
)
270 struct dbll_tar_obj
*zl_target
= (struct dbll_tar_obj
*)target
;
272 DBC_REQUIRE(refs
> 0);
273 DBC_REQUIRE(zl_target
);
275 if (zl_target
!= NULL
)
281 * ======== dbll_exit ========
282 * Discontinue usage of DBL module.
286 DBC_REQUIRE(refs
> 0);
293 DBC_ENSURE(refs
>= 0);
297 * ======== dbll_get_addr ========
298 * Get address of name in the specified library.
300 bool dbll_get_addr(struct dbll_library_obj
*zl_lib
, char *name
,
301 struct dbll_sym_val
**sym_val
)
303 struct dbll_symbol
*sym
;
306 DBC_REQUIRE(refs
> 0);
308 DBC_REQUIRE(name
!= NULL
);
309 DBC_REQUIRE(sym_val
!= NULL
);
310 DBC_REQUIRE(zl_lib
->sym_tab
!= NULL
);
312 sym
= (struct dbll_symbol
*)gh_find(zl_lib
->sym_tab
, name
);
314 *sym_val
= &sym
->value
;
318 dev_dbg(bridge
, "%s: lib: %p name: %s paddr: %p, status 0x%x\n",
319 __func__
, zl_lib
, name
, sym_val
, status
);
324 * ======== dbll_get_attrs ========
325 * Retrieve the attributes of the target.
327 void dbll_get_attrs(struct dbll_tar_obj
*target
, struct dbll_attrs
*pattrs
)
329 struct dbll_tar_obj
*zl_target
= (struct dbll_tar_obj
*)target
;
331 DBC_REQUIRE(refs
> 0);
332 DBC_REQUIRE(zl_target
);
333 DBC_REQUIRE(pattrs
!= NULL
);
335 if ((pattrs
!= NULL
) && (zl_target
!= NULL
))
336 *pattrs
= zl_target
->attrs
;
341 * ======== dbll_get_c_addr ========
342 * Get address of a "C" name in the specified library.
344 bool dbll_get_c_addr(struct dbll_library_obj
*zl_lib
, char *name
,
345 struct dbll_sym_val
**sym_val
)
347 struct dbll_symbol
*sym
;
348 char cname
[MAXEXPR
+ 1];
351 DBC_REQUIRE(refs
> 0);
353 DBC_REQUIRE(sym_val
!= NULL
);
354 DBC_REQUIRE(zl_lib
->sym_tab
!= NULL
);
355 DBC_REQUIRE(name
!= NULL
);
359 strncpy(cname
+ 1, name
, sizeof(cname
) - 2);
360 cname
[MAXEXPR
] = '\0'; /* insure '\0' string termination */
362 /* Check for C name, if not found */
363 sym
= (struct dbll_symbol
*)gh_find(zl_lib
->sym_tab
, cname
);
366 *sym_val
= &sym
->value
;
374 * ======== dbll_get_sect ========
375 * Get the base address and size (in bytes) of a COFF section.
377 int dbll_get_sect(struct dbll_library_obj
*lib
, char *name
, u32
*paddr
,
381 bool opened_doff
= false;
382 const struct ldr_section_info
*sect
= NULL
;
383 struct dbll_library_obj
*zl_lib
= (struct dbll_library_obj
*)lib
;
386 DBC_REQUIRE(refs
> 0);
387 DBC_REQUIRE(name
!= NULL
);
388 DBC_REQUIRE(paddr
!= NULL
);
389 DBC_REQUIRE(psize
!= NULL
);
392 /* If DOFF file is not open, we open it. */
393 if (zl_lib
!= NULL
) {
394 if (zl_lib
->fp
== NULL
) {
395 status
= dof_open(zl_lib
);
400 (*(zl_lib
->target_obj
->attrs
.fseek
)) (zl_lib
->fp
,
409 if (dload_get_section_info(zl_lib
->desc
, name
, §
)) {
410 *paddr
= sect
->load_addr
;
411 *psize
= sect
->size
* byte_size
;
412 /* Make sure size is even for good swap */
417 *psize
= DOFF_ALIGN(*psize
);
427 dev_dbg(bridge
, "%s: lib: %p name: %s paddr: %p psize: %p, "
428 "status 0x%x\n", __func__
, lib
, name
, paddr
, psize
, status
);
434 * ======== dbll_init ========
438 DBC_REQUIRE(refs
>= 0);
449 * ======== dbll_load ========
451 int dbll_load(struct dbll_library_obj
*lib
, dbll_flags flags
,
452 struct dbll_attrs
*attrs
, u32
*entry
)
454 struct dbll_library_obj
*zl_lib
= (struct dbll_library_obj
*)lib
;
455 struct dbll_tar_obj
*dbzl
;
456 bool got_symbols
= true;
459 bool opened_doff
= false;
460 DBC_REQUIRE(refs
> 0);
462 DBC_REQUIRE(entry
!= NULL
);
463 DBC_REQUIRE(attrs
!= NULL
);
466 * Load if not already loaded.
468 if (zl_lib
->load_ref
== 0 || !(flags
& DBLL_DYNAMIC
)) {
469 dbzl
= zl_lib
->target_obj
;
470 dbzl
->attrs
= *attrs
;
471 /* Create a hash table for symbols if not already created */
472 if (zl_lib
->sym_tab
== NULL
) {
474 zl_lib
->sym_tab
= gh_create(MAXBUCKETS
,
475 sizeof(struct dbll_symbol
),
477 name_match
, sym_delete
);
478 if (zl_lib
->sym_tab
== NULL
)
483 * Set up objects needed by the dynamic loader
486 zl_lib
->stream
.dl_stream
.read_buffer
= dbll_read_buffer
;
487 zl_lib
->stream
.dl_stream
.set_file_posn
= dbll_set_file_posn
;
488 zl_lib
->stream
.lib
= zl_lib
;
490 zl_lib
->symbol
.dl_symbol
.find_matching_symbol
=
493 zl_lib
->symbol
.dl_symbol
.add_to_symbol_table
=
494 find_in_symbol_table
;
496 zl_lib
->symbol
.dl_symbol
.add_to_symbol_table
=
497 dbll_add_to_symbol_table
;
499 zl_lib
->symbol
.dl_symbol
.purge_symbol_table
=
500 dbll_purge_symbol_table
;
501 zl_lib
->symbol
.dl_symbol
.dload_allocate
= allocate
;
502 zl_lib
->symbol
.dl_symbol
.dload_deallocate
= deallocate
;
503 zl_lib
->symbol
.dl_symbol
.error_report
= dbll_err_report
;
504 zl_lib
->symbol
.lib
= zl_lib
;
506 zl_lib
->allocate
.dl_alloc
.dload_allocate
= dbll_rmm_alloc
;
507 zl_lib
->allocate
.dl_alloc
.dload_deallocate
= rmm_dealloc
;
508 zl_lib
->allocate
.lib
= zl_lib
;
510 zl_lib
->init
.dl_init
.connect
= connect
;
511 zl_lib
->init
.dl_init
.readmem
= read_mem
;
512 zl_lib
->init
.dl_init
.writemem
= write_mem
;
513 zl_lib
->init
.dl_init
.fillmem
= fill_mem
;
514 zl_lib
->init
.dl_init
.execute
= execute
;
515 zl_lib
->init
.dl_init
.release
= release
;
516 zl_lib
->init
.lib
= zl_lib
;
517 /* If COFF file is not open, we open it. */
518 if (zl_lib
->fp
== NULL
) {
519 status
= dof_open(zl_lib
);
525 zl_lib
->ul_pos
= (*(zl_lib
->target_obj
->attrs
.ftell
))
527 /* Reset file cursor */
528 (*(zl_lib
->target_obj
->attrs
.fseek
)) (zl_lib
->fp
,
531 symbols_reloaded
= true;
532 /* The 5th argument, DLOAD_INITBSS, tells the DLL
533 * module to zero-init all BSS sections. In general,
534 * this is not necessary and also increases load time.
535 * We may want to make this configurable by the user */
536 err
= dynamic_load_module(&zl_lib
->stream
.dl_stream
,
537 &zl_lib
->symbol
.dl_symbol
,
538 &zl_lib
->allocate
.dl_alloc
,
539 &zl_lib
->init
.dl_init
,
541 &zl_lib
->dload_mod_obj
);
545 } else if (redefined_symbol
) {
547 dbll_unload(zl_lib
, (struct dbll_attrs
*)attrs
);
548 redefined_symbol
= false;
551 *entry
= zl_lib
->entry
;
558 /* Clean up DOFF resources */
562 DBC_ENSURE(status
|| zl_lib
->load_ref
> 0);
564 dev_dbg(bridge
, "%s: lib: %p flags: 0x%x entry: %p, status 0x%x\n",
565 __func__
, lib
, flags
, entry
, status
);
571 * ======== dbll_load_sect ========
572 * Not supported for COFF.
574 int dbll_load_sect(struct dbll_library_obj
*zl_lib
, char *sec_name
,
575 struct dbll_attrs
*attrs
)
583 * ======== dbll_open ========
585 int dbll_open(struct dbll_tar_obj
*target
, char *file
, dbll_flags flags
,
586 struct dbll_library_obj
**lib_obj
)
588 struct dbll_tar_obj
*zl_target
= (struct dbll_tar_obj
*)target
;
589 struct dbll_library_obj
*zl_lib
= NULL
;
593 DBC_REQUIRE(refs
> 0);
594 DBC_REQUIRE(zl_target
);
595 DBC_REQUIRE(zl_target
->attrs
.fopen
!= NULL
);
596 DBC_REQUIRE(file
!= NULL
);
597 DBC_REQUIRE(lib_obj
!= NULL
);
599 zl_lib
= zl_target
->head
;
600 while (zl_lib
!= NULL
) {
601 if (strcmp(zl_lib
->file_name
, file
) == 0) {
602 /* Library is already opened */
606 zl_lib
= zl_lib
->next
;
608 if (zl_lib
== NULL
) {
609 /* Allocate DBL library object */
610 zl_lib
= kzalloc(sizeof(struct dbll_library_obj
), GFP_KERNEL
);
611 if (zl_lib
== NULL
) {
615 /* Increment ref count to allow close on failure
618 zl_lib
->target_obj
= zl_target
;
619 /* Keep a copy of the file name */
620 zl_lib
->file_name
= kzalloc(strlen(file
) + 1,
622 if (zl_lib
->file_name
== NULL
) {
625 strncpy(zl_lib
->file_name
, file
,
628 zl_lib
->sym_tab
= NULL
;
632 * Set up objects needed by the dynamic loader
638 zl_lib
->stream
.dl_stream
.read_buffer
= dbll_read_buffer
;
639 zl_lib
->stream
.dl_stream
.set_file_posn
= dbll_set_file_posn
;
640 zl_lib
->stream
.lib
= zl_lib
;
642 zl_lib
->symbol
.dl_symbol
.add_to_symbol_table
= dbll_add_to_symbol_table
;
643 zl_lib
->symbol
.dl_symbol
.find_matching_symbol
= dbll_find_symbol
;
644 zl_lib
->symbol
.dl_symbol
.purge_symbol_table
= dbll_purge_symbol_table
;
645 zl_lib
->symbol
.dl_symbol
.dload_allocate
= allocate
;
646 zl_lib
->symbol
.dl_symbol
.dload_deallocate
= deallocate
;
647 zl_lib
->symbol
.dl_symbol
.error_report
= dbll_err_report
;
648 zl_lib
->symbol
.lib
= zl_lib
;
650 zl_lib
->allocate
.dl_alloc
.dload_allocate
= dbll_rmm_alloc
;
651 zl_lib
->allocate
.dl_alloc
.dload_deallocate
= rmm_dealloc
;
652 zl_lib
->allocate
.lib
= zl_lib
;
654 zl_lib
->init
.dl_init
.connect
= connect
;
655 zl_lib
->init
.dl_init
.readmem
= read_mem
;
656 zl_lib
->init
.dl_init
.writemem
= write_mem
;
657 zl_lib
->init
.dl_init
.fillmem
= fill_mem
;
658 zl_lib
->init
.dl_init
.execute
= execute
;
659 zl_lib
->init
.dl_init
.release
= release
;
660 zl_lib
->init
.lib
= zl_lib
;
661 if (!status
&& zl_lib
->fp
== NULL
)
662 status
= dof_open(zl_lib
);
664 zl_lib
->ul_pos
= (*(zl_lib
->target_obj
->attrs
.ftell
)) (zl_lib
->fp
);
665 (*(zl_lib
->target_obj
->attrs
.fseek
)) (zl_lib
->fp
, (long)0, SEEK_SET
);
666 /* Create a hash table for symbols if flag is set */
667 if (zl_lib
->sym_tab
!= NULL
|| !(flags
& DBLL_SYMB
))
671 gh_create(MAXBUCKETS
, sizeof(struct dbll_symbol
), name_hash
,
672 name_match
, sym_delete
);
673 if (zl_lib
->sym_tab
== NULL
) {
676 /* Do a fake load to get symbols - set write func to no_op */
677 zl_lib
->init
.dl_init
.writemem
= no_op
;
678 err
= dynamic_open_module(&zl_lib
->stream
.dl_stream
,
679 &zl_lib
->symbol
.dl_symbol
,
680 &zl_lib
->allocate
.dl_alloc
,
681 &zl_lib
->init
.dl_init
, 0,
682 &zl_lib
->dload_mod_obj
);
686 /* Now that we have the symbol table, we can unload */
687 err
= dynamic_unload_module(zl_lib
->dload_mod_obj
,
688 &zl_lib
->symbol
.dl_symbol
,
689 &zl_lib
->allocate
.dl_alloc
,
690 &zl_lib
->init
.dl_init
);
694 zl_lib
->dload_mod_obj
= NULL
;
699 if (zl_lib
->open_ref
== 1) {
700 /* First time opened - insert in list */
702 (zl_target
->head
)->prev
= zl_lib
;
705 zl_lib
->next
= zl_target
->head
;
706 zl_target
->head
= zl_lib
;
708 *lib_obj
= (struct dbll_library_obj
*)zl_lib
;
712 dbll_close((struct dbll_library_obj
*)zl_lib
);
715 DBC_ENSURE((!status
&& (zl_lib
->open_ref
> 0) && *lib_obj
)
716 || (status
&& *lib_obj
== NULL
));
718 dev_dbg(bridge
, "%s: target: %p file: %s lib_obj: %p, status 0x%x\n",
719 __func__
, target
, file
, lib_obj
, status
);
725 * ======== dbll_read_sect ========
726 * Get the content of a COFF section.
728 int dbll_read_sect(struct dbll_library_obj
*lib
, char *name
,
731 struct dbll_library_obj
*zl_lib
= (struct dbll_library_obj
*)lib
;
732 bool opened_doff
= false;
733 u32 byte_size
; /* size of bytes */
734 u32 ul_sect_size
; /* size of section */
735 const struct ldr_section_info
*sect
= NULL
;
738 DBC_REQUIRE(refs
> 0);
740 DBC_REQUIRE(name
!= NULL
);
741 DBC_REQUIRE(buf
!= NULL
);
742 DBC_REQUIRE(size
!= 0);
744 /* If DOFF file is not open, we open it. */
745 if (zl_lib
!= NULL
) {
746 if (zl_lib
->fp
== NULL
) {
747 status
= dof_open(zl_lib
);
752 (*(zl_lib
->target_obj
->attrs
.fseek
)) (zl_lib
->fp
,
763 if (!dload_get_section_info(zl_lib
->desc
, name
, §
)) {
768 * Ensure the supplied buffer size is sufficient to store
769 * the section buf to be read.
771 ul_sect_size
= sect
->size
* byte_size
;
772 /* Make sure size is even for good swap */
773 if (ul_sect_size
% 2)
777 ul_sect_size
= DOFF_ALIGN(ul_sect_size
);
778 if (ul_sect_size
> size
) {
781 if (!dload_get_section(zl_lib
->desc
, sect
, buf
))
791 dev_dbg(bridge
, "%s: lib: %p name: %s buf: %p size: 0x%x, "
792 "status 0x%x\n", __func__
, lib
, name
, buf
, size
, status
);
797 * ======== dbll_set_attrs ========
798 * Set the attributes of the target.
800 void dbll_set_attrs(struct dbll_tar_obj
*target
, struct dbll_attrs
*pattrs
)
802 struct dbll_tar_obj
*zl_target
= (struct dbll_tar_obj
*)target
;
803 DBC_REQUIRE(refs
> 0);
804 DBC_REQUIRE(zl_target
);
805 DBC_REQUIRE(pattrs
!= NULL
);
807 if ((pattrs
!= NULL
) && (zl_target
!= NULL
))
808 zl_target
->attrs
= *pattrs
;
813 * ======== dbll_unload ========
815 void dbll_unload(struct dbll_library_obj
*lib
, struct dbll_attrs
*attrs
)
817 struct dbll_library_obj
*zl_lib
= (struct dbll_library_obj
*)lib
;
820 DBC_REQUIRE(refs
> 0);
822 DBC_REQUIRE(zl_lib
->load_ref
> 0);
823 dev_dbg(bridge
, "%s: lib: %p\n", __func__
, lib
);
825 /* Unload only if reference count is 0 */
826 if (zl_lib
->load_ref
!= 0)
829 zl_lib
->target_obj
->attrs
= *attrs
;
830 if (zl_lib
->dload_mod_obj
) {
831 err
= dynamic_unload_module(zl_lib
->dload_mod_obj
,
832 &zl_lib
->symbol
.dl_symbol
,
833 &zl_lib
->allocate
.dl_alloc
,
834 &zl_lib
->init
.dl_init
);
836 dev_dbg(bridge
, "%s: failed: 0x%x\n", __func__
, err
);
838 /* remove symbols from symbol table */
839 if (zl_lib
->sym_tab
!= NULL
) {
840 gh_delete(zl_lib
->sym_tab
);
841 zl_lib
->sym_tab
= NULL
;
843 /* delete DOFF desc since it holds *lots* of host OS
847 DBC_ENSURE(zl_lib
->load_ref
>= 0);
851 * ======== dbll_unload_sect ========
852 * Not supported for COFF.
854 int dbll_unload_sect(struct dbll_library_obj
*lib
, char *sec_name
,
855 struct dbll_attrs
*attrs
)
857 DBC_REQUIRE(refs
> 0);
858 DBC_REQUIRE(sec_name
!= NULL
);
864 * ======== dof_close ========
866 static void dof_close(struct dbll_library_obj
*zl_lib
)
869 dload_module_close(zl_lib
->desc
);
874 (zl_lib
->target_obj
->attrs
.fclose
) (zl_lib
->fp
);
880 * ======== dof_open ========
882 static int dof_open(struct dbll_library_obj
*zl_lib
)
884 void *open
= *(zl_lib
->target_obj
->attrs
.fopen
);
887 /* First open the file for the dynamic loader, then open COF */
889 (void *)((dbll_f_open_fxn
) (open
)) (zl_lib
->file_name
, "rb");
891 /* Open DOFF module */
892 if (zl_lib
->fp
&& zl_lib
->desc
== NULL
) {
893 (*(zl_lib
->target_obj
->attrs
.fseek
)) (zl_lib
->fp
, (long)0,
896 dload_module_open(&zl_lib
->stream
.dl_stream
,
897 &zl_lib
->symbol
.dl_symbol
);
898 if (zl_lib
->desc
== NULL
) {
899 (zl_lib
->target_obj
->attrs
.fclose
) (zl_lib
->fp
);
911 * ======== name_hash ========
913 static u16
name_hash(void *key
, u16 max_bucket
)
917 char *name
= (char *)key
;
919 DBC_REQUIRE(name
!= NULL
);
928 ret
= hash
% max_bucket
;
934 * ======== name_match ========
936 static bool name_match(void *key
, void *sp
)
938 DBC_REQUIRE(key
!= NULL
);
939 DBC_REQUIRE(sp
!= NULL
);
941 if ((key
!= NULL
) && (sp
!= NULL
)) {
942 if (strcmp((char *)key
, ((struct dbll_symbol
*)sp
)->name
) ==
950 * ======== no_op ========
952 static int no_op(struct dynamic_loader_initialize
*thisptr
, void *bufr
,
953 ldr_addr locn
, struct ldr_section_info
*info
, unsigned bytsize
)
959 * ======== sym_delete ========
961 static void sym_delete(void *value
)
963 struct dbll_symbol
*sp
= (struct dbll_symbol
*)value
;
969 * Dynamic Loader Functions
972 /* dynamic_loader_stream */
974 * ======== dbll_read_buffer ========
976 static int dbll_read_buffer(struct dynamic_loader_stream
*this, void *buffer
,
979 struct dbll_stream
*pstream
= (struct dbll_stream
*)this;
980 struct dbll_library_obj
*lib
;
983 DBC_REQUIRE(this != NULL
);
989 (*(lib
->target_obj
->attrs
.fread
)) (buffer
, 1, bufsize
,
996 * ======== dbll_set_file_posn ========
998 static int dbll_set_file_posn(struct dynamic_loader_stream
*this,
1001 struct dbll_stream
*pstream
= (struct dbll_stream
*)this;
1002 struct dbll_library_obj
*lib
;
1003 int status
= 0; /* Success */
1005 DBC_REQUIRE(this != NULL
);
1010 status
= (*(lib
->target_obj
->attrs
.fseek
)) (lib
->fp
, (long)pos
,
1017 /* dynamic_loader_sym */
1020 * ======== dbll_find_symbol ========
1022 static struct dynload_symbol
*dbll_find_symbol(struct dynamic_loader_sym
*this,
1025 struct dynload_symbol
*ret_sym
;
1026 struct ldr_symbol
*ldr_sym
= (struct ldr_symbol
*)this;
1027 struct dbll_library_obj
*lib
;
1028 struct dbll_sym_val
*dbll_sym
= NULL
;
1029 bool status
= false; /* Symbol not found yet */
1031 DBC_REQUIRE(this != NULL
);
1036 if (lib
->target_obj
->attrs
.sym_lookup
) {
1037 /* Check current lib + base lib + dep lib +
1039 status
= (*(lib
->target_obj
->attrs
.sym_lookup
))
1040 (lib
->target_obj
->attrs
.sym_handle
,
1041 lib
->target_obj
->attrs
.sym_arg
,
1042 lib
->target_obj
->attrs
.rmm_handle
, name
,
1045 /* Just check current lib for symbol */
1046 status
= dbll_get_addr((struct dbll_library_obj
*)lib
,
1047 (char *)name
, &dbll_sym
);
1050 dbll_get_c_addr((struct dbll_library_obj
*)
1057 if (!status
&& gbl_search
)
1058 dev_dbg(bridge
, "%s: Symbol not found: %s\n", __func__
, name
);
1060 DBC_ASSERT((status
&& (dbll_sym
!= NULL
))
1061 || (!status
&& (dbll_sym
== NULL
)));
1063 ret_sym
= (struct dynload_symbol
*)dbll_sym
;
1068 * ======== find_in_symbol_table ========
1070 static struct dynload_symbol
*find_in_symbol_table(struct dynamic_loader_sym
1071 *this, const char *name
,
1074 struct dynload_symbol
*ret_sym
;
1075 struct ldr_symbol
*ldr_sym
= (struct ldr_symbol
*)this;
1076 struct dbll_library_obj
*lib
;
1077 struct dbll_symbol
*sym
;
1079 DBC_REQUIRE(this != NULL
);
1082 DBC_REQUIRE(lib
->sym_tab
!= NULL
);
1084 sym
= (struct dbll_symbol
*)gh_find(lib
->sym_tab
, (char *)name
);
1086 ret_sym
= (struct dynload_symbol
*)&sym
->value
;
1091 * ======== dbll_add_to_symbol_table ========
1093 static struct dynload_symbol
*dbll_add_to_symbol_table(struct dynamic_loader_sym
1094 *this, const char *name
,
1097 struct dbll_symbol
*sym_ptr
= NULL
;
1098 struct dbll_symbol symbol
;
1099 struct dynload_symbol
*dbll_sym
= NULL
;
1100 struct ldr_symbol
*ldr_sym
= (struct ldr_symbol
*)this;
1101 struct dbll_library_obj
*lib
;
1102 struct dynload_symbol
*ret
;
1104 DBC_REQUIRE(this != NULL
);
1109 /* Check to see if symbol is already defined in symbol table */
1110 if (!(lib
->target_obj
->attrs
.base_image
)) {
1112 dbll_sym
= dbll_find_symbol(this, name
);
1115 redefined_symbol
= true;
1116 dev_dbg(bridge
, "%s already defined in symbol table\n",
1121 /* Allocate string to copy symbol name */
1122 symbol
.name
= kzalloc(strlen((char *const)name
) + 1, GFP_KERNEL
);
1123 if (symbol
.name
== NULL
)
1126 if (symbol
.name
!= NULL
) {
1127 /* Just copy name (value will be filled in by dynamic loader) */
1128 strncpy(symbol
.name
, (char *const)name
,
1129 strlen((char *const)name
) + 1);
1131 /* Add symbol to symbol table */
1133 (struct dbll_symbol
*)gh_insert(lib
->sym_tab
, (void *)name
,
1135 if (sym_ptr
== NULL
)
1139 if (sym_ptr
!= NULL
)
1140 ret
= (struct dynload_symbol
*)&sym_ptr
->value
;
1148 * ======== dbll_purge_symbol_table ========
1150 static void dbll_purge_symbol_table(struct dynamic_loader_sym
*this,
1153 struct ldr_symbol
*ldr_sym
= (struct ldr_symbol
*)this;
1154 struct dbll_library_obj
*lib
;
1156 DBC_REQUIRE(this != NULL
);
1160 /* May not need to do anything */
1164 * ======== allocate ========
1166 static void *allocate(struct dynamic_loader_sym
*this, unsigned memsize
)
1168 struct ldr_symbol
*ldr_sym
= (struct ldr_symbol
*)this;
1169 struct dbll_library_obj
*lib
;
1172 DBC_REQUIRE(this != NULL
);
1176 buf
= kzalloc(memsize
, GFP_KERNEL
);
1182 * ======== deallocate ========
1184 static void deallocate(struct dynamic_loader_sym
*this, void *mem_ptr
)
1186 struct ldr_symbol
*ldr_sym
= (struct ldr_symbol
*)this;
1187 struct dbll_library_obj
*lib
;
1189 DBC_REQUIRE(this != NULL
);
1197 * ======== dbll_err_report ========
1199 static void dbll_err_report(struct dynamic_loader_sym
*this, const char *errstr
,
1202 struct ldr_symbol
*ldr_sym
= (struct ldr_symbol
*)this;
1203 struct dbll_library_obj
*lib
;
1204 char temp_buf
[MAXEXPR
];
1206 DBC_REQUIRE(this != NULL
);
1209 vsnprintf((char *)temp_buf
, MAXEXPR
, (char *)errstr
, args
);
1210 dev_dbg(bridge
, "%s\n", temp_buf
);
1213 /* dynamic_loader_allocate */
1216 * ======== dbll_rmm_alloc ========
1218 static int dbll_rmm_alloc(struct dynamic_loader_allocate
*this,
1219 struct ldr_section_info
*info
, unsigned align
)
1221 struct dbll_alloc
*dbll_alloc_obj
= (struct dbll_alloc
*)this;
1222 struct dbll_library_obj
*lib
;
1225 struct rmm_addr rmm_addr_obj
;
1227 unsigned stype
= DLOAD_SECTION_TYPE(info
->type
);
1229 char *sz_sec_last_token
= NULL
;
1230 char *sz_last_token
= NULL
;
1231 char *sz_sect_name
= NULL
;
1238 u32 run_addr_flag
= 0;
1240 DBC_REQUIRE(this != NULL
);
1241 lib
= dbll_alloc_obj
->lib
;
1245 (stype
== DLOAD_TEXT
) ? DBLL_CODE
: (stype
==
1246 DLOAD_BSS
) ? DBLL_BSS
:
1249 /* Attempt to extract the segment ID and requirement information from
1250 the name of the section */
1251 DBC_REQUIRE(info
->name
);
1252 token_len
= strlen((char *)(info
->name
)) + 1;
1254 sz_sect_name
= kzalloc(token_len
, GFP_KERNEL
);
1255 sz_last_token
= kzalloc(token_len
, GFP_KERNEL
);
1256 sz_sec_last_token
= kzalloc(token_len
, GFP_KERNEL
);
1258 if (sz_sect_name
== NULL
|| sz_sec_last_token
== NULL
||
1259 sz_last_token
== NULL
) {
1263 strncpy(sz_sect_name
, (char *)(info
->name
), token_len
);
1264 psz_cur
= sz_sect_name
;
1265 while ((token
= strsep(&psz_cur
, ":")) && *token
!= '\0') {
1266 strncpy(sz_sec_last_token
, sz_last_token
,
1267 strlen(sz_last_token
) + 1);
1268 strncpy(sz_last_token
, token
, strlen(token
) + 1);
1269 token
= strsep(&psz_cur
, ":");
1270 count
++; /* optimizes processing */
1272 /* If token is 0 or 1, and sz_sec_last_token is DYN_DARAM or DYN_SARAM,
1273 or DYN_EXTERNAL, then mem granularity information is present
1274 within the section name - only process if there are at least three
1275 tokens within the section name (just a minor optimization) */
1277 strict_strtol(sz_last_token
, 10, (long *)&req
);
1279 if ((req
== 0) || (req
== 1)) {
1280 if (strcmp(sz_sec_last_token
, "DYN_DARAM") == 0) {
1283 if (strcmp(sz_sec_last_token
, "DYN_SARAM") == 0) {
1286 if (strcmp(sz_sec_last_token
,
1287 "DYN_EXTERNAL") == 0)
1293 kfree(sz_sect_name
);
1294 sz_sect_name
= NULL
;
1295 kfree(sz_last_token
);
1296 sz_last_token
= NULL
;
1297 kfree(sz_sec_last_token
);
1298 sz_sec_last_token
= NULL
;
1300 if (mem_sect_type
== DBLL_CODE
)
1301 alloc_size
= info
->size
+ GEM_L1P_PREFETCH_SIZE
;
1303 alloc_size
= info
->size
;
1305 if (info
->load_addr
!= info
->run_addr
)
1307 /* TODO - ideally, we can pass the alignment requirement also
1311 (lib
->target_obj
->attrs
.alloc
) (lib
->target_obj
->attrs
.
1312 rmm_handle
, mem_sect_type
,
1314 (u32
*) &rmm_addr_obj
,
1315 seg_id
, req
, false);
1320 /* RMM gives word address. Need to convert to byte address */
1321 info
->load_addr
= rmm_addr_obj
.addr
* DSPWORDSIZE
;
1323 info
->run_addr
= info
->load_addr
;
1324 info
->context
= (u32
) rmm_addr_obj
.segid
;
1325 dev_dbg(bridge
, "%s: %s base = 0x%x len = 0x%x, "
1326 "info->run_addr 0x%x, info->load_addr 0x%x\n",
1327 __func__
, info
->name
, info
->load_addr
/ DSPWORDSIZE
,
1328 info
->size
/ DSPWORDSIZE
, info
->run_addr
,
1335 * ======== rmm_dealloc ========
1337 static void rmm_dealloc(struct dynamic_loader_allocate
*this,
1338 struct ldr_section_info
*info
)
1340 struct dbll_alloc
*dbll_alloc_obj
= (struct dbll_alloc
*)this;
1341 struct dbll_library_obj
*lib
;
1344 unsigned stype
= DLOAD_SECTION_TYPE(info
->type
);
1349 (stype
== DLOAD_TEXT
) ? DBLL_CODE
: (stype
==
1350 DLOAD_BSS
) ? DBLL_BSS
:
1352 DBC_REQUIRE(this != NULL
);
1353 lib
= dbll_alloc_obj
->lib
;
1355 /* segid was set by alloc function */
1356 segid
= (u32
) info
->context
;
1357 if (mem_sect_type
== DBLL_CODE
)
1358 free_size
= info
->size
+ GEM_L1P_PREFETCH_SIZE
;
1360 free_size
= info
->size
;
1363 (lib
->target_obj
->attrs
.free
) (lib
->target_obj
->attrs
.
1366 DSPWORDSIZE
, free_size
,
1371 /* dynamic_loader_initialize */
1373 * ======== connect ========
1375 static int connect(struct dynamic_loader_initialize
*this)
1381 * ======== read_mem ========
1382 * This function does not need to be implemented.
1384 static int read_mem(struct dynamic_loader_initialize
*this, void *buf
,
1385 ldr_addr addr
, struct ldr_section_info
*info
,
1388 struct dbll_init_obj
*init_obj
= (struct dbll_init_obj
*)this;
1389 struct dbll_library_obj
*lib
;
1392 DBC_REQUIRE(this != NULL
);
1393 lib
= init_obj
->lib
;
1395 /* Need bridge_brd_read function */
1400 * ======== write_mem ========
1402 static int write_mem(struct dynamic_loader_initialize
*this, void *buf
,
1403 ldr_addr addr
, struct ldr_section_info
*info
,
1406 struct dbll_init_obj
*init_obj
= (struct dbll_init_obj
*)this;
1407 struct dbll_library_obj
*lib
;
1408 struct dbll_tar_obj
*target_obj
;
1409 struct dbll_sect_info sect_info
;
1413 DBC_REQUIRE(this != NULL
);
1414 lib
= init_obj
->lib
;
1418 target_obj
= lib
->target_obj
;
1421 (DLOAD_SECTION_TYPE(info
->type
) ==
1422 DLOAD_TEXT
) ? DBLL_CODE
: DBLL_DATA
;
1423 if (target_obj
&& target_obj
->attrs
.write
) {
1425 (*target_obj
->attrs
.write
) (target_obj
->attrs
.input_params
,
1429 if (target_obj
->attrs
.log_write
) {
1430 sect_info
.name
= info
->name
;
1431 sect_info
.sect_run_addr
= info
->run_addr
;
1432 sect_info
.sect_load_addr
= info
->load_addr
;
1433 sect_info
.size
= info
->size
;
1434 sect_info
.type
= mem_sect_type
;
1435 /* Pass the information about what we've written to
1437 (*target_obj
->attrs
.log_write
) (target_obj
->attrs
.
1447 * ======== fill_mem ========
1448 * Fill bytes of memory at a given address with a given value by
1449 * writing from a buffer containing the given value. Write in
1450 * sets of MAXEXPR (128) bytes to avoid large stack buffer issues.
1452 static int fill_mem(struct dynamic_loader_initialize
*this, ldr_addr addr
,
1453 struct ldr_section_info
*info
, unsigned bytes
, unsigned val
)
1457 struct dbll_library_obj
*lib
;
1458 struct dbll_init_obj
*init_obj
= (struct dbll_init_obj
*)this;
1460 DBC_REQUIRE(this != NULL
);
1461 lib
= init_obj
->lib
;
1463 /* Pass the NULL pointer to write_mem to get the start address of Shared
1464 memory. This is a trick to just get the start address, there is no
1465 writing taking place with this Writemem
1467 if ((lib
->target_obj
->attrs
.write
) != (dbll_write_fxn
) no_op
)
1468 write_mem(this, &pbuf
, addr
, info
, 0);
1470 memset(pbuf
, val
, bytes
);
1476 * ======== execute ========
1478 static int execute(struct dynamic_loader_initialize
*this, ldr_addr start
)
1480 struct dbll_init_obj
*init_obj
= (struct dbll_init_obj
*)this;
1481 struct dbll_library_obj
*lib
;
1484 DBC_REQUIRE(this != NULL
);
1485 lib
= init_obj
->lib
;
1487 /* Save entry point */
1489 lib
->entry
= (u32
) start
;
1495 * ======== release ========
1497 static void release(struct dynamic_loader_initialize
*this)
1501 #ifdef CONFIG_TIDSPBRIDGE_BACKTRACE
1503 * find_symbol_context - Basic symbol context structure
1504 * @address: Symbol Adress
1505 * @offset_range: Offset range where the search for the DSP symbol
1507 * @cur_best_offset: Best offset to start looking for the DSP symbol
1508 * @sym_addr: Address of the DSP symbol
1509 * @name: Symbol name
1512 struct find_symbol_context
{
1517 u32 cur_best_offset
;
1524 * find_symbol_callback() - Validates symbol address and copies the symbol name
1526 * @elem: dsp library context
1527 * @user_data: Find symbol context
1530 void find_symbol_callback(void *elem
, void *user_data
)
1532 struct dbll_symbol
*symbol
= elem
;
1533 struct find_symbol_context
*context
= user_data
;
1534 u32 symbol_addr
= symbol
->value
.value
;
1535 u32 offset
= context
->address
- symbol_addr
;
1538 * Address given should be greater than symbol address,
1539 * symbol address should be within specified range
1540 * and the offset should be better than previous one
1542 if (context
->address
>= symbol_addr
&& symbol_addr
< (u32
)-1 &&
1543 offset
< context
->cur_best_offset
) {
1544 context
->cur_best_offset
= offset
;
1545 context
->sym_addr
= symbol_addr
;
1546 strncpy(context
->name
, symbol
->name
, sizeof(context
->name
));
1553 * dbll_find_dsp_symbol() - This function retrieves the dsp symbol from the dsp binary.
1554 * @zl_lib: DSP binary obj library pointer
1555 * @address: Given address to find the dsp symbol
1556 * @offset_range: offset range to look for dsp symbol
1557 * @sym_addr_output: Symbol Output address
1558 * @name_output: String with the dsp symbol
1560 * This function retrieves the dsp symbol from the dsp binary.
1562 bool dbll_find_dsp_symbol(struct dbll_library_obj
*zl_lib
, u32 address
,
1563 u32 offset_range
, u32
*sym_addr_output
,
1566 bool status
= false;
1567 struct find_symbol_context context
;
1569 context
.address
= address
;
1570 context
.offset_range
= offset_range
;
1571 context
.cur_best_offset
= offset_range
;
1572 context
.sym_addr
= 0;
1573 context
.name
[0] = '\0';
1575 gh_iterate(zl_lib
->sym_tab
, find_symbol_callback
, &context
);
1577 if (context
.name
[0]) {
1579 strcpy(name_output
, context
.name
);
1580 *sym_addr_output
= context
.sym_addr
;