GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / staging / tidspbridge / pmgr / dbll.c
blob23406386f61adccd065da4d4f8e372f4231183bd
1 /*
2 * dbll.c
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 */
42 #define MAXEXPR 128
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
50 * in a DOFF file.
53 * ======== dbll_tar_obj ========
55 struct 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
68 struct dbll_stream {
69 struct dynamic_loader_stream dl_stream;
70 struct dbll_library_obj *lib;
74 * ======== ldr_symbol ========
76 struct ldr_symbol {
77 struct dynamic_loader_sym dl_symbol;
78 struct dbll_library_obj *lib;
82 * ======== dbll_alloc ========
84 struct 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;
117 void *dload_mod_obj;
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 */
126 u32 ul_pos;
130 * ======== dbll_symbol ========
132 struct dbll_symbol {
133 struct dbll_sym_val value;
134 char *name;
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,
141 unsigned bytsize);
144 * Functions called by dynamic loader
147 /* dynamic_loader_stream */
148 static int dbll_read_buffer(struct dynamic_loader_stream *this, void *buffer,
149 unsigned bufsize);
150 static int dbll_set_file_posn(struct dynamic_loader_stream *this,
151 unsigned int pos);
152 /* dynamic_loader_sym */
153 static struct dynload_symbol *dbll_find_symbol(struct dynamic_loader_sym *this,
154 const char *name);
155 static struct dynload_symbol *dbll_add_to_symbol_table(struct dynamic_loader_sym
156 *this, const char *name,
157 unsigned module_id);
158 static struct dynload_symbol *find_in_symbol_table(struct dynamic_loader_sym
159 *this, const char *name,
160 unsigned moduleid);
161 static void dbll_purge_symbol_table(struct dynamic_loader_sym *this,
162 unsigned module_id);
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,
166 va_list args);
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,
177 unsigned bytes);
178 static int write_mem(struct dynamic_loader_initialize *this, void *buf,
179 ldr_addr addr, struct ldr_section_info *info,
180 unsigned nbytes);
181 static int fill_mem(struct dynamic_loader_initialize *this, ldr_addr addr,
182 struct ldr_section_info *info, unsigned bytes,
183 unsigned val);
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);
206 DBC_REQUIRE(zl_lib);
207 DBC_REQUIRE(zl_lib->open_ref > 0);
208 zl_target = zl_lib->target_obj;
209 zl_lib->open_ref--;
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;
215 if (zl_lib->prev)
216 (zl_lib->prev)->next = zl_lib->next;
218 if (zl_lib->next)
219 (zl_lib->next)->prev = zl_lib->prev;
221 /* Free DOF resources */
222 dof_close(zl_lib);
223 kfree(zl_lib->file_name);
225 /* remove symbols from symbol table */
226 if (zl_lib->sym_tab)
227 gh_delete(zl_lib->sym_tab);
229 /* remove the library object itself */
230 kfree(zl_lib);
231 zl_lib = NULL;
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;
242 int status = 0;
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) {
252 *target_obj = NULL;
253 status = -ENOMEM;
254 } else {
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));
262 return status;
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)
276 kfree(zl_target);
281 * ======== dbll_exit ========
282 * Discontinue usage of DBL module.
284 void dbll_exit(void)
286 DBC_REQUIRE(refs > 0);
288 refs--;
290 if (refs == 0)
291 gh_exit();
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;
304 bool status = false;
306 DBC_REQUIRE(refs > 0);
307 DBC_REQUIRE(zl_lib);
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);
313 if (sym != NULL) {
314 *sym_val = &sym->value;
315 status = true;
318 dev_dbg(bridge, "%s: lib: %p name: %s paddr: %p, status 0x%x\n",
319 __func__, zl_lib, name, sym_val, status);
320 return 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];
349 bool status = false;
351 DBC_REQUIRE(refs > 0);
352 DBC_REQUIRE(zl_lib);
353 DBC_REQUIRE(sym_val != NULL);
354 DBC_REQUIRE(zl_lib->sym_tab != NULL);
355 DBC_REQUIRE(name != NULL);
357 cname[0] = '_';
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);
365 if (sym != NULL) {
366 *sym_val = &sym->value;
367 status = true;
370 return status;
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,
378 u32 *psize)
380 u32 byte_size;
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;
384 int status = 0;
386 DBC_REQUIRE(refs > 0);
387 DBC_REQUIRE(name != NULL);
388 DBC_REQUIRE(paddr != NULL);
389 DBC_REQUIRE(psize != NULL);
390 DBC_REQUIRE(zl_lib);
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);
396 if (!status)
397 opened_doff = true;
399 } else {
400 (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp,
401 zl_lib->ul_pos,
402 SEEK_SET);
404 } else {
405 status = -EFAULT;
407 if (!status) {
408 byte_size = 1;
409 if (dload_get_section_info(zl_lib->desc, name, &sect)) {
410 *paddr = sect->load_addr;
411 *psize = sect->size * byte_size;
412 /* Make sure size is even for good swap */
413 if (*psize % 2)
414 (*psize)++;
416 /* Align size */
417 *psize = DOFF_ALIGN(*psize);
418 } else {
419 status = -ENXIO;
422 if (opened_doff) {
423 dof_close(zl_lib);
424 opened_doff = false;
427 dev_dbg(bridge, "%s: lib: %p name: %s paddr: %p psize: %p, "
428 "status 0x%x\n", __func__, lib, name, paddr, psize, status);
430 return status;
434 * ======== dbll_init ========
436 bool dbll_init(void)
438 DBC_REQUIRE(refs >= 0);
440 if (refs == 0)
441 gh_init();
443 refs++;
445 return true;
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;
457 s32 err;
458 int status = 0;
459 bool opened_doff = false;
460 DBC_REQUIRE(refs > 0);
461 DBC_REQUIRE(zl_lib);
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) {
473 got_symbols = false;
474 zl_lib->sym_tab = gh_create(MAXBUCKETS,
475 sizeof(struct dbll_symbol),
476 name_hash,
477 name_match, sym_delete);
478 if (zl_lib->sym_tab == NULL)
479 status = -ENOMEM;
483 * Set up objects needed by the dynamic loader
485 /* Stream */
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;
489 /* Symbol */
490 zl_lib->symbol.dl_symbol.find_matching_symbol =
491 dbll_find_symbol;
492 if (got_symbols) {
493 zl_lib->symbol.dl_symbol.add_to_symbol_table =
494 find_in_symbol_table;
495 } else {
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;
505 /* Allocate */
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;
509 /* Init */
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);
520 if (!status)
521 opened_doff = true;
524 if (!status) {
525 zl_lib->ul_pos = (*(zl_lib->target_obj->attrs.ftell))
526 (zl_lib->fp);
527 /* Reset file cursor */
528 (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp,
529 (long)0,
530 SEEK_SET);
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,
540 DLOAD_INITBSS,
541 &zl_lib->dload_mod_obj);
543 if (err != 0) {
544 status = -EILSEQ;
545 } else if (redefined_symbol) {
546 zl_lib->load_ref++;
547 dbll_unload(zl_lib, (struct dbll_attrs *)attrs);
548 redefined_symbol = false;
549 status = -EILSEQ;
550 } else {
551 *entry = zl_lib->entry;
555 if (!status)
556 zl_lib->load_ref++;
558 /* Clean up DOFF resources */
559 if (opened_doff)
560 dof_close(zl_lib);
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);
567 return 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)
577 DBC_REQUIRE(zl_lib);
579 return -ENOSYS;
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;
590 s32 err;
591 int status = 0;
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 */
603 zl_lib->open_ref++;
604 break;
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) {
612 status = -ENOMEM;
613 } else {
614 zl_lib->ul_pos = 0;
615 /* Increment ref count to allow close on failure
616 * later on */
617 zl_lib->open_ref++;
618 zl_lib->target_obj = zl_target;
619 /* Keep a copy of the file name */
620 zl_lib->file_name = kzalloc(strlen(file) + 1,
621 GFP_KERNEL);
622 if (zl_lib->file_name == NULL) {
623 status = -ENOMEM;
624 } else {
625 strncpy(zl_lib->file_name, file,
626 strlen(file) + 1);
628 zl_lib->sym_tab = NULL;
632 * Set up objects needed by the dynamic loader
634 if (status)
635 goto func_cont;
637 /* Stream */
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;
641 /* Symbol */
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;
649 /* Allocate */
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;
653 /* Init */
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))
668 goto func_cont;
670 zl_lib->sym_tab =
671 gh_create(MAXBUCKETS, sizeof(struct dbll_symbol), name_hash,
672 name_match, sym_delete);
673 if (zl_lib->sym_tab == NULL) {
674 status = -ENOMEM;
675 } else {
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);
683 if (err != 0) {
684 status = -EILSEQ;
685 } else {
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);
691 if (err != 0)
692 status = -EILSEQ;
694 zl_lib->dload_mod_obj = NULL;
697 func_cont:
698 if (!status) {
699 if (zl_lib->open_ref == 1) {
700 /* First time opened - insert in list */
701 if (zl_target->head)
702 (zl_target->head)->prev = zl_lib;
704 zl_lib->prev = NULL;
705 zl_lib->next = zl_target->head;
706 zl_target->head = zl_lib;
708 *lib_obj = (struct dbll_library_obj *)zl_lib;
709 } else {
710 *lib_obj = NULL;
711 if (zl_lib != NULL)
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);
721 return 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,
729 char *buf, u32 size)
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;
736 int status = 0;
738 DBC_REQUIRE(refs > 0);
739 DBC_REQUIRE(zl_lib);
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);
748 if (!status)
749 opened_doff = true;
751 } else {
752 (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp,
753 zl_lib->ul_pos,
754 SEEK_SET);
756 } else {
757 status = -EFAULT;
759 if (status)
760 goto func_cont;
762 byte_size = 1;
763 if (!dload_get_section_info(zl_lib->desc, name, &sect)) {
764 status = -ENXIO;
765 goto func_cont;
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)
774 ul_sect_size++;
776 /* Align size */
777 ul_sect_size = DOFF_ALIGN(ul_sect_size);
778 if (ul_sect_size > size) {
779 status = -EPERM;
780 } else {
781 if (!dload_get_section(zl_lib->desc, sect, buf))
782 status = -EBADF;
785 func_cont:
786 if (opened_doff) {
787 dof_close(zl_lib);
788 opened_doff = false;
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);
793 return 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;
818 s32 err = 0;
820 DBC_REQUIRE(refs > 0);
821 DBC_REQUIRE(zl_lib);
822 DBC_REQUIRE(zl_lib->load_ref > 0);
823 dev_dbg(bridge, "%s: lib: %p\n", __func__, lib);
824 zl_lib->load_ref--;
825 /* Unload only if reference count is 0 */
826 if (zl_lib->load_ref != 0)
827 goto func_end;
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);
835 if (err != 0)
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
844 * resources */
845 dof_close(zl_lib);
846 func_end:
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);
860 return -ENOSYS;
864 * ======== dof_close ========
866 static void dof_close(struct dbll_library_obj *zl_lib)
868 if (zl_lib->desc) {
869 dload_module_close(zl_lib->desc);
870 zl_lib->desc = NULL;
872 /* close file */
873 if (zl_lib->fp) {
874 (zl_lib->target_obj->attrs.fclose) (zl_lib->fp);
875 zl_lib->fp = NULL;
880 * ======== dof_open ========
882 static int dof_open(struct dbll_library_obj *zl_lib)
884 void *open = *(zl_lib->target_obj->attrs.fopen);
885 int status = 0;
887 /* First open the file for the dynamic loader, then open COF */
888 zl_lib->fp =
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,
894 SEEK_SET);
895 zl_lib->desc =
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);
900 zl_lib->fp = NULL;
901 status = -EBADF;
903 } else {
904 status = -EBADF;
907 return status;
911 * ======== name_hash ========
913 static u16 name_hash(void *key, u16 max_bucket)
915 u16 ret;
916 u16 hash;
917 char *name = (char *)key;
919 DBC_REQUIRE(name != NULL);
921 hash = 0;
923 while (*name) {
924 hash <<= 1;
925 hash ^= *name++;
928 ret = hash % max_bucket;
930 return ret;
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) ==
944 return true;
946 return false;
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)
955 return 1;
959 * ======== sym_delete ========
961 static void sym_delete(void *value)
963 struct dbll_symbol *sp = (struct dbll_symbol *)value;
965 kfree(sp->name);
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,
977 unsigned bufsize)
979 struct dbll_stream *pstream = (struct dbll_stream *)this;
980 struct dbll_library_obj *lib;
981 int bytes_read = 0;
983 DBC_REQUIRE(this != NULL);
984 lib = pstream->lib;
985 DBC_REQUIRE(lib);
987 if (lib != NULL) {
988 bytes_read =
989 (*(lib->target_obj->attrs.fread)) (buffer, 1, bufsize,
990 lib->fp);
992 return bytes_read;
996 * ======== dbll_set_file_posn ========
998 static int dbll_set_file_posn(struct dynamic_loader_stream *this,
999 unsigned int pos)
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);
1006 lib = pstream->lib;
1007 DBC_REQUIRE(lib);
1009 if (lib != NULL) {
1010 status = (*(lib->target_obj->attrs.fseek)) (lib->fp, (long)pos,
1011 SEEK_SET);
1014 return status;
1017 /* dynamic_loader_sym */
1020 * ======== dbll_find_symbol ========
1022 static struct dynload_symbol *dbll_find_symbol(struct dynamic_loader_sym *this,
1023 const char *name)
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);
1032 lib = ldr_sym->lib;
1033 DBC_REQUIRE(lib);
1035 if (lib != NULL) {
1036 if (lib->target_obj->attrs.sym_lookup) {
1037 /* Check current lib + base lib + dep lib +
1038 * persistent 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,
1043 &dbll_sym);
1044 } else {
1045 /* Just check current lib for symbol */
1046 status = dbll_get_addr((struct dbll_library_obj *)lib,
1047 (char *)name, &dbll_sym);
1048 if (!status) {
1049 status =
1050 dbll_get_c_addr((struct dbll_library_obj *)
1051 lib, (char *)name,
1052 &dbll_sym);
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;
1064 return ret_sym;
1068 * ======== find_in_symbol_table ========
1070 static struct dynload_symbol *find_in_symbol_table(struct dynamic_loader_sym
1071 *this, const char *name,
1072 unsigned moduleid)
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);
1080 lib = ldr_sym->lib;
1081 DBC_REQUIRE(lib);
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;
1087 return ret_sym;
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,
1095 unsigned module_id)
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);
1105 DBC_REQUIRE(name);
1106 lib = ldr_sym->lib;
1107 DBC_REQUIRE(lib);
1109 /* Check to see if symbol is already defined in symbol table */
1110 if (!(lib->target_obj->attrs.base_image)) {
1111 gbl_search = false;
1112 dbll_sym = dbll_find_symbol(this, name);
1113 gbl_search = true;
1114 if (dbll_sym) {
1115 redefined_symbol = true;
1116 dev_dbg(bridge, "%s already defined in symbol table\n",
1117 name);
1118 return NULL;
1121 /* Allocate string to copy symbol name */
1122 symbol.name = kzalloc(strlen((char *const)name) + 1, GFP_KERNEL);
1123 if (symbol.name == NULL)
1124 return 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 */
1132 sym_ptr =
1133 (struct dbll_symbol *)gh_insert(lib->sym_tab, (void *)name,
1134 (void *)&symbol);
1135 if (sym_ptr == NULL)
1136 kfree(symbol.name);
1139 if (sym_ptr != NULL)
1140 ret = (struct dynload_symbol *)&sym_ptr->value;
1141 else
1142 ret = NULL;
1144 return ret;
1148 * ======== dbll_purge_symbol_table ========
1150 static void dbll_purge_symbol_table(struct dynamic_loader_sym *this,
1151 unsigned module_id)
1153 struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this;
1154 struct dbll_library_obj *lib;
1156 DBC_REQUIRE(this != NULL);
1157 lib = ldr_sym->lib;
1158 DBC_REQUIRE(lib);
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;
1170 void *buf;
1172 DBC_REQUIRE(this != NULL);
1173 lib = ldr_sym->lib;
1174 DBC_REQUIRE(lib);
1176 buf = kzalloc(memsize, GFP_KERNEL);
1178 return buf;
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);
1190 lib = ldr_sym->lib;
1191 DBC_REQUIRE(lib);
1193 kfree(mem_ptr);
1197 * ======== dbll_err_report ========
1199 static void dbll_err_report(struct dynamic_loader_sym *this, const char *errstr,
1200 va_list args)
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);
1207 lib = ldr_sym->lib;
1208 DBC_REQUIRE(lib);
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;
1223 int status = 0;
1224 u32 mem_sect_type;
1225 struct rmm_addr rmm_addr_obj;
1226 s32 ret = true;
1227 unsigned stype = DLOAD_SECTION_TYPE(info->type);
1228 char *token = NULL;
1229 char *sz_sec_last_token = NULL;
1230 char *sz_last_token = NULL;
1231 char *sz_sect_name = NULL;
1232 char *psz_cur;
1233 s32 token_len = 0;
1234 s32 seg_id = -1;
1235 s32 req = -1;
1236 s32 count = 0;
1237 u32 alloc_size = 0;
1238 u32 run_addr_flag = 0;
1240 DBC_REQUIRE(this != NULL);
1241 lib = dbll_alloc_obj->lib;
1242 DBC_REQUIRE(lib);
1244 mem_sect_type =
1245 (stype == DLOAD_TEXT) ? DBLL_CODE : (stype ==
1246 DLOAD_BSS) ? DBLL_BSS :
1247 DBLL_DATA;
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) {
1260 status = -ENOMEM;
1261 goto func_cont;
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) */
1276 if (count >= 3)
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) {
1281 seg_id = 0;
1282 } else {
1283 if (strcmp(sz_sec_last_token, "DYN_SARAM") == 0) {
1284 seg_id = 1;
1285 } else {
1286 if (strcmp(sz_sec_last_token,
1287 "DYN_EXTERNAL") == 0)
1288 seg_id = 2;
1292 func_cont:
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;
1302 else
1303 alloc_size = info->size;
1305 if (info->load_addr != info->run_addr)
1306 run_addr_flag = 1;
1307 /* TODO - ideally, we can pass the alignment requirement also
1308 * from here */
1309 if (lib != NULL) {
1310 status =
1311 (lib->target_obj->attrs.alloc) (lib->target_obj->attrs.
1312 rmm_handle, mem_sect_type,
1313 alloc_size, align,
1314 (u32 *) &rmm_addr_obj,
1315 seg_id, req, false);
1317 if (status) {
1318 ret = false;
1319 } else {
1320 /* RMM gives word address. Need to convert to byte address */
1321 info->load_addr = rmm_addr_obj.addr * DSPWORDSIZE;
1322 if (!run_addr_flag)
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,
1329 info->load_addr);
1331 return ret;
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;
1342 u32 segid;
1343 int status = 0;
1344 unsigned stype = DLOAD_SECTION_TYPE(info->type);
1345 u32 mem_sect_type;
1346 u32 free_size = 0;
1348 mem_sect_type =
1349 (stype == DLOAD_TEXT) ? DBLL_CODE : (stype ==
1350 DLOAD_BSS) ? DBLL_BSS :
1351 DBLL_DATA;
1352 DBC_REQUIRE(this != NULL);
1353 lib = dbll_alloc_obj->lib;
1354 DBC_REQUIRE(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;
1359 else
1360 free_size = info->size;
1361 if (lib != NULL) {
1362 status =
1363 (lib->target_obj->attrs.free) (lib->target_obj->attrs.
1364 sym_handle, segid,
1365 info->load_addr /
1366 DSPWORDSIZE, free_size,
1367 false);
1371 /* dynamic_loader_initialize */
1373 * ======== connect ========
1375 static int connect(struct dynamic_loader_initialize *this)
1377 return true;
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,
1386 unsigned nbytes)
1388 struct dbll_init_obj *init_obj = (struct dbll_init_obj *)this;
1389 struct dbll_library_obj *lib;
1390 int bytes_read = 0;
1392 DBC_REQUIRE(this != NULL);
1393 lib = init_obj->lib;
1394 DBC_REQUIRE(lib);
1395 /* Need bridge_brd_read function */
1396 return bytes_read;
1400 * ======== write_mem ========
1402 static int write_mem(struct dynamic_loader_initialize *this, void *buf,
1403 ldr_addr addr, struct ldr_section_info *info,
1404 unsigned bytes)
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;
1410 u32 mem_sect_type;
1411 bool ret = true;
1413 DBC_REQUIRE(this != NULL);
1414 lib = init_obj->lib;
1415 if (!lib)
1416 return false;
1418 target_obj = lib->target_obj;
1420 mem_sect_type =
1421 (DLOAD_SECTION_TYPE(info->type) ==
1422 DLOAD_TEXT) ? DBLL_CODE : DBLL_DATA;
1423 if (target_obj && target_obj->attrs.write) {
1424 ret =
1425 (*target_obj->attrs.write) (target_obj->attrs.input_params,
1426 addr, buf, bytes,
1427 mem_sect_type);
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
1436 * another module */
1437 (*target_obj->attrs.log_write) (target_obj->attrs.
1438 log_write_handle,
1439 &sect_info, addr,
1440 bytes);
1443 return ret;
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)
1455 bool ret = true;
1456 char *pbuf;
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;
1462 pbuf = NULL;
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);
1469 if (pbuf)
1470 memset(pbuf, val, bytes);
1472 return ret;
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;
1482 bool ret = true;
1484 DBC_REQUIRE(this != NULL);
1485 lib = init_obj->lib;
1486 DBC_REQUIRE(lib);
1487 /* Save entry point */
1488 if (lib != NULL)
1489 lib->entry = (u32) start;
1491 return ret;
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
1506 * started.
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 {
1513 /* input */
1514 u32 address;
1515 u32 offset_range;
1516 /* state */
1517 u32 cur_best_offset;
1518 /* output */
1519 u32 sym_addr;
1520 char name[120];
1524 * find_symbol_callback() - Validates symbol address and copies the symbol name
1525 * to the user data.
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));
1549 return;
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,
1564 char *name_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]) {
1578 status = true;
1579 strcpy(name_output, context.name);
1580 *sym_addr_output = context.sym_addr;
1583 return status;
1585 #endif