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