staging: tidspbridge/pmgr: use strlcpy instead of strncpy
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / tidspbridge / pmgr / dbll.c
CommitLineData
c4ca3d5a
ORL
1/*
2 * dbll.c
3 *
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5 *
6 * Copyright (C) 2005-2006 Texas Instruments, Inc.
7 *
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.
11 *
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.
15 */
2094f12d 16#include <linux/types.h>
c4ca3d5a
ORL
17
18/* ----------------------------------- Host OS */
19#include <dspbridge/host_os.h>
20
21/* ----------------------------------- DSP/BIOS Bridge */
c4ca3d5a
ORL
22#include <dspbridge/dbdefs.h>
23
c4ca3d5a
ORL
24#include <dspbridge/gh.h>
25
26/* ----------------------------------- OS Adaptation Layer */
27
28/* Dynamic loader library interface */
29#include <dspbridge/dynamic_loader.h>
30#include <dspbridge/getsection.h>
31
32/* ----------------------------------- This */
33#include <dspbridge/dbll.h>
34#include <dspbridge/rmm.h>
35
36/* Number of buckets for symbol hash table */
37#define MAXBUCKETS 211
38
39/* Max buffer length */
40#define MAXEXPR 128
41
803cd75e 42#define DOFF_ALIGN(x) (((x) + 3) & ~3UL)
c4ca3d5a
ORL
43
44/*
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
48 * in a DOFF file.
49 */
50/*
51 * ======== dbll_tar_obj ========
52 */
53struct dbll_tar_obj {
54 struct dbll_attrs attrs;
55 struct dbll_library_obj *head; /* List of all opened libraries */
56};
57
58/*
59 * The following 4 typedefs are "super classes" of the dynamic loader
60 * library types used in dynamic loader functions (dynamic_loader.h).
61 */
62/*
63 * ======== dbll_stream ========
64 * Contains dynamic_loader_stream
65 */
66struct dbll_stream {
67 struct dynamic_loader_stream dl_stream;
68 struct dbll_library_obj *lib;
69};
70
71/*
72 * ======== ldr_symbol ========
73 */
74struct ldr_symbol {
75 struct dynamic_loader_sym dl_symbol;
76 struct dbll_library_obj *lib;
77};
78
79/*
80 * ======== dbll_alloc ========
81 */
82struct dbll_alloc {
83 struct dynamic_loader_allocate dl_alloc;
84 struct dbll_library_obj *lib;
85};
86
87/*
88 * ======== dbll_init_obj ========
89 */
90struct dbll_init_obj {
91 struct dynamic_loader_initialize dl_init;
92 struct dbll_library_obj *lib;
93};
94
95/*
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().
100 */
101
102/*
103 * ======== dbll_library_obj ========
104 */
105struct 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 */
109
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;
115 void *dload_mod_obj;
116
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 */
6c66e948 124 u32 pos;
c4ca3d5a
ORL
125};
126
127/*
128 * ======== dbll_symbol ========
129 */
130struct dbll_symbol {
131 struct dbll_sym_val value;
132 char *name;
133};
134
135static void dof_close(struct dbll_library_obj *zl_lib);
136static int dof_open(struct dbll_library_obj *zl_lib);
137static s32 no_op(struct dynamic_loader_initialize *thisptr, void *bufr,
c8c1ad8c
RS
138 ldr_addr locn, struct ldr_section_info *info,
139 unsigned bytsize);
c4ca3d5a
ORL
140
141/*
142 * Functions called by dynamic loader
143 *
144 */
145/* dynamic_loader_stream */
146static int dbll_read_buffer(struct dynamic_loader_stream *this, void *buffer,
147 unsigned bufsize);
148static int dbll_set_file_posn(struct dynamic_loader_stream *this,
149 unsigned int pos);
150/* dynamic_loader_sym */
151static struct dynload_symbol *dbll_find_symbol(struct dynamic_loader_sym *this,
152 const char *name);
153static struct dynload_symbol *dbll_add_to_symbol_table(struct dynamic_loader_sym
154 *this, const char *name,
95870a88 155 unsigned module_id);
c4ca3d5a
ORL
156static struct dynload_symbol *find_in_symbol_table(struct dynamic_loader_sym
157 *this, const char *name,
158 unsigned moduleid);
159static void dbll_purge_symbol_table(struct dynamic_loader_sym *this,
95870a88 160 unsigned module_id);
c4ca3d5a 161static void *allocate(struct dynamic_loader_sym *this, unsigned memsize);
95870a88 162static void deallocate(struct dynamic_loader_sym *this, void *mem_ptr);
c4ca3d5a
ORL
163static void dbll_err_report(struct dynamic_loader_sym *this, const char *errstr,
164 va_list args);
165/* dynamic_loader_allocate */
166static int dbll_rmm_alloc(struct dynamic_loader_allocate *this,
167 struct ldr_section_info *info, unsigned align);
168static void rmm_dealloc(struct dynamic_loader_allocate *this,
169 struct ldr_section_info *info);
170
171/* dynamic_loader_initialize */
172static int connect(struct dynamic_loader_initialize *this);
173static int read_mem(struct dynamic_loader_initialize *this, void *buf,
174 ldr_addr addr, struct ldr_section_info *info,
c8c1ad8c 175 unsigned bytes);
c4ca3d5a
ORL
176static int write_mem(struct dynamic_loader_initialize *this, void *buf,
177 ldr_addr addr, struct ldr_section_info *info,
178 unsigned nbytes);
179static int fill_mem(struct dynamic_loader_initialize *this, ldr_addr addr,
c8c1ad8c 180 struct ldr_section_info *info, unsigned bytes,
c4ca3d5a
ORL
181 unsigned val);
182static int execute(struct dynamic_loader_initialize *this, ldr_addr start);
183static void release(struct dynamic_loader_initialize *this);
184
185/* symbol table hash functions */
c8c1ad8c
RS
186static u16 name_hash(void *key, u16 max_bucket);
187static bool name_match(void *key, void *sp);
188static void sym_delete(void *value);
c4ca3d5a 189
c4ca3d5a
ORL
190/* Symbol Redefinition */
191static int redefined_symbol;
192static int gbl_search = 1;
193
194/*
195 * ======== dbll_close ========
196 */
197void dbll_close(struct dbll_library_obj *zl_lib)
198{
199 struct dbll_tar_obj *zl_target;
200
c4ca3d5a
ORL
201 zl_target = zl_lib->target_obj;
202 zl_lib->open_ref--;
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;
207
208 if (zl_lib->prev)
209 (zl_lib->prev)->next = zl_lib->next;
210
211 if (zl_lib->next)
212 (zl_lib->next)->prev = zl_lib->prev;
213
214 /* Free DOF resources */
215 dof_close(zl_lib);
216 kfree(zl_lib->file_name);
217
218 /* remove symbols from symbol table */
219 if (zl_lib->sym_tab)
220 gh_delete(zl_lib->sym_tab);
221
222 /* remove the library object itself */
223 kfree(zl_lib);
224 zl_lib = NULL;
225 }
226}
227
228/*
229 * ======== dbll_create ========
230 */
231int dbll_create(struct dbll_tar_obj **target_obj,
232 struct dbll_attrs *pattrs)
233{
234 struct dbll_tar_obj *pzl_target;
235 int status = 0;
236
c4ca3d5a
ORL
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) {
241 *target_obj = NULL;
242 status = -ENOMEM;
243 } else {
244 pzl_target->attrs = *pattrs;
245 *target_obj = (struct dbll_tar_obj *)pzl_target;
246 }
c4ca3d5a
ORL
247 }
248
249 return status;
250}
251
252/*
253 * ======== dbll_delete ========
254 */
255void dbll_delete(struct dbll_tar_obj *target)
256{
257 struct dbll_tar_obj *zl_target = (struct dbll_tar_obj *)target;
258
9f7ff701 259 kfree(zl_target);
c4ca3d5a
ORL
260
261}
262
263/*
264 * ======== dbll_exit ========
265 * Discontinue usage of DBL module.
266 */
267void dbll_exit(void)
268{
d111f6e9 269 /* do nothing */
c4ca3d5a
ORL
270}
271
272/*
273 * ======== dbll_get_addr ========
274 * Get address of name in the specified library.
275 */
276bool dbll_get_addr(struct dbll_library_obj *zl_lib, char *name,
13b18c29 277 struct dbll_sym_val **sym_val)
c4ca3d5a
ORL
278{
279 struct dbll_symbol *sym;
280 bool status = false;
281
c4ca3d5a
ORL
282 sym = (struct dbll_symbol *)gh_find(zl_lib->sym_tab, name);
283 if (sym != NULL) {
13b18c29 284 *sym_val = &sym->value;
c4ca3d5a
ORL
285 status = true;
286 }
287
288 dev_dbg(bridge, "%s: lib: %p name: %s paddr: %p, status 0x%x\n",
13b18c29 289 __func__, zl_lib, name, sym_val, status);
c4ca3d5a
ORL
290 return status;
291}
292
293/*
294 * ======== dbll_get_attrs ========
295 * Retrieve the attributes of the target.
296 */
297void dbll_get_attrs(struct dbll_tar_obj *target, struct dbll_attrs *pattrs)
298{
299 struct dbll_tar_obj *zl_target = (struct dbll_tar_obj *)target;
300
c4ca3d5a
ORL
301 if ((pattrs != NULL) && (zl_target != NULL))
302 *pattrs = zl_target->attrs;
303
304}
305
306/*
307 * ======== dbll_get_c_addr ========
308 * Get address of a "C" name in the specified library.
309 */
310bool dbll_get_c_addr(struct dbll_library_obj *zl_lib, char *name,
13b18c29 311 struct dbll_sym_val **sym_val)
c4ca3d5a
ORL
312{
313 struct dbll_symbol *sym;
314 char cname[MAXEXPR + 1];
315 bool status = false;
316
c4ca3d5a
ORL
317 cname[0] = '_';
318
319 strncpy(cname + 1, name, sizeof(cname) - 2);
320 cname[MAXEXPR] = '\0'; /* insure '\0' string termination */
321
322 /* Check for C name, if not found */
323 sym = (struct dbll_symbol *)gh_find(zl_lib->sym_tab, cname);
324
325 if (sym != NULL) {
13b18c29 326 *sym_val = &sym->value;
c4ca3d5a
ORL
327 status = true;
328 }
329
330 return status;
331}
332
333/*
334 * ======== dbll_get_sect ========
335 * Get the base address and size (in bytes) of a COFF section.
336 */
337int dbll_get_sect(struct dbll_library_obj *lib, char *name, u32 *paddr,
338 u32 *psize)
339{
340 u32 byte_size;
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;
344 int status = 0;
345
c4ca3d5a
ORL
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);
157990f0 350 if (!status)
c4ca3d5a
ORL
351 opened_doff = true;
352
353 } else {
354 (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp,
6c66e948 355 zl_lib->pos,
c4ca3d5a
ORL
356 SEEK_SET);
357 }
358 } else {
359 status = -EFAULT;
360 }
157990f0 361 if (!status) {
c4ca3d5a
ORL
362 byte_size = 1;
363 if (dload_get_section_info(zl_lib->desc, name, &sect)) {
364 *paddr = sect->load_addr;
365 *psize = sect->size * byte_size;
366 /* Make sure size is even for good swap */
367 if (*psize % 2)
368 (*psize)++;
369
370 /* Align size */
371 *psize = DOFF_ALIGN(*psize);
372 } else {
373 status = -ENXIO;
374 }
375 }
376 if (opened_doff) {
377 dof_close(zl_lib);
378 opened_doff = false;
379 }
380
381 dev_dbg(bridge, "%s: lib: %p name: %s paddr: %p psize: %p, "
382 "status 0x%x\n", __func__, lib, name, paddr, psize, status);
383
384 return status;
385}
386
387/*
388 * ======== dbll_init ========
389 */
390bool dbll_init(void)
391{
d111f6e9 392 /* do nothing */
c4ca3d5a
ORL
393
394 return true;
395}
396
397/*
398 * ======== dbll_load ========
399 */
400int dbll_load(struct dbll_library_obj *lib, dbll_flags flags,
a5120278 401 struct dbll_attrs *attrs, u32 *entry)
c4ca3d5a
ORL
402{
403 struct dbll_library_obj *zl_lib = (struct dbll_library_obj *)lib;
404 struct dbll_tar_obj *dbzl;
405 bool got_symbols = true;
406 s32 err;
407 int status = 0;
408 bool opened_doff = false;
c4ca3d5a
ORL
409
410 /*
411 * Load if not already loaded.
412 */
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) {
418 got_symbols = false;
419 zl_lib->sym_tab = gh_create(MAXBUCKETS,
420 sizeof(struct dbll_symbol),
421 name_hash,
422 name_match, sym_delete);
423 if (zl_lib->sym_tab == NULL)
424 status = -ENOMEM;
425
426 }
427 /*
428 * Set up objects needed by the dynamic loader
429 */
430 /* Stream */
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;
434 /* Symbol */
435 zl_lib->symbol.dl_symbol.find_matching_symbol =
436 dbll_find_symbol;
437 if (got_symbols) {
438 zl_lib->symbol.dl_symbol.add_to_symbol_table =
439 find_in_symbol_table;
440 } else {
441 zl_lib->symbol.dl_symbol.add_to_symbol_table =
442 dbll_add_to_symbol_table;
443 }
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;
450 /* Allocate */
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;
454 /* Init */
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);
157990f0 465 if (!status)
c4ca3d5a
ORL
466 opened_doff = true;
467
468 }
157990f0 469 if (!status) {
6c66e948 470 zl_lib->pos = (*(zl_lib->target_obj->attrs.ftell))
c4ca3d5a
ORL
471 (zl_lib->fp);
472 /* Reset file cursor */
473 (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp,
474 (long)0,
475 SEEK_SET);
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,
485 DLOAD_INITBSS,
486 &zl_lib->dload_mod_obj);
487
488 if (err != 0) {
489 status = -EILSEQ;
490 } else if (redefined_symbol) {
491 zl_lib->load_ref++;
492 dbll_unload(zl_lib, (struct dbll_attrs *)attrs);
493 redefined_symbol = false;
494 status = -EILSEQ;
495 } else {
a5120278 496 *entry = zl_lib->entry;
c4ca3d5a
ORL
497 }
498 }
499 }
157990f0 500 if (!status)
c4ca3d5a
ORL
501 zl_lib->load_ref++;
502
503 /* Clean up DOFF resources */
504 if (opened_doff)
505 dof_close(zl_lib);
506
a5120278
RS
507 dev_dbg(bridge, "%s: lib: %p flags: 0x%x entry: %p, status 0x%x\n",
508 __func__, lib, flags, entry, status);
c4ca3d5a
ORL
509
510 return status;
511}
512
c4ca3d5a
ORL
513/*
514 * ======== dbll_open ========
515 */
516int dbll_open(struct dbll_tar_obj *target, char *file, dbll_flags flags,
daa89e6c 517 struct dbll_library_obj **lib_obj)
c4ca3d5a
ORL
518{
519 struct dbll_tar_obj *zl_target = (struct dbll_tar_obj *)target;
520 struct dbll_library_obj *zl_lib = NULL;
521 s32 err;
522 int status = 0;
523
c4ca3d5a
ORL
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 */
528 zl_lib->open_ref++;
529 break;
530 }
531 zl_lib = zl_lib->next;
532 }
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) {
537 status = -ENOMEM;
538 } else {
6c66e948 539 zl_lib->pos = 0;
c4ca3d5a
ORL
540 /* Increment ref count to allow close on failure
541 * later on */
542 zl_lib->open_ref++;
543 zl_lib->target_obj = zl_target;
544 /* Keep a copy of the file name */
545 zl_lib->file_name = kzalloc(strlen(file) + 1,
546 GFP_KERNEL);
547 if (zl_lib->file_name == NULL) {
548 status = -ENOMEM;
549 } else {
550 strncpy(zl_lib->file_name, file,
551 strlen(file) + 1);
552 }
553 zl_lib->sym_tab = NULL;
554 }
555 }
556 /*
557 * Set up objects needed by the dynamic loader
558 */
51d5e099 559 if (status)
c4ca3d5a
ORL
560 goto func_cont;
561
562 /* Stream */
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;
566 /* Symbol */
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;
574 /* Allocate */
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;
578 /* Init */
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;
157990f0 586 if (!status && zl_lib->fp == NULL)
c4ca3d5a
ORL
587 status = dof_open(zl_lib);
588
6c66e948 589 zl_lib->pos = (*(zl_lib->target_obj->attrs.ftell)) (zl_lib->fp);
c4ca3d5a
ORL
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))
593 goto func_cont;
594
595 zl_lib->sym_tab =
596 gh_create(MAXBUCKETS, sizeof(struct dbll_symbol), name_hash,
597 name_match, sym_delete);
598 if (zl_lib->sym_tab == NULL) {
599 status = -ENOMEM;
600 } else {
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);
608 if (err != 0) {
609 status = -EILSEQ;
610 } else {
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);
616 if (err != 0)
617 status = -EILSEQ;
618
619 zl_lib->dload_mod_obj = NULL;
620 }
621 }
622func_cont:
157990f0 623 if (!status) {
c4ca3d5a
ORL
624 if (zl_lib->open_ref == 1) {
625 /* First time opened - insert in list */
626 if (zl_target->head)
627 (zl_target->head)->prev = zl_lib;
628
629 zl_lib->prev = NULL;
630 zl_lib->next = zl_target->head;
631 zl_target->head = zl_lib;
632 }
daa89e6c 633 *lib_obj = (struct dbll_library_obj *)zl_lib;
c4ca3d5a 634 } else {
daa89e6c 635 *lib_obj = NULL;
c4ca3d5a
ORL
636 if (zl_lib != NULL)
637 dbll_close((struct dbll_library_obj *)zl_lib);
638
639 }
c4ca3d5a 640
daa89e6c
RS
641 dev_dbg(bridge, "%s: target: %p file: %s lib_obj: %p, status 0x%x\n",
642 __func__, target, file, lib_obj, status);
c4ca3d5a
ORL
643
644 return status;
645}
646
647/*
648 * ======== dbll_read_sect ========
649 * Get the content of a COFF section.
650 */
651int dbll_read_sect(struct dbll_library_obj *lib, char *name,
c8c1ad8c 652 char *buf, u32 size)
c4ca3d5a
ORL
653{
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;
659 int status = 0;
660
c4ca3d5a
ORL
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);
157990f0 665 if (!status)
c4ca3d5a
ORL
666 opened_doff = true;
667
668 } else {
669 (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp,
6c66e948 670 zl_lib->pos,
c4ca3d5a
ORL
671 SEEK_SET);
672 }
673 } else {
674 status = -EFAULT;
675 }
51d5e099 676 if (status)
c4ca3d5a
ORL
677 goto func_cont;
678
679 byte_size = 1;
680 if (!dload_get_section_info(zl_lib->desc, name, &sect)) {
681 status = -ENXIO;
682 goto func_cont;
683 }
684 /*
685 * Ensure the supplied buffer size is sufficient to store
c8c1ad8c 686 * the section buf to be read.
c4ca3d5a
ORL
687 */
688 ul_sect_size = sect->size * byte_size;
689 /* Make sure size is even for good swap */
690 if (ul_sect_size % 2)
691 ul_sect_size++;
692
693 /* Align size */
694 ul_sect_size = DOFF_ALIGN(ul_sect_size);
695 if (ul_sect_size > size) {
696 status = -EPERM;
697 } else {
c8c1ad8c 698 if (!dload_get_section(zl_lib->desc, sect, buf))
c4ca3d5a
ORL
699 status = -EBADF;
700
701 }
702func_cont:
703 if (opened_doff) {
704 dof_close(zl_lib);
705 opened_doff = false;
706 }
707
c8c1ad8c
RS
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);
c4ca3d5a
ORL
710 return status;
711}
712
c4ca3d5a
ORL
713/*
714 * ======== dbll_unload ========
715 */
716void dbll_unload(struct dbll_library_obj *lib, struct dbll_attrs *attrs)
717{
718 struct dbll_library_obj *zl_lib = (struct dbll_library_obj *)lib;
719 s32 err = 0;
720
c4ca3d5a
ORL
721 dev_dbg(bridge, "%s: lib: %p\n", __func__, lib);
722 zl_lib->load_ref--;
723 /* Unload only if reference count is 0 */
724 if (zl_lib->load_ref != 0)
276cc746 725 return;
c4ca3d5a
ORL
726
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);
733 if (err != 0)
734 dev_dbg(bridge, "%s: failed: 0x%x\n", __func__, err);
735 }
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;
740 }
741 /* delete DOFF desc since it holds *lots* of host OS
742 * resources */
743 dof_close(zl_lib);
c4ca3d5a
ORL
744}
745
c4ca3d5a
ORL
746/*
747 * ======== dof_close ========
748 */
749static void dof_close(struct dbll_library_obj *zl_lib)
750{
751 if (zl_lib->desc) {
752 dload_module_close(zl_lib->desc);
753 zl_lib->desc = NULL;
754 }
755 /* close file */
756 if (zl_lib->fp) {
757 (zl_lib->target_obj->attrs.fclose) (zl_lib->fp);
758 zl_lib->fp = NULL;
759 }
760}
761
762/*
763 * ======== dof_open ========
764 */
765static int dof_open(struct dbll_library_obj *zl_lib)
766{
767 void *open = *(zl_lib->target_obj->attrs.fopen);
768 int status = 0;
769
770 /* First open the file for the dynamic loader, then open COF */
771 zl_lib->fp =
772 (void *)((dbll_f_open_fxn) (open)) (zl_lib->file_name, "rb");
773
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,
777 SEEK_SET);
778 zl_lib->desc =
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);
783 zl_lib->fp = NULL;
784 status = -EBADF;
785 }
786 } else {
787 status = -EBADF;
788 }
789
790 return status;
791}
792
793/*
794 * ======== name_hash ========
795 */
796static u16 name_hash(void *key, u16 max_bucket)
797{
798 u16 ret;
799 u16 hash;
800 char *name = (char *)key;
801
c4ca3d5a
ORL
802 hash = 0;
803
804 while (*name) {
805 hash <<= 1;
806 hash ^= *name++;
807 }
808
809 ret = hash % max_bucket;
810
811 return ret;
812}
813
814/*
815 * ======== name_match ========
816 */
c8c1ad8c 817static bool name_match(void *key, void *sp)
c4ca3d5a 818{
c8c1ad8c
RS
819 if ((key != NULL) && (sp != NULL)) {
820 if (strcmp((char *)key, ((struct dbll_symbol *)sp)->name) ==
c4ca3d5a
ORL
821 0)
822 return true;
823 }
824 return false;
825}
826
827/*
828 * ======== no_op ========
829 */
830static int no_op(struct dynamic_loader_initialize *thisptr, void *bufr,
831 ldr_addr locn, struct ldr_section_info *info, unsigned bytsize)
832{
833 return 1;
834}
835
836/*
837 * ======== sym_delete ========
838 */
839static void sym_delete(void *value)
840{
841 struct dbll_symbol *sp = (struct dbll_symbol *)value;
842
843 kfree(sp->name);
844}
845
846/*
847 * Dynamic Loader Functions
848 */
849
850/* dynamic_loader_stream */
851/*
852 * ======== dbll_read_buffer ========
853 */
854static int dbll_read_buffer(struct dynamic_loader_stream *this, void *buffer,
855 unsigned bufsize)
856{
857 struct dbll_stream *pstream = (struct dbll_stream *)this;
858 struct dbll_library_obj *lib;
859 int bytes_read = 0;
860
c4ca3d5a 861 lib = pstream->lib;
c4ca3d5a
ORL
862 if (lib != NULL) {
863 bytes_read =
864 (*(lib->target_obj->attrs.fread)) (buffer, 1, bufsize,
865 lib->fp);
866 }
867 return bytes_read;
868}
869
870/*
871 * ======== dbll_set_file_posn ========
872 */
873static int dbll_set_file_posn(struct dynamic_loader_stream *this,
874 unsigned int pos)
875{
876 struct dbll_stream *pstream = (struct dbll_stream *)this;
877 struct dbll_library_obj *lib;
878 int status = 0; /* Success */
879
c4ca3d5a 880 lib = pstream->lib;
c4ca3d5a
ORL
881 if (lib != NULL) {
882 status = (*(lib->target_obj->attrs.fseek)) (lib->fp, (long)pos,
883 SEEK_SET);
884 }
885
886 return status;
887}
888
889/* dynamic_loader_sym */
890
891/*
892 * ======== dbll_find_symbol ========
893 */
894static struct dynload_symbol *dbll_find_symbol(struct dynamic_loader_sym *this,
895 const char *name)
896{
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 */
902
c4ca3d5a 903 lib = ldr_sym->lib;
c4ca3d5a
ORL
904 if (lib != NULL) {
905 if (lib->target_obj->attrs.sym_lookup) {
906 /* Check current lib + base lib + dep lib +
907 * persistent 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,
912 &dbll_sym);
913 } else {
914 /* Just check current lib for symbol */
915 status = dbll_get_addr((struct dbll_library_obj *)lib,
916 (char *)name, &dbll_sym);
917 if (!status) {
918 status =
919 dbll_get_c_addr((struct dbll_library_obj *)
920 lib, (char *)name,
921 &dbll_sym);
922 }
923 }
924 }
925
926 if (!status && gbl_search)
927 dev_dbg(bridge, "%s: Symbol not found: %s\n", __func__, name);
928
c4ca3d5a
ORL
929 ret_sym = (struct dynload_symbol *)dbll_sym;
930 return ret_sym;
931}
932
933/*
934 * ======== find_in_symbol_table ========
935 */
936static struct dynload_symbol *find_in_symbol_table(struct dynamic_loader_sym
937 *this, const char *name,
938 unsigned moduleid)
939{
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;
944
c4ca3d5a 945 lib = ldr_sym->lib;
c4ca3d5a
ORL
946 sym = (struct dbll_symbol *)gh_find(lib->sym_tab, (char *)name);
947
948 ret_sym = (struct dynload_symbol *)&sym->value;
949 return ret_sym;
950}
951
952/*
953 * ======== dbll_add_to_symbol_table ========
954 */
955static struct dynload_symbol *dbll_add_to_symbol_table(struct dynamic_loader_sym
956 *this, const char *name,
95870a88 957 unsigned module_id)
c4ca3d5a
ORL
958{
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;
965
c4ca3d5a 966 lib = ldr_sym->lib;
c4ca3d5a
ORL
967
968 /* Check to see if symbol is already defined in symbol table */
969 if (!(lib->target_obj->attrs.base_image)) {
970 gbl_search = false;
971 dbll_sym = dbll_find_symbol(this, name);
972 gbl_search = true;
973 if (dbll_sym) {
974 redefined_symbol = true;
975 dev_dbg(bridge, "%s already defined in symbol table\n",
976 name);
977 return NULL;
978 }
979 }
980 /* Allocate string to copy symbol name */
981 symbol.name = kzalloc(strlen((char *const)name) + 1, GFP_KERNEL);
982 if (symbol.name == NULL)
983 return NULL;
984
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);
989
990 /* Add symbol to symbol table */
991 sym_ptr =
992 (struct dbll_symbol *)gh_insert(lib->sym_tab, (void *)name,
993 (void *)&symbol);
994 if (sym_ptr == NULL)
995 kfree(symbol.name);
996
997 }
998 if (sym_ptr != NULL)
999 ret = (struct dynload_symbol *)&sym_ptr->value;
1000 else
1001 ret = NULL;
1002
1003 return ret;
1004}
1005
1006/*
1007 * ======== dbll_purge_symbol_table ========
1008 */
1009static void dbll_purge_symbol_table(struct dynamic_loader_sym *this,
95870a88 1010 unsigned module_id)
c4ca3d5a
ORL
1011{
1012 struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this;
1013 struct dbll_library_obj *lib;
1014
c4ca3d5a 1015 lib = ldr_sym->lib;
c4ca3d5a
ORL
1016 /* May not need to do anything */
1017}
1018
1019/*
1020 * ======== allocate ========
1021 */
1022static void *allocate(struct dynamic_loader_sym *this, unsigned memsize)
1023{
1024 struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this;
1025 struct dbll_library_obj *lib;
1026 void *buf;
1027
c4ca3d5a 1028 lib = ldr_sym->lib;
c4ca3d5a
ORL
1029
1030 buf = kzalloc(memsize, GFP_KERNEL);
1031
1032 return buf;
1033}
1034
1035/*
1036 * ======== deallocate ========
1037 */
95870a88 1038static void deallocate(struct dynamic_loader_sym *this, void *mem_ptr)
c4ca3d5a
ORL
1039{
1040 struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this;
1041 struct dbll_library_obj *lib;
1042
c4ca3d5a 1043 lib = ldr_sym->lib;
c4ca3d5a 1044
95870a88 1045 kfree(mem_ptr);
c4ca3d5a
ORL
1046}
1047
1048/*
1049 * ======== dbll_err_report ========
1050 */
1051static void dbll_err_report(struct dynamic_loader_sym *this, const char *errstr,
1052 va_list args)
1053{
1054 struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this;
1055 struct dbll_library_obj *lib;
1056 char temp_buf[MAXEXPR];
1057
c4ca3d5a 1058 lib = ldr_sym->lib;
c4ca3d5a
ORL
1059 vsnprintf((char *)temp_buf, MAXEXPR, (char *)errstr, args);
1060 dev_dbg(bridge, "%s\n", temp_buf);
1061}
1062
1063/* dynamic_loader_allocate */
1064
1065/*
1066 * ======== dbll_rmm_alloc ========
1067 */
1068static int dbll_rmm_alloc(struct dynamic_loader_allocate *this,
1069 struct ldr_section_info *info, unsigned align)
1070{
1071 struct dbll_alloc *dbll_alloc_obj = (struct dbll_alloc *)this;
1072 struct dbll_library_obj *lib;
1073 int status = 0;
1074 u32 mem_sect_type;
1075 struct rmm_addr rmm_addr_obj;
5e768067 1076 s32 ret = true;
c4ca3d5a
ORL
1077 unsigned stype = DLOAD_SECTION_TYPE(info->type);
1078 char *token = NULL;
1079 char *sz_sec_last_token = NULL;
1080 char *sz_last_token = NULL;
1081 char *sz_sect_name = NULL;
1082 char *psz_cur;
1083 s32 token_len = 0;
1084 s32 seg_id = -1;
1085 s32 req = -1;
1086 s32 count = 0;
1087 u32 alloc_size = 0;
1088 u32 run_addr_flag = 0;
1089
c4ca3d5a 1090 lib = dbll_alloc_obj->lib;
c4ca3d5a
ORL
1091
1092 mem_sect_type =
1093 (stype == DLOAD_TEXT) ? DBLL_CODE : (stype ==
1094 DLOAD_BSS) ? DBLL_BSS :
1095 DBLL_DATA;
1096
1097 /* Attempt to extract the segment ID and requirement information from
1098 the name of the section */
c4ca3d5a
ORL
1099 token_len = strlen((char *)(info->name)) + 1;
1100
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);
1104
1105 if (sz_sect_name == NULL || sz_sec_last_token == NULL ||
1106 sz_last_token == NULL) {
1107 status = -ENOMEM;
1108 goto func_cont;
1109 }
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 */
1118 }
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) */
1123 if (count >= 3)
1124 strict_strtol(sz_last_token, 10, (long *)&req);
1125
1126 if ((req == 0) || (req == 1)) {
1127 if (strcmp(sz_sec_last_token, "DYN_DARAM") == 0) {
1128 seg_id = 0;
1129 } else {
1130 if (strcmp(sz_sec_last_token, "DYN_SARAM") == 0) {
1131 seg_id = 1;
1132 } else {
1133 if (strcmp(sz_sec_last_token,
1134 "DYN_EXTERNAL") == 0)
1135 seg_id = 2;
1136 }
1137 }
1138 }
1139func_cont:
1140 kfree(sz_sect_name);
1141 sz_sect_name = NULL;
1142 kfree(sz_last_token);
1143 sz_last_token = NULL;
1144 kfree(sz_sec_last_token);
1145 sz_sec_last_token = NULL;
1146
1147 if (mem_sect_type == DBLL_CODE)
1148 alloc_size = info->size + GEM_L1P_PREFETCH_SIZE;
1149 else
1150 alloc_size = info->size;
1151
1152 if (info->load_addr != info->run_addr)
1153 run_addr_flag = 1;
1154 /* TODO - ideally, we can pass the alignment requirement also
1155 * from here */
1156 if (lib != NULL) {
1157 status =
1158 (lib->target_obj->attrs.alloc) (lib->target_obj->attrs.
1159 rmm_handle, mem_sect_type,
1160 alloc_size, align,
1161 (u32 *) &rmm_addr_obj,
5e768067 1162 seg_id, req, false);
c4ca3d5a 1163 }
51d5e099 1164 if (status) {
c4ca3d5a
ORL
1165 ret = false;
1166 } else {
1167 /* RMM gives word address. Need to convert to byte address */
1168 info->load_addr = rmm_addr_obj.addr * DSPWORDSIZE;
1169 if (!run_addr_flag)
1170 info->run_addr = info->load_addr;
1171 info->context = (u32) rmm_addr_obj.segid;
1172 dev_dbg(bridge, "%s: %s base = 0x%x len = 0x%x, "
1173 "info->run_addr 0x%x, info->load_addr 0x%x\n",
1174 __func__, info->name, info->load_addr / DSPWORDSIZE,
1175 info->size / DSPWORDSIZE, info->run_addr,
1176 info->load_addr);
1177 }
1178 return ret;
1179}
1180
1181/*
1182 * ======== rmm_dealloc ========
1183 */
1184static void rmm_dealloc(struct dynamic_loader_allocate *this,
1185 struct ldr_section_info *info)
1186{
1187 struct dbll_alloc *dbll_alloc_obj = (struct dbll_alloc *)this;
1188 struct dbll_library_obj *lib;
1189 u32 segid;
1190 int status = 0;
1191 unsigned stype = DLOAD_SECTION_TYPE(info->type);
1192 u32 mem_sect_type;
1193 u32 free_size = 0;
1194
1195 mem_sect_type =
1196 (stype == DLOAD_TEXT) ? DBLL_CODE : (stype ==
1197 DLOAD_BSS) ? DBLL_BSS :
1198 DBLL_DATA;
c4ca3d5a 1199 lib = dbll_alloc_obj->lib;
c4ca3d5a
ORL
1200 /* segid was set by alloc function */
1201 segid = (u32) info->context;
1202 if (mem_sect_type == DBLL_CODE)
1203 free_size = info->size + GEM_L1P_PREFETCH_SIZE;
1204 else
1205 free_size = info->size;
1206 if (lib != NULL) {
1207 status =
1208 (lib->target_obj->attrs.free) (lib->target_obj->attrs.
1209 sym_handle, segid,
1210 info->load_addr /
1211 DSPWORDSIZE, free_size,
1212 false);
1213 }
1214}
1215
1216/* dynamic_loader_initialize */
1217/*
1218 * ======== connect ========
1219 */
1220static int connect(struct dynamic_loader_initialize *this)
1221{
1222 return true;
1223}
1224
1225/*
1226 * ======== read_mem ========
1227 * This function does not need to be implemented.
1228 */
1229static int read_mem(struct dynamic_loader_initialize *this, void *buf,
1230 ldr_addr addr, struct ldr_section_info *info,
1231 unsigned nbytes)
1232{
1233 struct dbll_init_obj *init_obj = (struct dbll_init_obj *)this;
1234 struct dbll_library_obj *lib;
1235 int bytes_read = 0;
1236
c4ca3d5a 1237 lib = init_obj->lib;
c4ca3d5a
ORL
1238 /* Need bridge_brd_read function */
1239 return bytes_read;
1240}
1241
1242/*
1243 * ======== write_mem ========
1244 */
1245static int write_mem(struct dynamic_loader_initialize *this, void *buf,
1246 ldr_addr addr, struct ldr_section_info *info,
1247 unsigned bytes)
1248{
1249 struct dbll_init_obj *init_obj = (struct dbll_init_obj *)this;
1250 struct dbll_library_obj *lib;
1251 struct dbll_tar_obj *target_obj;
1252 struct dbll_sect_info sect_info;
1253 u32 mem_sect_type;
1254 bool ret = true;
1255
c4ca3d5a
ORL
1256 lib = init_obj->lib;
1257 if (!lib)
1258 return false;
1259
1260 target_obj = lib->target_obj;
1261
1262 mem_sect_type =
1263 (DLOAD_SECTION_TYPE(info->type) ==
1264 DLOAD_TEXT) ? DBLL_CODE : DBLL_DATA;
1265 if (target_obj && target_obj->attrs.write) {
1266 ret =
1267 (*target_obj->attrs.write) (target_obj->attrs.input_params,
1268 addr, buf, bytes,
1269 mem_sect_type);
1270
1271 if (target_obj->attrs.log_write) {
1272 sect_info.name = info->name;
1273 sect_info.sect_run_addr = info->run_addr;
1274 sect_info.sect_load_addr = info->load_addr;
1275 sect_info.size = info->size;
1276 sect_info.type = mem_sect_type;
1277 /* Pass the information about what we've written to
1278 * another module */
1279 (*target_obj->attrs.log_write) (target_obj->attrs.
1280 log_write_handle,
1281 &sect_info, addr,
1282 bytes);
1283 }
1284 }
1285 return ret;
1286}
1287
1288/*
1289 * ======== fill_mem ========
1290 * Fill bytes of memory at a given address with a given value by
1291 * writing from a buffer containing the given value. Write in
1292 * sets of MAXEXPR (128) bytes to avoid large stack buffer issues.
1293 */
1294static int fill_mem(struct dynamic_loader_initialize *this, ldr_addr addr,
1295 struct ldr_section_info *info, unsigned bytes, unsigned val)
1296{
1297 bool ret = true;
1298 char *pbuf;
1299 struct dbll_library_obj *lib;
1300 struct dbll_init_obj *init_obj = (struct dbll_init_obj *)this;
1301
c4ca3d5a
ORL
1302 lib = init_obj->lib;
1303 pbuf = NULL;
1304 /* Pass the NULL pointer to write_mem to get the start address of Shared
1305 memory. This is a trick to just get the start address, there is no
1306 writing taking place with this Writemem
1307 */
1308 if ((lib->target_obj->attrs.write) != (dbll_write_fxn) no_op)
1309 write_mem(this, &pbuf, addr, info, 0);
1310 if (pbuf)
1311 memset(pbuf, val, bytes);
1312
1313 return ret;
1314}
1315
1316/*
1317 * ======== execute ========
1318 */
1319static int execute(struct dynamic_loader_initialize *this, ldr_addr start)
1320{
1321 struct dbll_init_obj *init_obj = (struct dbll_init_obj *)this;
1322 struct dbll_library_obj *lib;
1323 bool ret = true;
1324
c4ca3d5a 1325 lib = init_obj->lib;
c4ca3d5a
ORL
1326 /* Save entry point */
1327 if (lib != NULL)
1328 lib->entry = (u32) start;
1329
1330 return ret;
1331}
1332
1333/*
1334 * ======== release ========
1335 */
1336static void release(struct dynamic_loader_initialize *this)
1337{
1338}
1339
4f551c8f 1340#ifdef CONFIG_TIDSPBRIDGE_BACKTRACE
c4ca3d5a
ORL
1341/**
1342 * find_symbol_context - Basic symbol context structure
25a606c3 1343 * @address: Symbol Address
c4ca3d5a
ORL
1344 * @offset_range: Offset range where the search for the DSP symbol
1345 * started.
1346 * @cur_best_offset: Best offset to start looking for the DSP symbol
1347 * @sym_addr: Address of the DSP symbol
1348 * @name: Symbol name
1349 *
1350 */
1351struct find_symbol_context {
1352 /* input */
1353 u32 address;
1354 u32 offset_range;
1355 /* state */
1356 u32 cur_best_offset;
1357 /* output */
1358 u32 sym_addr;
1359 char name[120];
1360};
1361
1362/**
1363 * find_symbol_callback() - Validates symbol address and copies the symbol name
1364 * to the user data.
1365 * @elem: dsp library context
1366 * @user_data: Find symbol context
1367 *
1368 */
1369void find_symbol_callback(void *elem, void *user_data)
1370{
1371 struct dbll_symbol *symbol = elem;
1372 struct find_symbol_context *context = user_data;
1373 u32 symbol_addr = symbol->value.value;
1374 u32 offset = context->address - symbol_addr;
1375
1376 /*
1377 * Address given should be greater than symbol address,
1378 * symbol address should be within specified range
1379 * and the offset should be better than previous one
1380 */
1381 if (context->address >= symbol_addr && symbol_addr < (u32)-1 &&
1382 offset < context->cur_best_offset) {
1383 context->cur_best_offset = offset;
1384 context->sym_addr = symbol_addr;
9814a875 1385 strlcpy(context->name, symbol->name, sizeof(context->name));
c4ca3d5a
ORL
1386 }
1387
1388 return;
1389}
1390
1391/**
1392 * dbll_find_dsp_symbol() - This function retrieves the dsp symbol from the dsp binary.
1393 * @zl_lib: DSP binary obj library pointer
1394 * @address: Given address to find the dsp symbol
1395 * @offset_range: offset range to look for dsp symbol
1396 * @sym_addr_output: Symbol Output address
1397 * @name_output: String with the dsp symbol
1398 *
1399 * This function retrieves the dsp symbol from the dsp binary.
1400 */
1401bool dbll_find_dsp_symbol(struct dbll_library_obj *zl_lib, u32 address,
1402 u32 offset_range, u32 *sym_addr_output,
1403 char *name_output)
1404{
1405 bool status = false;
1406 struct find_symbol_context context;
1407
1408 context.address = address;
1409 context.offset_range = offset_range;
1410 context.cur_best_offset = offset_range;
1411 context.sym_addr = 0;
1412 context.name[0] = '\0';
1413
1414 gh_iterate(zl_lib->sym_tab, find_symbol_callback, &context);
1415
1416 if (context.name[0]) {
1417 status = true;
1418 strcpy(name_output, context.name);
1419 *sym_addr_output = context.sym_addr;
1420 }
1421
1422 return status;
1423}
4f551c8f 1424#endif