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