• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/staging/tidspbridge/pmgr/
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 */
55struct 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 */
68struct dbll_stream {
69	struct dynamic_loader_stream dl_stream;
70	struct dbll_library_obj *lib;
71};
72
73/*
74 *  ======== ldr_symbol ========
75 */
76struct ldr_symbol {
77	struct dynamic_loader_sym dl_symbol;
78	struct dbll_library_obj *lib;
79};
80
81/*
82 *  ======== dbll_alloc ========
83 */
84struct dbll_alloc {
85	struct dynamic_loader_allocate dl_alloc;
86	struct dbll_library_obj *lib;
87};
88
89/*
90 *  ======== dbll_init_obj ========
91 */
92struct 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 */
107struct 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 */
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 *  Functions called by dynamic loader
145 *
146 */
147/* dynamic_loader_stream */
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/* dynamic_loader_sym */
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/* dynamic_loader_allocate */
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/* dynamic_loader_initialize */
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/* symbol table hash functions */
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;		/* module reference count */
193
194/* Symbol Redefinition */
195static int redefined_symbol;
196static int gbl_search = 1;
197
198/*
199 *  ======== dbll_close ========
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		/* 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 */
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	/* 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((!status && *target_obj) ||
259				(status && *target_obj == NULL));
260	}
261
262	return status;
263}
264
265/*
266 *  ======== dbll_delete ========
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	if (zl_target != NULL)
276		kfree(zl_target);
277
278}
279
280/*
281 *  ======== dbll_exit ========
282 *  Discontinue usage of DBL module.
283 */
284void 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 */
300bool 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 */
327void 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 */
344bool 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 */
377int 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 (!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 (!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 */
436bool 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 */
451int 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 (!status)
521				opened_doff = true;
522
523		}
524		if (!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 (!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(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 */
574int 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 */
585int 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 (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 (!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	}
697func_cont:
698	if (!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((!status && (zl_lib->open_ref > 0) && *lib_obj)
716				|| (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 */
728int 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 (!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 (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	}
785func_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 */
800void 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 */
815void 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);
846func_end:
847	DBC_ENSURE(zl_lib->load_ref >= 0);
848}
849
850/*
851 *  ======== dbll_unload_sect ========
852 *  Not supported for COFF.
853 */
854int 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 */
866static 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 */
882static 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 */
913static 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 */
936static 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 */
952static 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 */
961static 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 */
976static 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 */
998static 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 */
1022static 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 */
1070static 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 */
1093static 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 */
1150static 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 */
1166static 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 */
1184static 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 */
1199static 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 */
1218static 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	}
1292func_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 (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 */
1337static 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 */
1375static 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 */
1384static 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 */
1402static 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 */
1452static 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 */
1478static 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 */
1497static 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 */
1512struct 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 */
1530void 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 */
1562bool 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
1586