staging: ti dspbridge: Rename words with camel case
[deliverable/linux.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 */
16
17/* ----------------------------------- Host OS */
18#include <dspbridge/host_os.h>
19
20/* ----------------------------------- DSP/BIOS Bridge */
21#include <dspbridge/std.h>
22#include <dspbridge/dbdefs.h>
23
24/* ----------------------------------- Trace & Debug */
25#include <dspbridge/dbc.h>
26#include <dspbridge/gh.h>
27
28/* ----------------------------------- OS Adaptation Layer */
29
30/* Dynamic loader library interface */
31#include <dspbridge/dynamic_loader.h>
32#include <dspbridge/getsection.h>
33
34/* ----------------------------------- This */
35#include <dspbridge/dbll.h>
36#include <dspbridge/rmm.h>
37
38/* Number of buckets for symbol hash table */
39#define MAXBUCKETS 211
40
41/* Max buffer length */
42#define MAXEXPR 128
43
44#ifndef UINT32_C
45#define UINT32_C(zzz) ((uint32_t)zzz)
46#endif
47#define DOFF_ALIGN(x) (((x) + 3) & ~UINT32_C(3))
48
49/*
50 * ======== struct dbll_tar_obj* ========
51 * A target may have one or more libraries of symbols/code/data loaded
52 * onto it, where a library is simply the symbols/code/data contained
53 * in a DOFF file.
54 */
55/*
56 * ======== dbll_tar_obj ========
57 */
58struct dbll_tar_obj {
59 struct dbll_attrs attrs;
60 struct dbll_library_obj *head; /* List of all opened libraries */
61};
62
63/*
64 * The following 4 typedefs are "super classes" of the dynamic loader
65 * library types used in dynamic loader functions (dynamic_loader.h).
66 */
67/*
68 * ======== dbll_stream ========
69 * Contains dynamic_loader_stream
70 */
71struct dbll_stream {
72 struct dynamic_loader_stream dl_stream;
73 struct dbll_library_obj *lib;
74};
75
76/*
77 * ======== ldr_symbol ========
78 */
79struct ldr_symbol {
80 struct dynamic_loader_sym dl_symbol;
81 struct dbll_library_obj *lib;
82};
83
84/*
85 * ======== dbll_alloc ========
86 */
87struct dbll_alloc {
88 struct dynamic_loader_allocate dl_alloc;
89 struct dbll_library_obj *lib;
90};
91
92/*
93 * ======== dbll_init_obj ========
94 */
95struct dbll_init_obj {
96 struct dynamic_loader_initialize dl_init;
97 struct dbll_library_obj *lib;
98};
99
100/*
101 * ======== DBLL_Library ========
102 * A library handle is returned by DBLL_Open() and is passed to dbll_load()
103 * to load symbols/code/data, and to dbll_unload(), to remove the
104 * symbols/code/data loaded by dbll_load().
105 */
106
107/*
108 * ======== dbll_library_obj ========
109 */
110struct dbll_library_obj {
111 struct dbll_library_obj *next; /* Next library in target's list */
112 struct dbll_library_obj *prev; /* Previous in the list */
113 struct dbll_tar_obj *target_obj; /* target for this library */
114
115 /* Objects needed by dynamic loader */
116 struct dbll_stream stream;
117 struct ldr_symbol symbol;
118 struct dbll_alloc allocate;
119 struct dbll_init_obj init;
120 void *dload_mod_obj;
121
122 char *file_name; /* COFF file name */
123 void *fp; /* Opaque file handle */
124 u32 entry; /* Entry point */
125 void *desc; /* desc of DOFF file loaded */
126 u32 open_ref; /* Number of times opened */
127 u32 load_ref; /* Number of times loaded */
128 struct gh_t_hash_tab *sym_tab; /* Hash table of symbols */
129 u32 ul_pos;
130};
131
132/*
133 * ======== dbll_symbol ========
134 */
135struct dbll_symbol {
136 struct dbll_sym_val value;
137 char *name;
138};
139
140static void dof_close(struct dbll_library_obj *zl_lib);
141static int dof_open(struct dbll_library_obj *zl_lib);
142static s32 no_op(struct dynamic_loader_initialize *thisptr, void *bufr,
143 ldr_addr locn, struct ldr_section_info *info, unsigned bytsiz);
144
145/*
146 * Functions called by dynamic loader
147 *
148 */
149/* dynamic_loader_stream */
150static int dbll_read_buffer(struct dynamic_loader_stream *this, void *buffer,
151 unsigned bufsize);
152static int dbll_set_file_posn(struct dynamic_loader_stream *this,
153 unsigned int pos);
154/* dynamic_loader_sym */
155static struct dynload_symbol *dbll_find_symbol(struct dynamic_loader_sym *this,
156 const char *name);
157static struct dynload_symbol *dbll_add_to_symbol_table(struct dynamic_loader_sym
158 *this, const char *name,
95870a88 159 unsigned module_id);
c4ca3d5a
ORL
160static struct dynload_symbol *find_in_symbol_table(struct dynamic_loader_sym
161 *this, const char *name,
162 unsigned moduleid);
163static void dbll_purge_symbol_table(struct dynamic_loader_sym *this,
95870a88 164 unsigned module_id);
c4ca3d5a 165static void *allocate(struct dynamic_loader_sym *this, unsigned memsize);
95870a88 166static void deallocate(struct dynamic_loader_sym *this, void *mem_ptr);
c4ca3d5a
ORL
167static void dbll_err_report(struct dynamic_loader_sym *this, const char *errstr,
168 va_list args);
169/* dynamic_loader_allocate */
170static int dbll_rmm_alloc(struct dynamic_loader_allocate *this,
171 struct ldr_section_info *info, unsigned align);
172static void rmm_dealloc(struct dynamic_loader_allocate *this,
173 struct ldr_section_info *info);
174
175/* dynamic_loader_initialize */
176static int connect(struct dynamic_loader_initialize *this);
177static int read_mem(struct dynamic_loader_initialize *this, void *buf,
178 ldr_addr addr, struct ldr_section_info *info,
179 unsigned nbytes);
180static int write_mem(struct dynamic_loader_initialize *this, void *buf,
181 ldr_addr addr, struct ldr_section_info *info,
182 unsigned nbytes);
183static int fill_mem(struct dynamic_loader_initialize *this, ldr_addr addr,
184 struct ldr_section_info *info, unsigned nbytes,
185 unsigned val);
186static int execute(struct dynamic_loader_initialize *this, ldr_addr start);
187static void release(struct dynamic_loader_initialize *this);
188
189/* symbol table hash functions */
190static u16 name_hash(void *name, u16 max_bucket);
191static bool name_match(void *name, void *sp);
192static void sym_delete(void *sp);
193
194static u32 refs; /* module reference count */
195
196/* Symbol Redefinition */
197static int redefined_symbol;
198static int gbl_search = 1;
199
200/*
201 * ======== dbll_close ========
202 */
203void dbll_close(struct dbll_library_obj *zl_lib)
204{
205 struct dbll_tar_obj *zl_target;
206
207 DBC_REQUIRE(refs > 0);
208 DBC_REQUIRE(zl_lib);
209 DBC_REQUIRE(zl_lib->open_ref > 0);
210 zl_target = zl_lib->target_obj;
211 zl_lib->open_ref--;
212 if (zl_lib->open_ref == 0) {
213 /* Remove library from list */
214 if (zl_target->head == zl_lib)
215 zl_target->head = zl_lib->next;
216
217 if (zl_lib->prev)
218 (zl_lib->prev)->next = zl_lib->next;
219
220 if (zl_lib->next)
221 (zl_lib->next)->prev = zl_lib->prev;
222
223 /* Free DOF resources */
224 dof_close(zl_lib);
225 kfree(zl_lib->file_name);
226
227 /* remove symbols from symbol table */
228 if (zl_lib->sym_tab)
229 gh_delete(zl_lib->sym_tab);
230
231 /* remove the library object itself */
232 kfree(zl_lib);
233 zl_lib = NULL;
234 }
235}
236
237/*
238 * ======== dbll_create ========
239 */
240int dbll_create(struct dbll_tar_obj **target_obj,
241 struct dbll_attrs *pattrs)
242{
243 struct dbll_tar_obj *pzl_target;
244 int status = 0;
245
246 DBC_REQUIRE(refs > 0);
247 DBC_REQUIRE(pattrs != NULL);
248 DBC_REQUIRE(target_obj != NULL);
249
250 /* Allocate DBL target object */
251 pzl_target = kzalloc(sizeof(struct dbll_tar_obj), GFP_KERNEL);
252 if (target_obj != NULL) {
253 if (pzl_target == NULL) {
254 *target_obj = NULL;
255 status = -ENOMEM;
256 } else {
257 pzl_target->attrs = *pattrs;
258 *target_obj = (struct dbll_tar_obj *)pzl_target;
259 }
260 DBC_ENSURE((DSP_SUCCEEDED(status) && *target_obj) ||
261 (DSP_FAILED(status) && *target_obj == NULL));
262 }
263
264 return status;
265}
266
267/*
268 * ======== dbll_delete ========
269 */
270void dbll_delete(struct dbll_tar_obj *target)
271{
272 struct dbll_tar_obj *zl_target = (struct dbll_tar_obj *)target;
273
274 DBC_REQUIRE(refs > 0);
275 DBC_REQUIRE(zl_target);
276
277 if (zl_target != NULL)
278 kfree(zl_target);
279
280}
281
282/*
283 * ======== dbll_exit ========
284 * Discontinue usage of DBL module.
285 */
286void dbll_exit(void)
287{
288 DBC_REQUIRE(refs > 0);
289
290 refs--;
291
292 if (refs == 0)
293 gh_exit();
294
295 DBC_ENSURE(refs >= 0);
296}
297
298/*
299 * ======== dbll_get_addr ========
300 * Get address of name in the specified library.
301 */
302bool dbll_get_addr(struct dbll_library_obj *zl_lib, char *name,
303 struct dbll_sym_val **ppSym)
304{
305 struct dbll_symbol *sym;
306 bool status = false;
307
308 DBC_REQUIRE(refs > 0);
309 DBC_REQUIRE(zl_lib);
310 DBC_REQUIRE(name != NULL);
311 DBC_REQUIRE(ppSym != NULL);
312 DBC_REQUIRE(zl_lib->sym_tab != NULL);
313
314 sym = (struct dbll_symbol *)gh_find(zl_lib->sym_tab, name);
315 if (sym != NULL) {
316 *ppSym = &sym->value;
317 status = true;
318 }
319
320 dev_dbg(bridge, "%s: lib: %p name: %s paddr: %p, status 0x%x\n",
321 __func__, zl_lib, name, ppSym, status);
322 return status;
323}
324
325/*
326 * ======== dbll_get_attrs ========
327 * Retrieve the attributes of the target.
328 */
329void dbll_get_attrs(struct dbll_tar_obj *target, struct dbll_attrs *pattrs)
330{
331 struct dbll_tar_obj *zl_target = (struct dbll_tar_obj *)target;
332
333 DBC_REQUIRE(refs > 0);
334 DBC_REQUIRE(zl_target);
335 DBC_REQUIRE(pattrs != NULL);
336
337 if ((pattrs != NULL) && (zl_target != NULL))
338 *pattrs = zl_target->attrs;
339
340}
341
342/*
343 * ======== dbll_get_c_addr ========
344 * Get address of a "C" name in the specified library.
345 */
346bool dbll_get_c_addr(struct dbll_library_obj *zl_lib, char *name,
347 struct dbll_sym_val **ppSym)
348{
349 struct dbll_symbol *sym;
350 char cname[MAXEXPR + 1];
351 bool status = false;
352
353 DBC_REQUIRE(refs > 0);
354 DBC_REQUIRE(zl_lib);
355 DBC_REQUIRE(ppSym != NULL);
356 DBC_REQUIRE(zl_lib->sym_tab != NULL);
357 DBC_REQUIRE(name != NULL);
358
359 cname[0] = '_';
360
361 strncpy(cname + 1, name, sizeof(cname) - 2);
362 cname[MAXEXPR] = '\0'; /* insure '\0' string termination */
363
364 /* Check for C name, if not found */
365 sym = (struct dbll_symbol *)gh_find(zl_lib->sym_tab, cname);
366
367 if (sym != NULL) {
368 *ppSym = &sym->value;
369 status = true;
370 }
371
372 return status;
373}
374
375/*
376 * ======== dbll_get_sect ========
377 * Get the base address and size (in bytes) of a COFF section.
378 */
379int dbll_get_sect(struct dbll_library_obj *lib, char *name, u32 *paddr,
380 u32 *psize)
381{
382 u32 byte_size;
383 bool opened_doff = false;
384 const struct ldr_section_info *sect = NULL;
385 struct dbll_library_obj *zl_lib = (struct dbll_library_obj *)lib;
386 int status = 0;
387
388 DBC_REQUIRE(refs > 0);
389 DBC_REQUIRE(name != NULL);
390 DBC_REQUIRE(paddr != NULL);
391 DBC_REQUIRE(psize != NULL);
392 DBC_REQUIRE(zl_lib);
393
394 /* If DOFF file is not open, we open it. */
395 if (zl_lib != NULL) {
396 if (zl_lib->fp == NULL) {
397 status = dof_open(zl_lib);
398 if (DSP_SUCCEEDED(status))
399 opened_doff = true;
400
401 } else {
402 (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp,
403 zl_lib->ul_pos,
404 SEEK_SET);
405 }
406 } else {
407 status = -EFAULT;
408 }
409 if (DSP_SUCCEEDED(status)) {
410 byte_size = 1;
411 if (dload_get_section_info(zl_lib->desc, name, &sect)) {
412 *paddr = sect->load_addr;
413 *psize = sect->size * byte_size;
414 /* Make sure size is even for good swap */
415 if (*psize % 2)
416 (*psize)++;
417
418 /* Align size */
419 *psize = DOFF_ALIGN(*psize);
420 } else {
421 status = -ENXIO;
422 }
423 }
424 if (opened_doff) {
425 dof_close(zl_lib);
426 opened_doff = false;
427 }
428
429 dev_dbg(bridge, "%s: lib: %p name: %s paddr: %p psize: %p, "
430 "status 0x%x\n", __func__, lib, name, paddr, psize, status);
431
432 return status;
433}
434
435/*
436 * ======== dbll_init ========
437 */
438bool dbll_init(void)
439{
440 DBC_REQUIRE(refs >= 0);
441
442 if (refs == 0)
443 gh_init();
444
445 refs++;
446
447 return true;
448}
449
450/*
451 * ======== dbll_load ========
452 */
453int dbll_load(struct dbll_library_obj *lib, dbll_flags flags,
454 struct dbll_attrs *attrs, u32 *pEntry)
455{
456 struct dbll_library_obj *zl_lib = (struct dbll_library_obj *)lib;
457 struct dbll_tar_obj *dbzl;
458 bool got_symbols = true;
459 s32 err;
460 int status = 0;
461 bool opened_doff = false;
462 DBC_REQUIRE(refs > 0);
463 DBC_REQUIRE(zl_lib);
464 DBC_REQUIRE(pEntry != NULL);
465 DBC_REQUIRE(attrs != NULL);
466
467 /*
468 * Load if not already loaded.
469 */
470 if (zl_lib->load_ref == 0 || !(flags & DBLL_DYNAMIC)) {
471 dbzl = zl_lib->target_obj;
472 dbzl->attrs = *attrs;
473 /* Create a hash table for symbols if not already created */
474 if (zl_lib->sym_tab == NULL) {
475 got_symbols = false;
476 zl_lib->sym_tab = gh_create(MAXBUCKETS,
477 sizeof(struct dbll_symbol),
478 name_hash,
479 name_match, sym_delete);
480 if (zl_lib->sym_tab == NULL)
481 status = -ENOMEM;
482
483 }
484 /*
485 * Set up objects needed by the dynamic loader
486 */
487 /* Stream */
488 zl_lib->stream.dl_stream.read_buffer = dbll_read_buffer;
489 zl_lib->stream.dl_stream.set_file_posn = dbll_set_file_posn;
490 zl_lib->stream.lib = zl_lib;
491 /* Symbol */
492 zl_lib->symbol.dl_symbol.find_matching_symbol =
493 dbll_find_symbol;
494 if (got_symbols) {
495 zl_lib->symbol.dl_symbol.add_to_symbol_table =
496 find_in_symbol_table;
497 } else {
498 zl_lib->symbol.dl_symbol.add_to_symbol_table =
499 dbll_add_to_symbol_table;
500 }
501 zl_lib->symbol.dl_symbol.purge_symbol_table =
502 dbll_purge_symbol_table;
503 zl_lib->symbol.dl_symbol.dload_allocate = allocate;
504 zl_lib->symbol.dl_symbol.dload_deallocate = deallocate;
505 zl_lib->symbol.dl_symbol.error_report = dbll_err_report;
506 zl_lib->symbol.lib = zl_lib;
507 /* Allocate */
508 zl_lib->allocate.dl_alloc.dload_allocate = dbll_rmm_alloc;
509 zl_lib->allocate.dl_alloc.dload_deallocate = rmm_dealloc;
510 zl_lib->allocate.lib = zl_lib;
511 /* Init */
512 zl_lib->init.dl_init.connect = connect;
513 zl_lib->init.dl_init.readmem = read_mem;
514 zl_lib->init.dl_init.writemem = write_mem;
515 zl_lib->init.dl_init.fillmem = fill_mem;
516 zl_lib->init.dl_init.execute = execute;
517 zl_lib->init.dl_init.release = release;
518 zl_lib->init.lib = zl_lib;
519 /* If COFF file is not open, we open it. */
520 if (zl_lib->fp == NULL) {
521 status = dof_open(zl_lib);
522 if (DSP_SUCCEEDED(status))
523 opened_doff = true;
524
525 }
526 if (DSP_SUCCEEDED(status)) {
527 zl_lib->ul_pos = (*(zl_lib->target_obj->attrs.ftell))
528 (zl_lib->fp);
529 /* Reset file cursor */
530 (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp,
531 (long)0,
532 SEEK_SET);
533 symbols_reloaded = true;
534 /* The 5th argument, DLOAD_INITBSS, tells the DLL
535 * module to zero-init all BSS sections. In general,
536 * this is not necessary and also increases load time.
537 * We may want to make this configurable by the user */
538 err = dynamic_load_module(&zl_lib->stream.dl_stream,
539 &zl_lib->symbol.dl_symbol,
540 &zl_lib->allocate.dl_alloc,
541 &zl_lib->init.dl_init,
542 DLOAD_INITBSS,
543 &zl_lib->dload_mod_obj);
544
545 if (err != 0) {
546 status = -EILSEQ;
547 } else if (redefined_symbol) {
548 zl_lib->load_ref++;
549 dbll_unload(zl_lib, (struct dbll_attrs *)attrs);
550 redefined_symbol = false;
551 status = -EILSEQ;
552 } else {
553 *pEntry = zl_lib->entry;
554 }
555 }
556 }
557 if (DSP_SUCCEEDED(status))
558 zl_lib->load_ref++;
559
560 /* Clean up DOFF resources */
561 if (opened_doff)
562 dof_close(zl_lib);
563
564 DBC_ENSURE(DSP_FAILED(status) || zl_lib->load_ref > 0);
565
566 dev_dbg(bridge, "%s: lib: %p flags: 0x%x pEntry: %p, status 0x%x\n",
567 __func__, lib, flags, pEntry, status);
568
569 return status;
570}
571
572/*
573 * ======== dbll_load_sect ========
574 * Not supported for COFF.
575 */
576int dbll_load_sect(struct dbll_library_obj *zl_lib, char *sectName,
577 struct dbll_attrs *attrs)
578{
579 DBC_REQUIRE(zl_lib);
580
581 return -ENOSYS;
582}
583
584/*
585 * ======== dbll_open ========
586 */
587int dbll_open(struct dbll_tar_obj *target, char *file, dbll_flags flags,
588 struct dbll_library_obj **pLib)
589{
590 struct dbll_tar_obj *zl_target = (struct dbll_tar_obj *)target;
591 struct dbll_library_obj *zl_lib = NULL;
592 s32 err;
593 int status = 0;
594
595 DBC_REQUIRE(refs > 0);
596 DBC_REQUIRE(zl_target);
597 DBC_REQUIRE(zl_target->attrs.fopen != NULL);
598 DBC_REQUIRE(file != NULL);
599 DBC_REQUIRE(pLib != NULL);
600
601 zl_lib = zl_target->head;
602 while (zl_lib != NULL) {
603 if (strcmp(zl_lib->file_name, file) == 0) {
604 /* Library is already opened */
605 zl_lib->open_ref++;
606 break;
607 }
608 zl_lib = zl_lib->next;
609 }
610 if (zl_lib == NULL) {
611 /* Allocate DBL library object */
612 zl_lib = kzalloc(sizeof(struct dbll_library_obj), GFP_KERNEL);
613 if (zl_lib == NULL) {
614 status = -ENOMEM;
615 } else {
616 zl_lib->ul_pos = 0;
617 /* Increment ref count to allow close on failure
618 * later on */
619 zl_lib->open_ref++;
620 zl_lib->target_obj = zl_target;
621 /* Keep a copy of the file name */
622 zl_lib->file_name = kzalloc(strlen(file) + 1,
623 GFP_KERNEL);
624 if (zl_lib->file_name == NULL) {
625 status = -ENOMEM;
626 } else {
627 strncpy(zl_lib->file_name, file,
628 strlen(file) + 1);
629 }
630 zl_lib->sym_tab = NULL;
631 }
632 }
633 /*
634 * Set up objects needed by the dynamic loader
635 */
636 if (DSP_FAILED(status))
637 goto func_cont;
638
639 /* Stream */
640 zl_lib->stream.dl_stream.read_buffer = dbll_read_buffer;
641 zl_lib->stream.dl_stream.set_file_posn = dbll_set_file_posn;
642 zl_lib->stream.lib = zl_lib;
643 /* Symbol */
644 zl_lib->symbol.dl_symbol.add_to_symbol_table = dbll_add_to_symbol_table;
645 zl_lib->symbol.dl_symbol.find_matching_symbol = dbll_find_symbol;
646 zl_lib->symbol.dl_symbol.purge_symbol_table = dbll_purge_symbol_table;
647 zl_lib->symbol.dl_symbol.dload_allocate = allocate;
648 zl_lib->symbol.dl_symbol.dload_deallocate = deallocate;
649 zl_lib->symbol.dl_symbol.error_report = dbll_err_report;
650 zl_lib->symbol.lib = zl_lib;
651 /* Allocate */
652 zl_lib->allocate.dl_alloc.dload_allocate = dbll_rmm_alloc;
653 zl_lib->allocate.dl_alloc.dload_deallocate = rmm_dealloc;
654 zl_lib->allocate.lib = zl_lib;
655 /* Init */
656 zl_lib->init.dl_init.connect = connect;
657 zl_lib->init.dl_init.readmem = read_mem;
658 zl_lib->init.dl_init.writemem = write_mem;
659 zl_lib->init.dl_init.fillmem = fill_mem;
660 zl_lib->init.dl_init.execute = execute;
661 zl_lib->init.dl_init.release = release;
662 zl_lib->init.lib = zl_lib;
663 if (DSP_SUCCEEDED(status) && zl_lib->fp == NULL)
664 status = dof_open(zl_lib);
665
666 zl_lib->ul_pos = (*(zl_lib->target_obj->attrs.ftell)) (zl_lib->fp);
667 (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp, (long)0, SEEK_SET);
668 /* Create a hash table for symbols if flag is set */
669 if (zl_lib->sym_tab != NULL || !(flags & DBLL_SYMB))
670 goto func_cont;
671
672 zl_lib->sym_tab =
673 gh_create(MAXBUCKETS, sizeof(struct dbll_symbol), name_hash,
674 name_match, sym_delete);
675 if (zl_lib->sym_tab == NULL) {
676 status = -ENOMEM;
677 } else {
678 /* Do a fake load to get symbols - set write func to no_op */
679 zl_lib->init.dl_init.writemem = no_op;
680 err = dynamic_open_module(&zl_lib->stream.dl_stream,
681 &zl_lib->symbol.dl_symbol,
682 &zl_lib->allocate.dl_alloc,
683 &zl_lib->init.dl_init, 0,
684 &zl_lib->dload_mod_obj);
685 if (err != 0) {
686 status = -EILSEQ;
687 } else {
688 /* Now that we have the symbol table, we can unload */
689 err = dynamic_unload_module(zl_lib->dload_mod_obj,
690 &zl_lib->symbol.dl_symbol,
691 &zl_lib->allocate.dl_alloc,
692 &zl_lib->init.dl_init);
693 if (err != 0)
694 status = -EILSEQ;
695
696 zl_lib->dload_mod_obj = NULL;
697 }
698 }
699func_cont:
700 if (DSP_SUCCEEDED(status)) {
701 if (zl_lib->open_ref == 1) {
702 /* First time opened - insert in list */
703 if (zl_target->head)
704 (zl_target->head)->prev = zl_lib;
705
706 zl_lib->prev = NULL;
707 zl_lib->next = zl_target->head;
708 zl_target->head = zl_lib;
709 }
710 *pLib = (struct dbll_library_obj *)zl_lib;
711 } else {
712 *pLib = NULL;
713 if (zl_lib != NULL)
714 dbll_close((struct dbll_library_obj *)zl_lib);
715
716 }
717 DBC_ENSURE((DSP_SUCCEEDED(status) && (zl_lib->open_ref > 0) && *pLib)
718 || (DSP_FAILED(status) && *pLib == NULL));
719
720 dev_dbg(bridge, "%s: target: %p file: %s pLib: %p, status 0x%x\n",
721 __func__, target, file, pLib, status);
722
723 return status;
724}
725
726/*
727 * ======== dbll_read_sect ========
728 * Get the content of a COFF section.
729 */
730int dbll_read_sect(struct dbll_library_obj *lib, char *name,
aa09b091 731 char *content, u32 size)
c4ca3d5a
ORL
732{
733 struct dbll_library_obj *zl_lib = (struct dbll_library_obj *)lib;
734 bool opened_doff = false;
735 u32 byte_size; /* size of bytes */
736 u32 ul_sect_size; /* size of section */
737 const struct ldr_section_info *sect = NULL;
738 int status = 0;
739
740 DBC_REQUIRE(refs > 0);
741 DBC_REQUIRE(zl_lib);
742 DBC_REQUIRE(name != NULL);
aa09b091 743 DBC_REQUIRE(content != NULL);
c4ca3d5a
ORL
744 DBC_REQUIRE(size != 0);
745
746 /* If DOFF file is not open, we open it. */
747 if (zl_lib != NULL) {
748 if (zl_lib->fp == NULL) {
749 status = dof_open(zl_lib);
750 if (DSP_SUCCEEDED(status))
751 opened_doff = true;
752
753 } else {
754 (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp,
755 zl_lib->ul_pos,
756 SEEK_SET);
757 }
758 } else {
759 status = -EFAULT;
760 }
761 if (DSP_FAILED(status))
762 goto func_cont;
763
764 byte_size = 1;
765 if (!dload_get_section_info(zl_lib->desc, name, &sect)) {
766 status = -ENXIO;
767 goto func_cont;
768 }
769 /*
770 * Ensure the supplied buffer size is sufficient to store
771 * the section content to be read.
772 */
773 ul_sect_size = sect->size * byte_size;
774 /* Make sure size is even for good swap */
775 if (ul_sect_size % 2)
776 ul_sect_size++;
777
778 /* Align size */
779 ul_sect_size = DOFF_ALIGN(ul_sect_size);
780 if (ul_sect_size > size) {
781 status = -EPERM;
782 } else {
aa09b091 783 if (!dload_get_section(zl_lib->desc, sect, content))
c4ca3d5a
ORL
784 status = -EBADF;
785
786 }
787func_cont:
788 if (opened_doff) {
789 dof_close(zl_lib);
790 opened_doff = false;
791 }
792
aa09b091
RS
793 dev_dbg(bridge, "%s: lib: %p name: %s content: %p size: 0x%x, "
794 "status 0x%x\n", __func__, lib, name, content, size, status);
c4ca3d5a
ORL
795 return status;
796}
797
798/*
799 * ======== dbll_set_attrs ========
800 * Set the attributes of the target.
801 */
802void dbll_set_attrs(struct dbll_tar_obj *target, struct dbll_attrs *pattrs)
803{
804 struct dbll_tar_obj *zl_target = (struct dbll_tar_obj *)target;
805 DBC_REQUIRE(refs > 0);
806 DBC_REQUIRE(zl_target);
807 DBC_REQUIRE(pattrs != NULL);
808
809 if ((pattrs != NULL) && (zl_target != NULL))
810 zl_target->attrs = *pattrs;
811
812}
813
814/*
815 * ======== dbll_unload ========
816 */
817void dbll_unload(struct dbll_library_obj *lib, struct dbll_attrs *attrs)
818{
819 struct dbll_library_obj *zl_lib = (struct dbll_library_obj *)lib;
820 s32 err = 0;
821
822 DBC_REQUIRE(refs > 0);
823 DBC_REQUIRE(zl_lib);
824 DBC_REQUIRE(zl_lib->load_ref > 0);
825 dev_dbg(bridge, "%s: lib: %p\n", __func__, lib);
826 zl_lib->load_ref--;
827 /* Unload only if reference count is 0 */
828 if (zl_lib->load_ref != 0)
829 goto func_end;
830
831 zl_lib->target_obj->attrs = *attrs;
832 if (zl_lib->dload_mod_obj) {
833 err = dynamic_unload_module(zl_lib->dload_mod_obj,
834 &zl_lib->symbol.dl_symbol,
835 &zl_lib->allocate.dl_alloc,
836 &zl_lib->init.dl_init);
837 if (err != 0)
838 dev_dbg(bridge, "%s: failed: 0x%x\n", __func__, err);
839 }
840 /* remove symbols from symbol table */
841 if (zl_lib->sym_tab != NULL) {
842 gh_delete(zl_lib->sym_tab);
843 zl_lib->sym_tab = NULL;
844 }
845 /* delete DOFF desc since it holds *lots* of host OS
846 * resources */
847 dof_close(zl_lib);
848func_end:
849 DBC_ENSURE(zl_lib->load_ref >= 0);
850}
851
852/*
853 * ======== dbll_unload_sect ========
854 * Not supported for COFF.
855 */
856int dbll_unload_sect(struct dbll_library_obj *lib, char *sectName,
857 struct dbll_attrs *attrs)
858{
859 DBC_REQUIRE(refs > 0);
860 DBC_REQUIRE(sectName != NULL);
861
862 return -ENOSYS;
863}
864
865/*
866 * ======== dof_close ========
867 */
868static void dof_close(struct dbll_library_obj *zl_lib)
869{
870 if (zl_lib->desc) {
871 dload_module_close(zl_lib->desc);
872 zl_lib->desc = NULL;
873 }
874 /* close file */
875 if (zl_lib->fp) {
876 (zl_lib->target_obj->attrs.fclose) (zl_lib->fp);
877 zl_lib->fp = NULL;
878 }
879}
880
881/*
882 * ======== dof_open ========
883 */
884static int dof_open(struct dbll_library_obj *zl_lib)
885{
886 void *open = *(zl_lib->target_obj->attrs.fopen);
887 int status = 0;
888
889 /* First open the file for the dynamic loader, then open COF */
890 zl_lib->fp =
891 (void *)((dbll_f_open_fxn) (open)) (zl_lib->file_name, "rb");
892
893 /* Open DOFF module */
894 if (zl_lib->fp && zl_lib->desc == NULL) {
895 (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp, (long)0,
896 SEEK_SET);
897 zl_lib->desc =
898 dload_module_open(&zl_lib->stream.dl_stream,
899 &zl_lib->symbol.dl_symbol);
900 if (zl_lib->desc == NULL) {
901 (zl_lib->target_obj->attrs.fclose) (zl_lib->fp);
902 zl_lib->fp = NULL;
903 status = -EBADF;
904 }
905 } else {
906 status = -EBADF;
907 }
908
909 return status;
910}
911
912/*
913 * ======== name_hash ========
914 */
915static u16 name_hash(void *key, u16 max_bucket)
916{
917 u16 ret;
918 u16 hash;
919 char *name = (char *)key;
920
921 DBC_REQUIRE(name != NULL);
922
923 hash = 0;
924
925 while (*name) {
926 hash <<= 1;
927 hash ^= *name++;
928 }
929
930 ret = hash % max_bucket;
931
932 return ret;
933}
934
935/*
936 * ======== name_match ========
937 */
938static bool name_match(void *key, void *value)
939{
940 DBC_REQUIRE(key != NULL);
941 DBC_REQUIRE(value != NULL);
942
943 if ((key != NULL) && (value != NULL)) {
944 if (strcmp((char *)key, ((struct dbll_symbol *)value)->name) ==
945 0)
946 return true;
947 }
948 return false;
949}
950
951/*
952 * ======== no_op ========
953 */
954static int no_op(struct dynamic_loader_initialize *thisptr, void *bufr,
955 ldr_addr locn, struct ldr_section_info *info, unsigned bytsize)
956{
957 return 1;
958}
959
960/*
961 * ======== sym_delete ========
962 */
963static void sym_delete(void *value)
964{
965 struct dbll_symbol *sp = (struct dbll_symbol *)value;
966
967 kfree(sp->name);
968}
969
970/*
971 * Dynamic Loader Functions
972 */
973
974/* dynamic_loader_stream */
975/*
976 * ======== dbll_read_buffer ========
977 */
978static int dbll_read_buffer(struct dynamic_loader_stream *this, void *buffer,
979 unsigned bufsize)
980{
981 struct dbll_stream *pstream = (struct dbll_stream *)this;
982 struct dbll_library_obj *lib;
983 int bytes_read = 0;
984
985 DBC_REQUIRE(this != NULL);
986 lib = pstream->lib;
987 DBC_REQUIRE(lib);
988
989 if (lib != NULL) {
990 bytes_read =
991 (*(lib->target_obj->attrs.fread)) (buffer, 1, bufsize,
992 lib->fp);
993 }
994 return bytes_read;
995}
996
997/*
998 * ======== dbll_set_file_posn ========
999 */
1000static int dbll_set_file_posn(struct dynamic_loader_stream *this,
1001 unsigned int pos)
1002{
1003 struct dbll_stream *pstream = (struct dbll_stream *)this;
1004 struct dbll_library_obj *lib;
1005 int status = 0; /* Success */
1006
1007 DBC_REQUIRE(this != NULL);
1008 lib = pstream->lib;
1009 DBC_REQUIRE(lib);
1010
1011 if (lib != NULL) {
1012 status = (*(lib->target_obj->attrs.fseek)) (lib->fp, (long)pos,
1013 SEEK_SET);
1014 }
1015
1016 return status;
1017}
1018
1019/* dynamic_loader_sym */
1020
1021/*
1022 * ======== dbll_find_symbol ========
1023 */
1024static struct dynload_symbol *dbll_find_symbol(struct dynamic_loader_sym *this,
1025 const char *name)
1026{
1027 struct dynload_symbol *ret_sym;
1028 struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this;
1029 struct dbll_library_obj *lib;
1030 struct dbll_sym_val *dbll_sym = NULL;
1031 bool status = false; /* Symbol not found yet */
1032
1033 DBC_REQUIRE(this != NULL);
1034 lib = ldr_sym->lib;
1035 DBC_REQUIRE(lib);
1036
1037 if (lib != NULL) {
1038 if (lib->target_obj->attrs.sym_lookup) {
1039 /* Check current lib + base lib + dep lib +
1040 * persistent lib */
1041 status = (*(lib->target_obj->attrs.sym_lookup))
1042 (lib->target_obj->attrs.sym_handle,
1043 lib->target_obj->attrs.sym_arg,
1044 lib->target_obj->attrs.rmm_handle, name,
1045 &dbll_sym);
1046 } else {
1047 /* Just check current lib for symbol */
1048 status = dbll_get_addr((struct dbll_library_obj *)lib,
1049 (char *)name, &dbll_sym);
1050 if (!status) {
1051 status =
1052 dbll_get_c_addr((struct dbll_library_obj *)
1053 lib, (char *)name,
1054 &dbll_sym);
1055 }
1056 }
1057 }
1058
1059 if (!status && gbl_search)
1060 dev_dbg(bridge, "%s: Symbol not found: %s\n", __func__, name);
1061
1062 DBC_ASSERT((status && (dbll_sym != NULL))
1063 || (!status && (dbll_sym == NULL)));
1064
1065 ret_sym = (struct dynload_symbol *)dbll_sym;
1066 return ret_sym;
1067}
1068
1069/*
1070 * ======== find_in_symbol_table ========
1071 */
1072static struct dynload_symbol *find_in_symbol_table(struct dynamic_loader_sym
1073 *this, const char *name,
1074 unsigned moduleid)
1075{
1076 struct dynload_symbol *ret_sym;
1077 struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this;
1078 struct dbll_library_obj *lib;
1079 struct dbll_symbol *sym;
1080
1081 DBC_REQUIRE(this != NULL);
1082 lib = ldr_sym->lib;
1083 DBC_REQUIRE(lib);
1084 DBC_REQUIRE(lib->sym_tab != NULL);
1085
1086 sym = (struct dbll_symbol *)gh_find(lib->sym_tab, (char *)name);
1087
1088 ret_sym = (struct dynload_symbol *)&sym->value;
1089 return ret_sym;
1090}
1091
1092/*
1093 * ======== dbll_add_to_symbol_table ========
1094 */
1095static struct dynload_symbol *dbll_add_to_symbol_table(struct dynamic_loader_sym
1096 *this, const char *name,
95870a88 1097 unsigned module_id)
c4ca3d5a
ORL
1098{
1099 struct dbll_symbol *sym_ptr = NULL;
1100 struct dbll_symbol symbol;
1101 struct dynload_symbol *dbll_sym = NULL;
1102 struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this;
1103 struct dbll_library_obj *lib;
1104 struct dynload_symbol *ret;
1105
1106 DBC_REQUIRE(this != NULL);
1107 DBC_REQUIRE(name);
1108 lib = ldr_sym->lib;
1109 DBC_REQUIRE(lib);
1110
1111 /* Check to see if symbol is already defined in symbol table */
1112 if (!(lib->target_obj->attrs.base_image)) {
1113 gbl_search = false;
1114 dbll_sym = dbll_find_symbol(this, name);
1115 gbl_search = true;
1116 if (dbll_sym) {
1117 redefined_symbol = true;
1118 dev_dbg(bridge, "%s already defined in symbol table\n",
1119 name);
1120 return NULL;
1121 }
1122 }
1123 /* Allocate string to copy symbol name */
1124 symbol.name = kzalloc(strlen((char *const)name) + 1, GFP_KERNEL);
1125 if (symbol.name == NULL)
1126 return NULL;
1127
1128 if (symbol.name != NULL) {
1129 /* Just copy name (value will be filled in by dynamic loader) */
1130 strncpy(symbol.name, (char *const)name,
1131 strlen((char *const)name) + 1);
1132
1133 /* Add symbol to symbol table */
1134 sym_ptr =
1135 (struct dbll_symbol *)gh_insert(lib->sym_tab, (void *)name,
1136 (void *)&symbol);
1137 if (sym_ptr == NULL)
1138 kfree(symbol.name);
1139
1140 }
1141 if (sym_ptr != NULL)
1142 ret = (struct dynload_symbol *)&sym_ptr->value;
1143 else
1144 ret = NULL;
1145
1146 return ret;
1147}
1148
1149/*
1150 * ======== dbll_purge_symbol_table ========
1151 */
1152static void dbll_purge_symbol_table(struct dynamic_loader_sym *this,
95870a88 1153 unsigned module_id)
c4ca3d5a
ORL
1154{
1155 struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this;
1156 struct dbll_library_obj *lib;
1157
1158 DBC_REQUIRE(this != NULL);
1159 lib = ldr_sym->lib;
1160 DBC_REQUIRE(lib);
1161
1162 /* May not need to do anything */
1163}
1164
1165/*
1166 * ======== allocate ========
1167 */
1168static void *allocate(struct dynamic_loader_sym *this, unsigned memsize)
1169{
1170 struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this;
1171 struct dbll_library_obj *lib;
1172 void *buf;
1173
1174 DBC_REQUIRE(this != NULL);
1175 lib = ldr_sym->lib;
1176 DBC_REQUIRE(lib);
1177
1178 buf = kzalloc(memsize, GFP_KERNEL);
1179
1180 return buf;
1181}
1182
1183/*
1184 * ======== deallocate ========
1185 */
95870a88 1186static void deallocate(struct dynamic_loader_sym *this, void *mem_ptr)
c4ca3d5a
ORL
1187{
1188 struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this;
1189 struct dbll_library_obj *lib;
1190
1191 DBC_REQUIRE(this != NULL);
1192 lib = ldr_sym->lib;
1193 DBC_REQUIRE(lib);
1194
95870a88 1195 kfree(mem_ptr);
c4ca3d5a
ORL
1196}
1197
1198/*
1199 * ======== dbll_err_report ========
1200 */
1201static void dbll_err_report(struct dynamic_loader_sym *this, const char *errstr,
1202 va_list args)
1203{
1204 struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this;
1205 struct dbll_library_obj *lib;
1206 char temp_buf[MAXEXPR];
1207
1208 DBC_REQUIRE(this != NULL);
1209 lib = ldr_sym->lib;
1210 DBC_REQUIRE(lib);
1211 vsnprintf((char *)temp_buf, MAXEXPR, (char *)errstr, args);
1212 dev_dbg(bridge, "%s\n", temp_buf);
1213}
1214
1215/* dynamic_loader_allocate */
1216
1217/*
1218 * ======== dbll_rmm_alloc ========
1219 */
1220static int dbll_rmm_alloc(struct dynamic_loader_allocate *this,
1221 struct ldr_section_info *info, unsigned align)
1222{
1223 struct dbll_alloc *dbll_alloc_obj = (struct dbll_alloc *)this;
1224 struct dbll_library_obj *lib;
1225 int status = 0;
1226 u32 mem_sect_type;
1227 struct rmm_addr rmm_addr_obj;
1228 s32 ret = TRUE;
1229 unsigned stype = DLOAD_SECTION_TYPE(info->type);
1230 char *token = NULL;
1231 char *sz_sec_last_token = NULL;
1232 char *sz_last_token = NULL;
1233 char *sz_sect_name = NULL;
1234 char *psz_cur;
1235 s32 token_len = 0;
1236 s32 seg_id = -1;
1237 s32 req = -1;
1238 s32 count = 0;
1239 u32 alloc_size = 0;
1240 u32 run_addr_flag = 0;
1241
1242 DBC_REQUIRE(this != NULL);
1243 lib = dbll_alloc_obj->lib;
1244 DBC_REQUIRE(lib);
1245
1246 mem_sect_type =
1247 (stype == DLOAD_TEXT) ? DBLL_CODE : (stype ==
1248 DLOAD_BSS) ? DBLL_BSS :
1249 DBLL_DATA;
1250
1251 /* Attempt to extract the segment ID and requirement information from
1252 the name of the section */
1253 DBC_REQUIRE(info->name);
1254 token_len = strlen((char *)(info->name)) + 1;
1255
1256 sz_sect_name = kzalloc(token_len, GFP_KERNEL);
1257 sz_last_token = kzalloc(token_len, GFP_KERNEL);
1258 sz_sec_last_token = kzalloc(token_len, GFP_KERNEL);
1259
1260 if (sz_sect_name == NULL || sz_sec_last_token == NULL ||
1261 sz_last_token == NULL) {
1262 status = -ENOMEM;
1263 goto func_cont;
1264 }
1265 strncpy(sz_sect_name, (char *)(info->name), token_len);
1266 psz_cur = sz_sect_name;
1267 while ((token = strsep(&psz_cur, ":")) && *token != '\0') {
1268 strncpy(sz_sec_last_token, sz_last_token,
1269 strlen(sz_last_token) + 1);
1270 strncpy(sz_last_token, token, strlen(token) + 1);
1271 token = strsep(&psz_cur, ":");
1272 count++; /* optimizes processing */
1273 }
1274 /* If token is 0 or 1, and sz_sec_last_token is DYN_DARAM or DYN_SARAM,
1275 or DYN_EXTERNAL, then mem granularity information is present
1276 within the section name - only process if there are at least three
1277 tokens within the section name (just a minor optimization) */
1278 if (count >= 3)
1279 strict_strtol(sz_last_token, 10, (long *)&req);
1280
1281 if ((req == 0) || (req == 1)) {
1282 if (strcmp(sz_sec_last_token, "DYN_DARAM") == 0) {
1283 seg_id = 0;
1284 } else {
1285 if (strcmp(sz_sec_last_token, "DYN_SARAM") == 0) {
1286 seg_id = 1;
1287 } else {
1288 if (strcmp(sz_sec_last_token,
1289 "DYN_EXTERNAL") == 0)
1290 seg_id = 2;
1291 }
1292 }
1293 }
1294func_cont:
1295 kfree(sz_sect_name);
1296 sz_sect_name = NULL;
1297 kfree(sz_last_token);
1298 sz_last_token = NULL;
1299 kfree(sz_sec_last_token);
1300 sz_sec_last_token = NULL;
1301
1302 if (mem_sect_type == DBLL_CODE)
1303 alloc_size = info->size + GEM_L1P_PREFETCH_SIZE;
1304 else
1305 alloc_size = info->size;
1306
1307 if (info->load_addr != info->run_addr)
1308 run_addr_flag = 1;
1309 /* TODO - ideally, we can pass the alignment requirement also
1310 * from here */
1311 if (lib != NULL) {
1312 status =
1313 (lib->target_obj->attrs.alloc) (lib->target_obj->attrs.
1314 rmm_handle, mem_sect_type,
1315 alloc_size, align,
1316 (u32 *) &rmm_addr_obj,
1317 seg_id, req, FALSE);
1318 }
1319 if (DSP_FAILED(status)) {
1320 ret = false;
1321 } else {
1322 /* RMM gives word address. Need to convert to byte address */
1323 info->load_addr = rmm_addr_obj.addr * DSPWORDSIZE;
1324 if (!run_addr_flag)
1325 info->run_addr = info->load_addr;
1326 info->context = (u32) rmm_addr_obj.segid;
1327 dev_dbg(bridge, "%s: %s base = 0x%x len = 0x%x, "
1328 "info->run_addr 0x%x, info->load_addr 0x%x\n",
1329 __func__, info->name, info->load_addr / DSPWORDSIZE,
1330 info->size / DSPWORDSIZE, info->run_addr,
1331 info->load_addr);
1332 }
1333 return ret;
1334}
1335
1336/*
1337 * ======== rmm_dealloc ========
1338 */
1339static void rmm_dealloc(struct dynamic_loader_allocate *this,
1340 struct ldr_section_info *info)
1341{
1342 struct dbll_alloc *dbll_alloc_obj = (struct dbll_alloc *)this;
1343 struct dbll_library_obj *lib;
1344 u32 segid;
1345 int status = 0;
1346 unsigned stype = DLOAD_SECTION_TYPE(info->type);
1347 u32 mem_sect_type;
1348 u32 free_size = 0;
1349
1350 mem_sect_type =
1351 (stype == DLOAD_TEXT) ? DBLL_CODE : (stype ==
1352 DLOAD_BSS) ? DBLL_BSS :
1353 DBLL_DATA;
1354 DBC_REQUIRE(this != NULL);
1355 lib = dbll_alloc_obj->lib;
1356 DBC_REQUIRE(lib);
1357 /* segid was set by alloc function */
1358 segid = (u32) info->context;
1359 if (mem_sect_type == DBLL_CODE)
1360 free_size = info->size + GEM_L1P_PREFETCH_SIZE;
1361 else
1362 free_size = info->size;
1363 if (lib != NULL) {
1364 status =
1365 (lib->target_obj->attrs.free) (lib->target_obj->attrs.
1366 sym_handle, segid,
1367 info->load_addr /
1368 DSPWORDSIZE, free_size,
1369 false);
1370 }
1371}
1372
1373/* dynamic_loader_initialize */
1374/*
1375 * ======== connect ========
1376 */
1377static int connect(struct dynamic_loader_initialize *this)
1378{
1379 return true;
1380}
1381
1382/*
1383 * ======== read_mem ========
1384 * This function does not need to be implemented.
1385 */
1386static int read_mem(struct dynamic_loader_initialize *this, void *buf,
1387 ldr_addr addr, struct ldr_section_info *info,
1388 unsigned nbytes)
1389{
1390 struct dbll_init_obj *init_obj = (struct dbll_init_obj *)this;
1391 struct dbll_library_obj *lib;
1392 int bytes_read = 0;
1393
1394 DBC_REQUIRE(this != NULL);
1395 lib = init_obj->lib;
1396 DBC_REQUIRE(lib);
1397 /* Need bridge_brd_read function */
1398 return bytes_read;
1399}
1400
1401/*
1402 * ======== write_mem ========
1403 */
1404static int write_mem(struct dynamic_loader_initialize *this, void *buf,
1405 ldr_addr addr, struct ldr_section_info *info,
1406 unsigned bytes)
1407{
1408 struct dbll_init_obj *init_obj = (struct dbll_init_obj *)this;
1409 struct dbll_library_obj *lib;
1410 struct dbll_tar_obj *target_obj;
1411 struct dbll_sect_info sect_info;
1412 u32 mem_sect_type;
1413 bool ret = true;
1414
1415 DBC_REQUIRE(this != NULL);
1416 lib = init_obj->lib;
1417 if (!lib)
1418 return false;
1419
1420 target_obj = lib->target_obj;
1421
1422 mem_sect_type =
1423 (DLOAD_SECTION_TYPE(info->type) ==
1424 DLOAD_TEXT) ? DBLL_CODE : DBLL_DATA;
1425 if (target_obj && target_obj->attrs.write) {
1426 ret =
1427 (*target_obj->attrs.write) (target_obj->attrs.input_params,
1428 addr, buf, bytes,
1429 mem_sect_type);
1430
1431 if (target_obj->attrs.log_write) {
1432 sect_info.name = info->name;
1433 sect_info.sect_run_addr = info->run_addr;
1434 sect_info.sect_load_addr = info->load_addr;
1435 sect_info.size = info->size;
1436 sect_info.type = mem_sect_type;
1437 /* Pass the information about what we've written to
1438 * another module */
1439 (*target_obj->attrs.log_write) (target_obj->attrs.
1440 log_write_handle,
1441 &sect_info, addr,
1442 bytes);
1443 }
1444 }
1445 return ret;
1446}
1447
1448/*
1449 * ======== fill_mem ========
1450 * Fill bytes of memory at a given address with a given value by
1451 * writing from a buffer containing the given value. Write in
1452 * sets of MAXEXPR (128) bytes to avoid large stack buffer issues.
1453 */
1454static int fill_mem(struct dynamic_loader_initialize *this, ldr_addr addr,
1455 struct ldr_section_info *info, unsigned bytes, unsigned val)
1456{
1457 bool ret = true;
1458 char *pbuf;
1459 struct dbll_library_obj *lib;
1460 struct dbll_init_obj *init_obj = (struct dbll_init_obj *)this;
1461
1462 DBC_REQUIRE(this != NULL);
1463 lib = init_obj->lib;
1464 pbuf = NULL;
1465 /* Pass the NULL pointer to write_mem to get the start address of Shared
1466 memory. This is a trick to just get the start address, there is no
1467 writing taking place with this Writemem
1468 */
1469 if ((lib->target_obj->attrs.write) != (dbll_write_fxn) no_op)
1470 write_mem(this, &pbuf, addr, info, 0);
1471 if (pbuf)
1472 memset(pbuf, val, bytes);
1473
1474 return ret;
1475}
1476
1477/*
1478 * ======== execute ========
1479 */
1480static int execute(struct dynamic_loader_initialize *this, ldr_addr start)
1481{
1482 struct dbll_init_obj *init_obj = (struct dbll_init_obj *)this;
1483 struct dbll_library_obj *lib;
1484 bool ret = true;
1485
1486 DBC_REQUIRE(this != NULL);
1487 lib = init_obj->lib;
1488 DBC_REQUIRE(lib);
1489 /* Save entry point */
1490 if (lib != NULL)
1491 lib->entry = (u32) start;
1492
1493 return ret;
1494}
1495
1496/*
1497 * ======== release ========
1498 */
1499static void release(struct dynamic_loader_initialize *this)
1500{
1501}
1502
4f551c8f 1503#ifdef CONFIG_TIDSPBRIDGE_BACKTRACE
c4ca3d5a
ORL
1504/**
1505 * find_symbol_context - Basic symbol context structure
1506 * @address: Symbol Adress
1507 * @offset_range: Offset range where the search for the DSP symbol
1508 * started.
1509 * @cur_best_offset: Best offset to start looking for the DSP symbol
1510 * @sym_addr: Address of the DSP symbol
1511 * @name: Symbol name
1512 *
1513 */
1514struct find_symbol_context {
1515 /* input */
1516 u32 address;
1517 u32 offset_range;
1518 /* state */
1519 u32 cur_best_offset;
1520 /* output */
1521 u32 sym_addr;
1522 char name[120];
1523};
1524
1525/**
1526 * find_symbol_callback() - Validates symbol address and copies the symbol name
1527 * to the user data.
1528 * @elem: dsp library context
1529 * @user_data: Find symbol context
1530 *
1531 */
1532void find_symbol_callback(void *elem, void *user_data)
1533{
1534 struct dbll_symbol *symbol = elem;
1535 struct find_symbol_context *context = user_data;
1536 u32 symbol_addr = symbol->value.value;
1537 u32 offset = context->address - symbol_addr;
1538
1539 /*
1540 * Address given should be greater than symbol address,
1541 * symbol address should be within specified range
1542 * and the offset should be better than previous one
1543 */
1544 if (context->address >= symbol_addr && symbol_addr < (u32)-1 &&
1545 offset < context->cur_best_offset) {
1546 context->cur_best_offset = offset;
1547 context->sym_addr = symbol_addr;
1548 strncpy(context->name, symbol->name, sizeof(context->name));
1549 }
1550
1551 return;
1552}
1553
1554/**
1555 * dbll_find_dsp_symbol() - This function retrieves the dsp symbol from the dsp binary.
1556 * @zl_lib: DSP binary obj library pointer
1557 * @address: Given address to find the dsp symbol
1558 * @offset_range: offset range to look for dsp symbol
1559 * @sym_addr_output: Symbol Output address
1560 * @name_output: String with the dsp symbol
1561 *
1562 * This function retrieves the dsp symbol from the dsp binary.
1563 */
1564bool dbll_find_dsp_symbol(struct dbll_library_obj *zl_lib, u32 address,
1565 u32 offset_range, u32 *sym_addr_output,
1566 char *name_output)
1567{
1568 bool status = false;
1569 struct find_symbol_context context;
1570
1571 context.address = address;
1572 context.offset_range = offset_range;
1573 context.cur_best_offset = offset_range;
1574 context.sym_addr = 0;
1575 context.name[0] = '\0';
1576
1577 gh_iterate(zl_lib->sym_tab, find_symbol_callback, &context);
1578
1579 if (context.name[0]) {
1580 status = true;
1581 strcpy(name_output, context.name);
1582 *sym_addr_output = context.sym_addr;
1583 }
1584
1585 return status;
1586}
4f551c8f 1587#endif
This page took 0.086567 seconds and 5 git commands to generate.