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