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