lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Wed, 23 Jun 2010 16:02:02 +0300
From:	Ohad Ben-Cohen <ohad@...ery.com>
To:	Greg KH <greg@...ah.com>
Cc:	<linux-kernel@...r.kernel.org>, <linux-omap@...r.kernel.org>,
	Hebbar Shivananda <x0hebbar@...com>,
	Ramos Falcon Ernesto <ernesto@...com>,
	Anna Suman <s-anna@...com>, Kanigeri Hari <h-kanigeri2@...com>,
	Felipe Contreras <felipe.contreras@...il.com>,
	Felipe Balbi <felipe.balbi@...ia.com>,
	Hiroshi DOYU <Hiroshi.DOYU@...ia.com>,
	Gupta Ramesh <grgupta@...com>,
	Guzman Lugo Fernando <fernando.lugo@...com>,
	Tony Lindgren <tony@...mide.com>,
	Ameya Palande <ameya.palande@...ia.com>,
	Gomez Castellanos Ivan <ivan.gomez@...com>,
	Andy Shevchenko <ext-andriy.shevchenko@...ia.com>,
	Armando Uribe De Leon <x0095078@...com>,
	Deepak Chitriki <deepak.chitriki@...com>,
	Menon Nishanth <nm@...com>,
	Phil Carmody <ext-phil.2.carmody@...ia.com>,
	Pitney Gilbert <gpitney@...com>, Bhavin Shah <bshah@...com>,
	Omar Ramirez Luna <omar.ramirez@...com>,
	Ohad Ben-Cohen <ohad@...ery.com>
Subject: [PATCH 08/11] staging: ti dspbridge: add DOFF binaries loader

From: Omar Ramirez Luna <omar.ramirez@...com>

Add TI's DSP Bridge DOFF binaries dynamic loader driver sources

Signed-off-by: Omar Ramirez Luna <omar.ramirez@...com>
Signed-off-by: Kanigeri, Hari <h-kanigeri2@...com>
Signed-off-by: Ameya Palande <ameya.palande@...ia.com>
Signed-off-by: Guzman Lugo, Fernando <fernando.lugo@...com>
Signed-off-by: Hebbar, Shivananda <x0hebbar@...com>
Signed-off-by: Ramos Falcon, Ernesto <ernesto@...com>
Signed-off-by: Felipe Contreras <felipe.contreras@...il.com>
Signed-off-by: Anna, Suman <s-anna@...com>
Signed-off-by: Gupta, Ramesh <grgupta@...com>
Signed-off-by: Gomez Castellanos, Ivan <ivan.gomez@...com>
Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko@...ia.com>
Signed-off-by: Armando Uribe De Leon <x0095078@...com>
Signed-off-by: Deepak Chitriki <deepak.chitriki@...com>
Signed-off-by: Menon, Nishanth <nm@...com>
Signed-off-by: Phil Carmody <ext-phil.2.carmody@...ia.com>
Signed-off-by: Ohad Ben-Cohen <ohad@...ery.com>
---
 drivers/staging/tidspbridge/dynload/cload.c        | 1960 ++++++++++++++++++++
 .../staging/tidspbridge/dynload/dload_internal.h   |  351 ++++
 drivers/staging/tidspbridge/dynload/doff.h         |  344 ++++
 drivers/staging/tidspbridge/dynload/getsection.c   |  416 +++++
 drivers/staging/tidspbridge/dynload/header.h       |   55 +
 drivers/staging/tidspbridge/dynload/module_list.h  |  159 ++
 drivers/staging/tidspbridge/dynload/params.h       |  226 +++
 drivers/staging/tidspbridge/dynload/reloc.c        |  484 +++++
 drivers/staging/tidspbridge/dynload/reloc_table.h  |  102 +
 .../tidspbridge/dynload/reloc_table_c6000.c        |  257 +++
 drivers/staging/tidspbridge/dynload/tramp.c        | 1143 ++++++++++++
 .../tidspbridge/dynload/tramp_table_c6000.c        |  164 ++
 12 files changed, 5661 insertions(+), 0 deletions(-)
 create mode 100644 drivers/staging/tidspbridge/dynload/cload.c
 create mode 100644 drivers/staging/tidspbridge/dynload/dload_internal.h
 create mode 100644 drivers/staging/tidspbridge/dynload/doff.h
 create mode 100644 drivers/staging/tidspbridge/dynload/getsection.c
 create mode 100644 drivers/staging/tidspbridge/dynload/header.h
 create mode 100644 drivers/staging/tidspbridge/dynload/module_list.h
 create mode 100644 drivers/staging/tidspbridge/dynload/params.h
 create mode 100644 drivers/staging/tidspbridge/dynload/reloc.c
 create mode 100644 drivers/staging/tidspbridge/dynload/reloc_table.h
 create mode 100644 drivers/staging/tidspbridge/dynload/reloc_table_c6000.c
 create mode 100644 drivers/staging/tidspbridge/dynload/tramp.c
 create mode 100644 drivers/staging/tidspbridge/dynload/tramp_table_c6000.c

diff --git a/drivers/staging/tidspbridge/dynload/cload.c b/drivers/staging/tidspbridge/dynload/cload.c
new file mode 100644
index 0000000..d4f71b5
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/cload.c
@@ -0,0 +1,1960 @@
+/*
+ * cload.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "header.h"
+
+#include "module_list.h"
+#define LINKER_MODULES_HEADER ("_" MODULES_HEADER)
+
+/*
+ * we use the fact that DOFF section records are shaped just like
+ * ldr_section_info to reduce our section storage usage.  This macro marks
+ * the places where that assumption is made
+ */
+#define DOFFSEC_IS_LDRSEC(pdoffsec) ((struct ldr_section_info *)(pdoffsec))
+
+/*
+ * forward references
+ */
+static void dload_symbols(struct dload_state *dlthis);
+static void dload_data(struct dload_state *dlthis);
+static void allocate_sections(struct dload_state *dlthis);
+static void string_table_free(struct dload_state *dlthis);
+static void symbol_table_free(struct dload_state *dlthis);
+static void section_table_free(struct dload_state *dlthis);
+static void init_module_handle(struct dload_state *dlthis);
+#if BITS_PER_AU > BITS_PER_BYTE
+static char *unpack_name(struct dload_state *dlthis, u32 soffset);
+#endif
+
+static const char cinitname[] = { ".cinit" };
+static const char loader_dllview_root[] = { "?DLModules?" };
+
+/*
+ * Error strings
+ */
+static const char readstrm[] = { "Error reading %s from input stream" };
+static const char err_alloc[] = { "Syms->dload_allocate( %d ) failed" };
+static const char tgtalloc[] = {
+	"Target memory allocate failed, section %s size " FMT_UI32 };
+static const char initfail[] = { "%s to target address " FMT_UI32 " failed" };
+static const char dlvwrite[] = { "Write to DLLview list failed" };
+static const char iconnect[] = { "Connect call to init interface failed" };
+static const char err_checksum[] = { "Checksum failed on %s" };
+
+/*************************************************************************
+ * Procedure dload_error
+ *
+ * Parameters:
+ *	errtxt	description of the error, printf style
+ *	...		additional information
+ *
+ * Effect:
+ *	Reports or records the error as appropriate.
+ *********************************************************************** */
+void dload_error(struct dload_state *dlthis, const char *errtxt, ...)
+{
+	va_list args;
+
+	va_start(args, errtxt);
+	dlthis->mysym->error_report(dlthis->mysym, errtxt, args);
+	va_end(args);
+	dlthis->dload_errcount += 1;
+
+}				/* dload_error */
+
+#define DL_ERROR(zza, zzb) dload_error(dlthis, zza, zzb)
+
+/*************************************************************************
+ * Procedure dload_syms_error
+ *
+ * Parameters:
+ *	errtxt	description of the error, printf style
+ *	...		additional information
+ *
+ * Effect:
+ *	Reports or records the error as appropriate.
+ *********************************************************************** */
+void dload_syms_error(struct dynamic_loader_sym *syms, const char *errtxt, ...)
+{
+	va_list args;
+
+	va_start(args, errtxt);
+	syms->error_report(syms, errtxt, args);
+	va_end(args);
+}
+
+/*************************************************************************
+ * Procedure dynamic_load_module
+ *
+ * Parameters:
+ *	module	The input stream that supplies the module image
+ *	syms	Host-side symbol table and malloc/free functions
+ *	alloc	Target-side memory allocation
+ *	init	Target-side memory initialization
+ *	options	Option flags DLOAD_*
+ *	mhandle	A module handle for use with Dynamic_Unload
+ *
+ * Effect:
+ *	The module image is read using *module.  Target storage for the new
+ *	image is
+ * obtained from *alloc.  Symbols defined and referenced by the module are
+ * managed using *syms.  The image is then relocated and references
+ *	resolved as necessary, and the resulting executable bits are placed
+ *	into target memory using *init.
+ *
+ * Returns:
+ *	On a successful load, a module handle is placed in *mhandle,
+ *	and zero is returned.  On error, the number of errors detected is
+ *	returned.  Individual errors are reported during the load process
+ *	using syms->error_report().
+ ********************************************************************** */
+int dynamic_load_module(struct dynamic_loader_stream *module,
+			struct dynamic_loader_sym *syms,
+			struct dynamic_loader_allocate *alloc,
+			struct dynamic_loader_initialize *init,
+			unsigned options, void **mhandle)
+{
+	register unsigned *dp, sz;
+	struct dload_state dl_state;	/* internal state for this call */
+
+	/* blast our internal state */
+	dp = (unsigned *)&dl_state;
+	for (sz = sizeof(dl_state) / sizeof(unsigned); sz > 0; sz -= 1)
+		*dp++ = 0;
+
+	/* Enable _only_ BSS initialization if enabled by user */
+	if ((options & DLOAD_INITBSS) == DLOAD_INITBSS)
+		dl_state.myoptions = DLOAD_INITBSS;
+
+	/* Check that mandatory arguments are present */
+	if (!module || !syms) {
+		dload_error(&dl_state, "Required parameter is NULL");
+	} else {
+		dl_state.strm = module;
+		dl_state.mysym = syms;
+		dload_headers(&dl_state);
+		if (!dl_state.dload_errcount)
+			dload_strings(&dl_state, false);
+		if (!dl_state.dload_errcount)
+			dload_sections(&dl_state);
+
+		if (init && !dl_state.dload_errcount) {
+			if (init->connect(init)) {
+				dl_state.myio = init;
+				dl_state.myalloc = alloc;
+				/* do now, before reducing symbols */
+				allocate_sections(&dl_state);
+			} else
+				dload_error(&dl_state, iconnect);
+		}
+
+		if (!dl_state.dload_errcount) {
+			/* fix up entry point address */
+			unsigned sref = dl_state.dfile_hdr.df_entry_secn - 1;
+			if (sref < dl_state.allocated_secn_count)
+				dl_state.dfile_hdr.df_entrypt +=
+				    dl_state.ldr_sections[sref].run_addr;
+
+			dload_symbols(&dl_state);
+		}
+
+		if (init && !dl_state.dload_errcount)
+			dload_data(&dl_state);
+
+		init_module_handle(&dl_state);
+
+		/* dl_state.myio is init or 0 at this point. */
+		if (dl_state.myio) {
+			if ((!dl_state.dload_errcount) &&
+			    (dl_state.dfile_hdr.df_entry_secn != DN_UNDEF) &&
+			    (!init->execute(init,
+					    dl_state.dfile_hdr.df_entrypt)))
+				dload_error(&dl_state, "Init->Execute Failed");
+			init->release(init);
+		}
+
+		symbol_table_free(&dl_state);
+		section_table_free(&dl_state);
+		string_table_free(&dl_state);
+		dload_tramp_cleanup(&dl_state);
+
+		if (dl_state.dload_errcount) {
+			dynamic_unload_module(dl_state.myhandle, syms, alloc,
+					      init);
+			dl_state.myhandle = NULL;
+		}
+	}
+
+	if (mhandle)
+		*mhandle = dl_state.myhandle;	/* give back the handle */
+
+	return dl_state.dload_errcount;
+}				/* DLOAD_File */
+
+/*************************************************************************
+ * Procedure dynamic_open_module
+ *
+ * Parameters:
+ *      module  The input stream that supplies the module image
+ *      syms    Host-side symbol table and malloc/free functions
+ *      alloc   Target-side memory allocation
+ *      init    Target-side memory initialization
+ *      options Option flags DLOAD_*
+ *      mhandle A module handle for use with Dynamic_Unload
+ *
+ * Effect:
+ *      The module image is read using *module.  Target storage for the new
+ *      image is
+ * 	obtained from *alloc.  Symbols defined and referenced by the module are
+ * 	managed using *syms.  The image is then relocated and references
+ *      resolved as necessary, and the resulting executable bits are placed
+ *      into target memory using *init.
+ *
+ * Returns:
+ *      On a successful load, a module handle is placed in *mhandle,
+ *      and zero is returned.  On error, the number of errors detected is
+ *      returned.  Individual errors are reported during the load process
+ *      using syms->error_report().
+ ********************************************************************** */
+int
+dynamic_open_module(struct dynamic_loader_stream *module,
+		    struct dynamic_loader_sym *syms,
+		    struct dynamic_loader_allocate *alloc,
+		    struct dynamic_loader_initialize *init,
+		    unsigned options, void **mhandle)
+{
+	register unsigned *dp, sz;
+	struct dload_state dl_state;	/* internal state for this call */
+
+	/* blast our internal state */
+	dp = (unsigned *)&dl_state;
+	for (sz = sizeof(dl_state) / sizeof(unsigned); sz > 0; sz -= 1)
+		*dp++ = 0;
+
+	/* Enable _only_ BSS initialization if enabled by user */
+	if ((options & DLOAD_INITBSS) == DLOAD_INITBSS)
+		dl_state.myoptions = DLOAD_INITBSS;
+
+	/* Check that mandatory arguments are present */
+	if (!module || !syms) {
+		dload_error(&dl_state, "Required parameter is NULL");
+	} else {
+		dl_state.strm = module;
+		dl_state.mysym = syms;
+		dload_headers(&dl_state);
+		if (!dl_state.dload_errcount)
+			dload_strings(&dl_state, false);
+		if (!dl_state.dload_errcount)
+			dload_sections(&dl_state);
+
+		if (init && !dl_state.dload_errcount) {
+			if (init->connect(init)) {
+				dl_state.myio = init;
+				dl_state.myalloc = alloc;
+				/* do now, before reducing symbols */
+				allocate_sections(&dl_state);
+			} else
+				dload_error(&dl_state, iconnect);
+		}
+
+		if (!dl_state.dload_errcount) {
+			/* fix up entry point address */
+			unsigned sref = dl_state.dfile_hdr.df_entry_secn - 1;
+			if (sref < dl_state.allocated_secn_count)
+				dl_state.dfile_hdr.df_entrypt +=
+				    dl_state.ldr_sections[sref].run_addr;
+
+			dload_symbols(&dl_state);
+		}
+
+		init_module_handle(&dl_state);
+
+		/* dl_state.myio is either 0 or init at this point. */
+		if (dl_state.myio) {
+			if ((!dl_state.dload_errcount) &&
+			    (dl_state.dfile_hdr.df_entry_secn != DN_UNDEF) &&
+			    (!init->execute(init,
+					    dl_state.dfile_hdr.df_entrypt)))
+				dload_error(&dl_state, "Init->Execute Failed");
+			init->release(init);
+		}
+
+		symbol_table_free(&dl_state);
+		section_table_free(&dl_state);
+		string_table_free(&dl_state);
+
+		if (dl_state.dload_errcount) {
+			dynamic_unload_module(dl_state.myhandle, syms, alloc,
+					      init);
+			dl_state.myhandle = NULL;
+		}
+	}
+
+	if (mhandle)
+		*mhandle = dl_state.myhandle;	/* give back the handle */
+
+	return dl_state.dload_errcount;
+}				/* DLOAD_File */
+
+/*************************************************************************
+ * Procedure dload_headers
+ *
+ * Parameters:
+ *	none
+ *
+ * Effect:
+ *	Loads the DOFF header and verify record.  Deals with any byte-order
+ * issues and checks them for validity.
+ *********************************************************************** */
+#define COMBINED_HEADER_SIZE (sizeof(struct doff_filehdr_t)+ \
+			     sizeof(struct doff_verify_rec_t))
+
+void dload_headers(struct dload_state *dlthis)
+{
+	u32 map;
+
+	/* Read the header and the verify record as one.  If we don't get it
+	   all, we're done */
+	if (dlthis->strm->read_buffer(dlthis->strm, &dlthis->dfile_hdr,
+				      COMBINED_HEADER_SIZE) !=
+	    COMBINED_HEADER_SIZE) {
+		DL_ERROR(readstrm, "File Headers");
+		return;
+	}
+	/*
+	 * Verify that we have the byte order of the file correct.
+	 * If not, must fix it before we can continue
+	 */
+	map = REORDER_MAP(dlthis->dfile_hdr.df_byte_reshuffle);
+	if (map != REORDER_MAP(BYTE_RESHUFFLE_VALUE)) {
+		/* input is either byte-shuffled or bad */
+		if ((map & 0xFCFCFCFC) == 0) {	/* no obviously bogus bits */
+			dload_reorder(&dlthis->dfile_hdr, COMBINED_HEADER_SIZE,
+				      map);
+		}
+		if (dlthis->dfile_hdr.df_byte_reshuffle !=
+		    BYTE_RESHUFFLE_VALUE) {
+			/* didn't fix the problem, the byte swap map is bad */
+			dload_error(dlthis,
+				    "Bad byte swap map " FMT_UI32 " in header",
+				    dlthis->dfile_hdr.df_byte_reshuffle);
+			return;
+		}
+		dlthis->reorder_map = map;	/* keep map for future use */
+	}
+
+	/*
+	 * Verify checksum of header and verify record
+	 */
+	if (~dload_checksum(&dlthis->dfile_hdr,
+			    sizeof(struct doff_filehdr_t)) ||
+	    ~dload_checksum(&dlthis->verify,
+			    sizeof(struct doff_verify_rec_t))) {
+		DL_ERROR(err_checksum, "header or verify record");
+		return;
+	}
+#if HOST_ENDIANNESS
+	dlthis->dfile_hdr.df_byte_reshuffle = map;	/* put back for later */
+#endif
+
+	/* Check for valid target ID */
+	if ((dlthis->dfile_hdr.df_target_id != TARGET_ID) &&
+	    -(dlthis->dfile_hdr.df_target_id != TMS470_ID)) {
+		dload_error(dlthis, "Bad target ID 0x%x and TARGET_ID 0x%x",
+			    dlthis->dfile_hdr.df_target_id, TARGET_ID);
+		return;
+	}
+	/* Check for valid file format */
+	if ((dlthis->dfile_hdr.df_doff_version != DOFF0)) {
+		dload_error(dlthis, "Bad DOFF version 0x%x",
+			    dlthis->dfile_hdr.df_doff_version);
+		return;
+	}
+
+	/*
+	 * Apply reasonableness checks to count fields
+	 */
+	if (dlthis->dfile_hdr.df_strtab_size > MAX_REASONABLE_STRINGTAB) {
+		dload_error(dlthis, "Excessive string table size " FMT_UI32,
+			    dlthis->dfile_hdr.df_strtab_size);
+		return;
+	}
+	if (dlthis->dfile_hdr.df_no_scns > MAX_REASONABLE_SECTIONS) {
+		dload_error(dlthis, "Excessive section count 0x%x",
+			    dlthis->dfile_hdr.df_no_scns);
+		return;
+	}
+#ifndef TARGET_ENDIANNESS
+	/*
+	 * Check that endianness does not disagree with explicit specification
+	 */
+	if ((dlthis->dfile_hdr.df_flags >> ALIGN_COFF_ENDIANNESS) &
+	    dlthis->myoptions & ENDIANNESS_MASK) {
+		dload_error(dlthis,
+			    "Input endianness disagrees with specified option");
+		return;
+	}
+	dlthis->big_e_target = dlthis->dfile_hdr.df_flags & DF_BIG;
+#endif
+
+}				/* dload_headers */
+
+/*	COFF Section Processing
+ *
+ *	COFF sections are read in and retained intact.  Each record is embedded
+ * 	in a new structure that records the updated load and
+ * 	run addresses of the section */
+
+static const char secn_errid[] = { "section" };
+
+/*************************************************************************
+ * Procedure dload_sections
+ *
+ * Parameters:
+ *	none
+ *
+ * Effect:
+ *	Loads the section records into an internal table.
+ *********************************************************************** */
+void dload_sections(struct dload_state *dlthis)
+{
+	s16 siz;
+	struct doff_scnhdr_t *shp;
+	unsigned nsecs = dlthis->dfile_hdr.df_no_scns;
+
+	/* allocate space for the DOFF section records */
+	siz = nsecs * sizeof(struct doff_scnhdr_t);
+	shp =
+	    (struct doff_scnhdr_t *)dlthis->mysym->dload_allocate(dlthis->mysym,
+								  siz);
+	if (!shp) {		/* not enough storage */
+		DL_ERROR(err_alloc, siz);
+		return;
+	}
+	dlthis->sect_hdrs = shp;
+
+	/* read in the section records */
+	if (dlthis->strm->read_buffer(dlthis->strm, shp, siz) != siz) {
+		DL_ERROR(readstrm, secn_errid);
+		return;
+	}
+
+	/* if we need to fix up byte order, do it now */
+	if (dlthis->reorder_map)
+		dload_reorder(shp, siz, dlthis->reorder_map);
+
+	/* check for validity */
+	if (~dload_checksum(dlthis->sect_hdrs, siz) !=
+	    dlthis->verify.dv_scn_rec_checksum) {
+		DL_ERROR(err_checksum, secn_errid);
+		return;
+	}
+
+}				/* dload_sections */
+
+/*****************************************************************************
+ * Procedure allocate_sections
+ *
+ * Parameters:
+ *	alloc	target memory allocator class
+ *
+ * Effect:
+ *	Assigns new (target) addresses for sections
+ **************************************************************************** */
+static void allocate_sections(struct dload_state *dlthis)
+{
+	u16 curr_sect, nsecs, siz;
+	struct doff_scnhdr_t *shp;
+	struct ldr_section_info *asecs;
+	struct my_handle *hndl;
+	nsecs = dlthis->dfile_hdr.df_no_scns;
+	if (!nsecs)
+		return;
+	if ((dlthis->myalloc == NULL) &&
+	    (dlthis->dfile_hdr.df_target_scns > 0)) {
+		DL_ERROR("Arg 3 (alloc) required but NULL", 0);
+		return;
+	}
+	/*
+	 * allocate space for the module handle, which we will keep for unload
+	 * purposes include an additional section store for an auto-generated
+	 * trampoline section in case we need it.
+	 */
+	siz = (dlthis->dfile_hdr.df_target_scns + 1) *
+	    sizeof(struct ldr_section_info) + MY_HANDLE_SIZE;
+
+	hndl =
+	    (struct my_handle *)dlthis->mysym->dload_allocate(dlthis->mysym,
+							      siz);
+	if (!hndl) {		/* not enough storage */
+		DL_ERROR(err_alloc, siz);
+		return;
+	}
+	/* initialize the handle header */
+	hndl->dm.hnext = hndl->dm.hprev = hndl;	/* circular list */
+	hndl->dm.hroot = NULL;
+	hndl->dm.dbthis = 0;
+	dlthis->myhandle = hndl;	/* save away for return */
+	/* pointer to the section list of allocated sections */
+	dlthis->ldr_sections = asecs = hndl->secns;
+	/* * Insert names into all sections, make copies of
+	   the sections we allocate */
+	shp = dlthis->sect_hdrs;
+	for (curr_sect = 0; curr_sect < nsecs; curr_sect++) {
+		u32 soffset = shp->ds_offset;
+#if BITS_PER_AU <= BITS_PER_BYTE
+		/* attempt to insert the name of this section */
+		if (soffset < dlthis->dfile_hdr.df_strtab_size)
+			DOFFSEC_IS_LDRSEC(shp)->name = dlthis->str_head +
+			    soffset;
+		else {
+			dload_error(dlthis, "Bad name offset in section %d",
+				    curr_sect);
+			DOFFSEC_IS_LDRSEC(shp)->name = NULL;
+		}
+#endif
+		/* allocate target storage for sections that require it */
+		if (DS_NEEDS_ALLOCATION(shp)) {
+			*asecs = *DOFFSEC_IS_LDRSEC(shp);
+			asecs->context = 0;	/* zero the context field */
+#if BITS_PER_AU > BITS_PER_BYTE
+			asecs->name = unpack_name(dlthis, soffset);
+			dlthis->debug_string_size = soffset + dlthis->temp_len;
+#else
+			dlthis->debug_string_size = soffset;
+#endif
+			if (dlthis->myalloc != NULL) {
+				if (!dlthis->myalloc->
+				    dload_allocate(dlthis->myalloc, asecs,
+						   DS_ALIGNMENT(asecs->type))) {
+					dload_error(dlthis, tgtalloc,
+						    asecs->name, asecs->size);
+					return;
+				}
+			}
+			/* keep address deltas in original section table */
+			shp->ds_vaddr = asecs->load_addr - shp->ds_vaddr;
+			shp->ds_paddr = asecs->run_addr - shp->ds_paddr;
+			dlthis->allocated_secn_count += 1;
+		}		/* allocate target storage */
+		shp += 1;
+		asecs += 1;
+	}
+#if BITS_PER_AU <= BITS_PER_BYTE
+	dlthis->debug_string_size +=
+	    strlen(dlthis->str_head + dlthis->debug_string_size) + 1;
+#endif
+}				/* allocate sections */
+
+/*************************************************************************
+ * Procedure section_table_free
+ *
+ * Parameters:
+ *	none
+ *
+ * Effect:
+ *	Frees any state used by the symbol table.
+ *
+ * WARNING:
+ *	This routine is not allowed to declare errors!
+ *********************************************************************** */
+static void section_table_free(struct dload_state *dlthis)
+{
+	struct doff_scnhdr_t *shp;
+
+	shp = dlthis->sect_hdrs;
+	if (shp)
+		dlthis->mysym->dload_deallocate(dlthis->mysym, shp);
+
+}				/* section_table_free */
+
+/*************************************************************************
+ * Procedure dload_strings
+ *
+ * Parameters:
+ *  sec_names_only   If true only read in the "section names"
+ *		     portion of the string table
+ *
+ * Effect:
+ *	Loads the DOFF string table into memory. DOFF keeps all strings in a
+ * big unsorted array.  We just read that array into memory in bulk.
+ *********************************************************************** */
+static const char stringtbl[] = { "string table" };
+
+void dload_strings(struct dload_state *dlthis, bool sec_names_only)
+{
+	u32 ssiz;
+	char *strbuf;
+
+	if (sec_names_only) {
+		ssiz = BYTE_TO_HOST(DOFF_ALIGN
+				    (dlthis->dfile_hdr.df_scn_name_size));
+	} else {
+		ssiz = BYTE_TO_HOST(DOFF_ALIGN
+				    (dlthis->dfile_hdr.df_strtab_size));
+	}
+	if (ssiz == 0)
+		return;
+
+	/* get some memory for the string table */
+#if BITS_PER_AU > BITS_PER_BYTE
+	strbuf = (char *)dlthis->mysym->dload_allocate(dlthis->mysym, ssiz +
+						       dlthis->dfile_hdr.
+						       df_max_str_len);
+#else
+	strbuf = (char *)dlthis->mysym->dload_allocate(dlthis->mysym, ssiz);
+#endif
+	if (strbuf == NULL) {
+		DL_ERROR(err_alloc, ssiz);
+		return;
+	}
+	dlthis->str_head = strbuf;
+#if BITS_PER_AU > BITS_PER_BYTE
+	dlthis->str_temp = strbuf + ssiz;
+#endif
+	/* read in the strings and verify them */
+	if ((unsigned)(dlthis->strm->read_buffer(dlthis->strm, strbuf,
+						 ssiz)) != ssiz) {
+		DL_ERROR(readstrm, stringtbl);
+	}
+	/* if we need to fix up byte order, do it now */
+#ifndef _BIG_ENDIAN
+	if (dlthis->reorder_map)
+		dload_reorder(strbuf, ssiz, dlthis->reorder_map);
+
+	if ((!sec_names_only) && (~dload_checksum(strbuf, ssiz) !=
+				  dlthis->verify.dv_str_tab_checksum)) {
+		DL_ERROR(err_checksum, stringtbl);
+	}
+#else
+	if (dlthis->dfile_hdr.df_byte_reshuffle !=
+	    HOST_BYTE_ORDER(REORDER_MAP(BYTE_RESHUFFLE_VALUE))) {
+		/* put strings in big-endian order, not in PC order */
+		dload_reorder(strbuf, ssiz,
+			      HOST_BYTE_ORDER(dlthis->
+					      dfile_hdr.df_byte_reshuffle));
+	}
+	if ((!sec_names_only) && (~dload_reverse_checksum(strbuf, ssiz) !=
+				  dlthis->verify.dv_str_tab_checksum)) {
+		DL_ERROR(err_checksum, stringtbl);
+	}
+#endif
+}				/* dload_strings */
+
+/*************************************************************************
+ * Procedure string_table_free
+ *
+ * Parameters:
+ *	none
+ *
+ * Effect:
+ *	Frees any state used by the string table.
+ *
+ * WARNING:
+ *	This routine is not allowed to declare errors!
+ ************************************************************************ */
+static void string_table_free(struct dload_state *dlthis)
+{
+	if (dlthis->str_head)
+		dlthis->mysym->dload_deallocate(dlthis->mysym,
+						dlthis->str_head);
+
+}				/* string_table_free */
+
+/*
+ * Symbol Table Maintenance Functions
+ *
+ * COFF symbols are read by dload_symbols(), which is called after
+ * sections have been allocated.  Symbols which might be used in
+ * relocation (ie, not debug info) are retained in an internal temporary
+ * compressed table (type local_symbol). A particular symbol is recovered
+ * by index by calling dload_find_symbol().  dload_find_symbol
+ * reconstructs a more explicit representation (type SLOTVEC) which is
+ * used by reloc.c
+ */
+/* real size of debug header */
+#define DBG_HDR_SIZE (sizeof(struct dll_module) - sizeof(struct dll_sect))
+
+static const char sym_errid[] = { "symbol" };
+
+/**************************************************************************
+ * Procedure dload_symbols
+ *
+ * Parameters:
+ *	none
+ *
+ * Effect:
+ *	Reads in symbols and retains ones that might be needed for relocation
+ * purposes.
+ *********************************************************************** */
+/* size of symbol buffer no bigger than target data buffer, to limit stack
+ * usage */
+#define MY_SYM_BUF_SIZ (BYTE_TO_HOST(IMAGE_PACKET_SIZE)/\
+			sizeof(struct doff_syment_t))
+
+static void dload_symbols(struct dload_state *dlthis)
+{
+	u32 sym_count, siz, dsiz, symbols_left;
+	u32 checks;
+	struct local_symbol *sp;
+	struct dynload_symbol *symp;
+	struct dynload_symbol *newsym;
+
+	sym_count = dlthis->dfile_hdr.df_no_syms;
+	if (sym_count == 0)
+		return;
+
+	/*
+	 * We keep a local symbol table for all of the symbols in the input.
+	 * This table contains only section & value info, as we do not have
+	 * to do any name processing for locals.  We reuse this storage
+	 * as a temporary for .dllview record construction.
+	 * Allocate storage for the whole table.  Add 1 to the section count
+	 * in case a trampoline section is auto-generated as well as the
+	 * size of the trampoline section name so DLLView doens't get lost.
+	 */
+
+	siz = sym_count * sizeof(struct local_symbol);
+	dsiz = DBG_HDR_SIZE +
+	    (sizeof(struct dll_sect) * dlthis->allocated_secn_count) +
+	    BYTE_TO_HOST_ROUND(dlthis->debug_string_size + 1);
+	if (dsiz > siz)
+		siz = dsiz;	/* larger of symbols and .dllview temp */
+	sp = (struct local_symbol *)dlthis->mysym->dload_allocate(dlthis->mysym,
+								  siz);
+	if (!sp) {
+		DL_ERROR(err_alloc, siz);
+		return;
+	}
+	dlthis->local_symtab = sp;
+	/* Read the symbols in the input, store them in the table, and post any
+	 * globals to the global symbol table.  In the process, externals
+	 become defined from the global symbol table */
+	checks = dlthis->verify.dv_sym_tab_checksum;
+	symbols_left = sym_count;
+	do {			/* read all symbols */
+		char *sname;
+		u32 val;
+		s32 delta;
+		struct doff_syment_t *input_sym;
+		unsigned syms_in_buf;
+		struct doff_syment_t my_sym_buf[MY_SYM_BUF_SIZ];
+		input_sym = my_sym_buf;
+		syms_in_buf = symbols_left > MY_SYM_BUF_SIZ ?
+		    MY_SYM_BUF_SIZ : symbols_left;
+		siz = syms_in_buf * sizeof(struct doff_syment_t);
+		if (dlthis->strm->read_buffer(dlthis->strm, input_sym, siz) !=
+		    siz) {
+			DL_ERROR(readstrm, sym_errid);
+			return;
+		}
+		if (dlthis->reorder_map)
+			dload_reorder(input_sym, siz, dlthis->reorder_map);
+
+		checks += dload_checksum(input_sym, siz);
+		do {		/* process symbols in buffer */
+			symbols_left -= 1;
+			/* attempt to derive the name of this symbol */
+			sname = NULL;
+			if (input_sym->dn_offset > 0) {
+#if BITS_PER_AU <= BITS_PER_BYTE
+				if ((u32) input_sym->dn_offset <
+				    dlthis->dfile_hdr.df_strtab_size)
+					sname = dlthis->str_head +
+					    BYTE_TO_HOST(input_sym->dn_offset);
+				else
+					dload_error(dlthis,
+						    "Bad name offset in symbol "
+						    " %d", symbols_left);
+#else
+				sname = unpack_name(dlthis,
+						    input_sym->dn_offset);
+#endif
+			}
+			val = input_sym->dn_value;
+			delta = 0;
+			sp->sclass = input_sym->dn_sclass;
+			sp->secnn = input_sym->dn_scnum;
+			/* if this is an undefined symbol,
+			 * define it (or fail) now */
+			if (sp->secnn == DN_UNDEF) {
+				/* pointless for static undefined */
+				if (input_sym->dn_sclass != DN_EXT)
+					goto loop_cont;
+
+				/* try to define symbol from previously
+				 * loaded images */
+				symp = dlthis->mysym->find_matching_symbol
+				    (dlthis->mysym, sname);
+				if (!symp) {
+					DL_ERROR
+					    ("Undefined external symbol %s",
+					     sname);
+					goto loop_cont;
+				}
+				val = delta = symp->value;
+#ifdef ENABLE_TRAMP_DEBUG
+				dload_syms_error(dlthis->mysym,
+						 "===> ext sym [%s] at %x",
+						 sname, val);
+#endif
+
+				goto loop_cont;
+			}
+			/* symbol defined by this module */
+			if (sp->secnn > 0) {
+				/* symbol references a section */
+				if ((unsigned)sp->secnn <=
+				    dlthis->allocated_secn_count) {
+					/* section was allocated */
+					struct doff_scnhdr_t *srefp =
+					    &dlthis->sect_hdrs[sp->secnn - 1];
+
+					if (input_sym->dn_sclass ==
+					    DN_STATLAB ||
+					    input_sym->dn_sclass == DN_EXTLAB) {
+						/* load */
+						delta = srefp->ds_vaddr;
+					} else {
+						/* run */
+						delta = srefp->ds_paddr;
+					}
+					val += delta;
+				}
+				goto loop_itr;
+			}
+			/* This symbol is an absolute symbol */
+			if (sp->secnn == DN_ABS && ((sp->sclass == DN_EXT) ||
+						    (sp->sclass ==
+						     DN_EXTLAB))) {
+				symp =
+				    dlthis->mysym->find_matching_symbol(dlthis->
+									mysym,
+									sname);
+				if (!symp)
+					goto loop_itr;
+				/* This absolute symbol is already defined. */
+				if (symp->value == input_sym->dn_value) {
+					/* If symbol values are equal, continue
+					 * but don't add to the global symbol
+					 * table */
+					sp->value = val;
+					sp->delta = delta;
+					sp += 1;
+					input_sym += 1;
+					continue;
+				} else {
+					/* If symbol values are not equal,
+					 * return with redefinition error */
+					DL_ERROR("Absolute symbol %s is "
+						 "defined multiple times with "
+						 "different values", sname);
+					return;
+				}
+			}
+loop_itr:
+			/* if this is a global symbol, post it to the
+			 * global table */
+			if (input_sym->dn_sclass == DN_EXT ||
+			    input_sym->dn_sclass == DN_EXTLAB) {
+				/* Keep this global symbol for subsequent
+				 * modules. Don't complain on error, to allow
+				 * symbol API to suppress global symbols */
+				if (!sname)
+					goto loop_cont;
+
+				newsym = dlthis->mysym->add_to_symbol_table
+				    (dlthis->mysym, sname,
+				     (unsigned)dlthis->myhandle);
+				if (newsym)
+					newsym->value = val;
+
+			}	/* global */
+loop_cont:
+			sp->value = val;
+			sp->delta = delta;
+			sp += 1;
+			input_sym += 1;
+		} while ((syms_in_buf -= 1) > 0);	/* process sym in buf */
+	} while (symbols_left > 0);	/* read all symbols */
+	if (~checks)
+		dload_error(dlthis, "Checksum of symbols failed");
+
+}				/* dload_symbols */
+
+/*****************************************************************************
+ * Procedure symbol_table_free
+ *
+ * Parameters:
+ *	none
+ *
+ * Effect:
+ *	Frees any state used by the symbol table.
+ *
+ * WARNING:
+ *	This routine is not allowed to declare errors!
+ **************************************************************************** */
+static void symbol_table_free(struct dload_state *dlthis)
+{
+	if (dlthis->local_symtab) {
+		if (dlthis->dload_errcount) {	/* blow off our symbols */
+			dlthis->mysym->purge_symbol_table(dlthis->mysym,
+							  (unsigned)
+							  dlthis->myhandle);
+		}
+		dlthis->mysym->dload_deallocate(dlthis->mysym,
+						dlthis->local_symtab);
+	}
+}				/* symbol_table_free */
+
+/* .cinit Processing
+ *
+ * The dynamic loader does .cinit interpretation.  cload_cinit()
+ * acts as a special write-to-target function, in that it takes relocated
+ * data from the normal data flow, and interprets it as .cinit actions.
+ * Because the normal data flow does not  necessarily process the whole
+ * .cinit section in one buffer, cload_cinit() must be prepared to
+ * interpret the data piecemeal.  A state machine is used for this
+ * purpose.
+ */
+
+/* The following are only for use by reloc.c and things it calls */
+static const struct ldr_section_info cinit_info_init = { cinitname, 0, 0,
+	(ldr_addr)-1, 0, DLOAD_BSS, 0
+};
+
+/*************************************************************************
+ * Procedure cload_cinit
+ *
+ * Parameters:
+ *	ipacket		Pointer to data packet to be loaded
+ *
+ * Effect:
+ *	Interprets the data in the buffer as .cinit data, and performs the
+ * appropriate initializations.
+ *********************************************************************** */
+static void cload_cinit(struct dload_state *dlthis,
+			struct image_packet_t *ipacket)
+{
+#if TDATA_TO_HOST(CINIT_COUNT)*BITS_PER_AU > 16
+	s32 init_count, left;
+#else
+	s16 init_count, left;
+#endif
+	unsigned char *pktp = ipacket->img_data;
+	unsigned char *pktend = pktp + BYTE_TO_HOST_ROUND(ipacket->packet_size);
+	int temp;
+	ldr_addr atmp;
+	struct ldr_section_info cinit_info;
+
+	/*  PROCESS ALL THE INITIALIZATION RECORDS IN THE BUFFER. */
+	while (true) {
+		left = pktend - pktp;
+		switch (dlthis->cinit_state) {
+		case CI_COUNT:	/* count field */
+			if (left < TDATA_TO_HOST(CINIT_COUNT))
+				goto loopexit;
+			temp = dload_unpack(dlthis, (tgt_au_t *) pktp,
+					    CINIT_COUNT * TDATA_AU_BITS, 0,
+					    ROP_SGN);
+			pktp += TDATA_TO_HOST(CINIT_COUNT);
+			/* negative signifies BSS table, zero means done */
+			if (temp <= 0) {
+				dlthis->cinit_state = CI_DONE;
+				break;
+			}
+			dlthis->cinit_count = temp;
+			dlthis->cinit_state = CI_ADDRESS;
+			break;
+#if CINIT_ALIGN < CINIT_ADDRESS
+		case CI_PARTADDRESS:
+			pktp -= TDATA_TO_HOST(CINIT_ALIGN);
+			/* back up pointer into space courtesy of caller */
+			*(uint16_t *) pktp = dlthis->cinit_addr;
+			/* stuff in saved bits  !! FALL THRU !! */
+#endif
+		case CI_ADDRESS:	/* Address field for a copy packet */
+			if (left < TDATA_TO_HOST(CINIT_ADDRESS)) {
+#if CINIT_ALIGN < CINIT_ADDRESS
+				if (left == TDATA_TO_HOST(CINIT_ALIGN)) {
+					/* address broken into halves */
+					dlthis->cinit_addr = *(uint16_t *) pktp;
+					/* remember 1st half */
+					dlthis->cinit_state = CI_PARTADDRESS;
+					left = 0;
+				}
+#endif
+				goto loopexit;
+			}
+			atmp = dload_unpack(dlthis, (tgt_au_t *) pktp,
+					    CINIT_ADDRESS * TDATA_AU_BITS, 0,
+					    ROP_UNS);
+			pktp += TDATA_TO_HOST(CINIT_ADDRESS);
+#if CINIT_PAGE_BITS > 0
+			dlthis->cinit_page = atmp &
+			    ((1 << CINIT_PAGE_BITS) - 1);
+			atmp >>= CINIT_PAGE_BITS;
+#else
+			dlthis->cinit_page = CINIT_DEFAULT_PAGE;
+#endif
+			dlthis->cinit_addr = atmp;
+			dlthis->cinit_state = CI_COPY;
+			break;
+		case CI_COPY:	/* copy bits to the target */
+			init_count = HOST_TO_TDATA(left);
+			if (init_count > dlthis->cinit_count)
+				init_count = dlthis->cinit_count;
+			if (init_count == 0)
+				goto loopexit;	/* get more bits */
+			cinit_info = cinit_info_init;
+			cinit_info.page = dlthis->cinit_page;
+			if (!dlthis->myio->writemem(dlthis->myio, pktp,
+						   TDATA_TO_TADDR
+						   (dlthis->cinit_addr),
+						   &cinit_info,
+						   TDATA_TO_HOST(init_count))) {
+				dload_error(dlthis, initfail, "write",
+					    dlthis->cinit_addr);
+			}
+			dlthis->cinit_count -= init_count;
+			if (dlthis->cinit_count <= 0) {
+				dlthis->cinit_state = CI_COUNT;
+				init_count = (init_count + CINIT_ALIGN - 1) &
+				    -CINIT_ALIGN;
+				/* align to next init */
+			}
+			pktp += TDATA_TO_HOST(init_count);
+			dlthis->cinit_addr += init_count;
+			break;
+		case CI_DONE:	/* no more .cinit to do */
+			return;
+		}		/* switch (cinit_state) */
+	}			/* while */
+
+loopexit:
+	if (left > 0) {
+		dload_error(dlthis, "%d bytes left over in cinit packet", left);
+		dlthis->cinit_state = CI_DONE;	/* left over bytes are bad */
+	}
+}				/* cload_cinit */
+
+/*	Functions to interface to reloc.c
+ *
+ * reloc.c is the relocation module borrowed from the linker, with
+ * minimal (we hope) changes for our purposes.  cload_sect_data() invokes
+ * this module on a section to relocate and load the image data for that
+ * section.  The actual read and write actions are supplied by the global
+ * routines below.
+ */
+
+/************************************************************************
+ * Procedure relocate_packet
+ *
+ * Parameters:
+ *	ipacket		Pointer to an image packet to relocate
+ *
+ * Effect:
+ *	Performs the required relocations on the packet.  Returns a checksum
+ * of the relocation operations.
+ *********************************************************************** */
+#define MY_RELOC_BUF_SIZ 8
+/* careful! exists at the same time as the image buffer */
+static int relocate_packet(struct dload_state *dlthis,
+			   struct image_packet_t *ipacket,
+			   u32 *checks, bool *tramps_generated)
+{
+	u32 rnum;
+	*tramps_generated = false;
+
+	rnum = ipacket->num_relocs;
+	do {			/* all relocs */
+		unsigned rinbuf;
+		int siz;
+		struct reloc_record_t *rp, rrec[MY_RELOC_BUF_SIZ];
+		rp = rrec;
+		rinbuf = rnum > MY_RELOC_BUF_SIZ ? MY_RELOC_BUF_SIZ : rnum;
+		siz = rinbuf * sizeof(struct reloc_record_t);
+		if (dlthis->strm->read_buffer(dlthis->strm, rp, siz) != siz) {
+			DL_ERROR(readstrm, "relocation");
+			return 0;
+		}
+		/* reorder the bytes if need be */
+		if (dlthis->reorder_map)
+			dload_reorder(rp, siz, dlthis->reorder_map);
+
+		*checks += dload_checksum(rp, siz);
+		do {
+			/* perform the relocation operation */
+			dload_relocate(dlthis, (tgt_au_t *) ipacket->img_data,
+				       rp, tramps_generated, false);
+			rp += 1;
+			rnum -= 1;
+		} while ((rinbuf -= 1) > 0);
+	} while (rnum > 0);	/* all relocs */
+	/* If trampoline(s) were generated, we need to do an update of the
+	 * trampoline copy of the packet since a 2nd phase relo will be done
+	 * later. */
+	if (*tramps_generated == true) {
+		dload_tramp_pkt_udpate(dlthis,
+				       (dlthis->image_secn -
+					dlthis->ldr_sections),
+				       dlthis->image_offset, ipacket);
+	}
+
+	return 1;
+}				/* dload_read_reloc */
+
+#define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
+
+/* VERY dangerous */
+static const char imagepak[] = { "image packet" };
+
+/*************************************************************************
+ * Procedure dload_data
+ *
+ * Parameters:
+ *	none
+ *
+ * Effect:
+ *	Read image data from input file, relocate it, and download it to the
+ *	target.
+ *********************************************************************** */
+static void dload_data(struct dload_state *dlthis)
+{
+	u16 curr_sect;
+	struct doff_scnhdr_t *sptr = dlthis->sect_hdrs;
+	struct ldr_section_info *lptr = dlthis->ldr_sections;
+#ifdef OPT_ZERO_COPY_LOADER
+	bool zero_copy = false;
+#endif
+	u8 *dest;
+
+	struct {
+		struct image_packet_t ipacket;
+		u8 bufr[BYTE_TO_HOST(IMAGE_PACKET_SIZE)];
+	} ibuf;
+
+	/* Indicates whether CINIT processing has occurred */
+	bool cinit_processed = false;
+
+	/* Loop through the sections and load them one at a time.
+	 */
+	for (curr_sect = 0; curr_sect < dlthis->dfile_hdr.df_no_scns;
+	     curr_sect += 1) {
+		if (DS_NEEDS_DOWNLOAD(sptr)) {
+			s32 nip;
+			ldr_addr image_offset = 0;
+			/* set relocation info for this section */
+			if (curr_sect < dlthis->allocated_secn_count)
+				dlthis->delta_runaddr = sptr->ds_paddr;
+			else {
+				lptr = DOFFSEC_IS_LDRSEC(sptr);
+				dlthis->delta_runaddr = 0;
+			}
+			dlthis->image_secn = lptr;
+#if BITS_PER_AU > BITS_PER_BYTE
+			lptr->name = unpack_name(dlthis, sptr->ds_offset);
+#endif
+			nip = sptr->ds_nipacks;
+			while ((nip -= 1) >= 0) {	/* process packets */
+
+				s32 ipsize;
+				u32 checks;
+				bool tramp_generated = false;
+
+				/* get the fixed header bits */
+				if (dlthis->strm->read_buffer(dlthis->strm,
+							      &ibuf.ipacket,
+							      IPH_SIZE) !=
+				    IPH_SIZE) {
+					DL_ERROR(readstrm, imagepak);
+					return;
+				}
+				/* reorder the header if need be */
+				if (dlthis->reorder_map) {
+					dload_reorder(&ibuf.ipacket, IPH_SIZE,
+						      dlthis->reorder_map);
+				}
+				/* now read the rest of the packet */
+				ipsize =
+				    BYTE_TO_HOST(DOFF_ALIGN
+						 (ibuf.ipacket.packet_size));
+				if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) {
+					DL_ERROR("Bad image packet size %d",
+						 ipsize);
+					return;
+				}
+				dest = ibuf.bufr;
+#ifdef OPT_ZERO_COPY_LOADER
+				zero_copy = false;
+				if (DLOAD_SECT_TYPE(sptr) != DLOAD_CINIT) {
+					dlthis->myio->writemem(dlthis->myio,
+							       &dest,
+							       lptr->load_addr +
+							       image_offset,
+							       lptr, 0);
+					zero_copy = (dest != ibuf.bufr);
+				}
+#endif
+				/* End of determination */
+
+				if (dlthis->strm->read_buffer(dlthis->strm,
+							      ibuf.bufr,
+							      ipsize) !=
+				    ipsize) {
+					DL_ERROR(readstrm, imagepak);
+					return;
+				}
+				ibuf.ipacket.img_data = dest;
+
+				/* reorder the bytes if need be */
+#if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
+				if (dlthis->reorder_map) {
+					dload_reorder(dest, ipsize,
+						      dlthis->reorder_map);
+				}
+				checks = dload_checksum(dest, ipsize);
+#else
+				if (dlthis->dfile_hdr.df_byte_reshuffle !=
+				    TARGET_ORDER(REORDER_MAP
+						 (BYTE_RESHUFFLE_VALUE))) {
+					/* put image bytes in big-endian order,
+					 * not PC order */
+					dload_reorder(dest, ipsize,
+						      TARGET_ORDER
+						      (dlthis->dfile_hdr.
+						       df_byte_reshuffle));
+				}
+#if TARGET_AU_BITS > 8
+				checks = dload_reverse_checksum16(dest, ipsize);
+#else
+				checks = dload_reverse_checksum(dest, ipsize);
+#endif
+#endif
+
+				checks += dload_checksum(&ibuf.ipacket,
+							 IPH_SIZE);
+				/* relocate the image bits as needed */
+				if (ibuf.ipacket.num_relocs) {
+					dlthis->image_offset = image_offset;
+					if (!relocate_packet(dlthis,
+							     &ibuf.ipacket,
+							     &checks,
+							     &tramp_generated))
+						return;	/* serious error */
+				}
+				if (~checks)
+					DL_ERROR(err_checksum, imagepak);
+				/* Only write the result to the target if no
+				 * trampoline was generated.  Otherwise it
+				 *will be done during trampoline finalize. */
+
+				if (tramp_generated == false) {
+
+					/* stuff the result into target
+					 * memory */
+					if (DLOAD_SECT_TYPE(sptr) ==
+					    DLOAD_CINIT) {
+						cload_cinit(dlthis,
+							    &ibuf.ipacket);
+						cinit_processed = true;
+					} else {
+#ifdef OPT_ZERO_COPY_LOADER
+						if (!zero_copy) {
+#endif
+							/* FIXME */
+							if (!dlthis->myio->
+							    writemem(dlthis->
+								myio,
+								ibuf.bufr,
+								lptr->
+								load_addr +
+								image_offset,
+								lptr,
+								BYTE_TO_HOST
+								(ibuf.
+								ipacket.
+								packet_size))) {
+								DL_ERROR
+								  ("Write to "
+								  FMT_UI32
+								  " failed",
+								  lptr->
+								  load_addr +
+								  image_offset);
+							}
+#ifdef OPT_ZERO_COPY_LOADER
+						}
+#endif
+					}
+				}
+				image_offset +=
+				    BYTE_TO_TADDR(ibuf.ipacket.packet_size);
+			}	/* process packets */
+			/* if this is a BSS section, we may want to fill it */
+			if (DLOAD_SECT_TYPE(sptr) != DLOAD_BSS)
+				goto loop_cont;
+
+			if (!(dlthis->myoptions & DLOAD_INITBSS))
+				goto loop_cont;
+
+			if (cinit_processed) {
+				/* Don't clear BSS after load-time
+				 * initialization */
+				DL_ERROR
+				    ("Zero-initialization at " FMT_UI32
+				     " after " "load-time initialization!",
+				     lptr->load_addr);
+				goto loop_cont;
+			}
+			/* fill the .bss area */
+			dlthis->myio->fillmem(dlthis->myio,
+					      TADDR_TO_HOST(lptr->load_addr),
+					      lptr, TADDR_TO_HOST(lptr->size),
+					      DLOAD_FILL_BSS);
+			goto loop_cont;
+		}
+		/* if DS_DOWNLOAD_MASK */
+		/* If not loading, but BSS, zero initialize */
+		if (DLOAD_SECT_TYPE(sptr) != DLOAD_BSS)
+			goto loop_cont;
+
+		if (!(dlthis->myoptions & DLOAD_INITBSS))
+			goto loop_cont;
+
+		if (curr_sect >= dlthis->allocated_secn_count)
+			lptr = DOFFSEC_IS_LDRSEC(sptr);
+
+		if (cinit_processed) {
+			/*Don't clear BSS after load-time initialization */
+			DL_ERROR("Zero-initialization at " FMT_UI32
+				 " attempted after "
+				 "load-time initialization!", lptr->load_addr);
+			goto loop_cont;
+		}
+		/* fill the .bss area */
+		dlthis->myio->fillmem(dlthis->myio,
+				      TADDR_TO_HOST(lptr->load_addr), lptr,
+				      TADDR_TO_HOST(lptr->size),
+				      DLOAD_FILL_BSS);
+loop_cont:
+		sptr += 1;
+		lptr += 1;
+	}			/* load sections */
+
+	/*  Finalize any trampolines that were created during the load */
+	if (dload_tramp_finalize(dlthis) == 0) {
+		DL_ERROR("Finalization of auto-trampolines (size = " FMT_UI32
+			 ") failed", dlthis->tramp.tramp_sect_next_addr);
+	}
+}				/* dload_data */
+
+/*************************************************************************
+ * Procedure dload_reorder
+ *
+ * Parameters:
+ *	data	32-bit aligned pointer to data to be byte-swapped
+ *	dsiz	size of the data to be reordered in sizeof() units.
+ *	map		32-bit map defining how to reorder the data.  Value
+ *			must be REORDER_MAP() of some permutation
+ *			of 0x00 01 02 03
+ *
+ * Effect:
+ *	Re-arranges the bytes in each word according to the map specified.
+ *
+ *********************************************************************** */
+/* mask for byte shift count */
+#define SHIFT_COUNT_MASK (3 << LOG_BITS_PER_BYTE)
+
+void dload_reorder(void *data, int dsiz, unsigned int map)
+{
+	register u32 tmp, tmap, datv;
+	u32 *dp = (u32 *) data;
+
+	map <<= LOG_BITS_PER_BYTE;	/* align map with SHIFT_COUNT_MASK */
+	do {
+		tmp = 0;
+		datv = *dp;
+		tmap = map;
+		do {
+			tmp |= (datv & BYTE_MASK) << (tmap & SHIFT_COUNT_MASK);
+			tmap >>= BITS_PER_BYTE;
+		} while (datv >>= BITS_PER_BYTE);
+		*dp++ = tmp;
+	} while ((dsiz -= sizeof(u32)) > 0);
+}				/* dload_reorder */
+
+/*************************************************************************
+ * Procedure dload_checksum
+ *
+ * Parameters:
+ *	data	32-bit aligned pointer to data to be checksummed
+ *	siz		size of the data to be checksummed in sizeof() units.
+ *
+ * Effect:
+ *	Returns a checksum of the specified block
+ *
+ *********************************************************************** */
+u32 dload_checksum(void *data, unsigned siz)
+{
+	u32 sum;
+	u32 *dp;
+	int left;
+
+	sum = 0;
+	dp = (u32 *) data;
+	for (left = siz; left > 0; left -= sizeof(u32))
+		sum += *dp++;
+	return sum;
+}				/* dload_checksum */
+
+#if HOST_ENDIANNESS
+/*************************************************************************
+ * Procedure dload_reverse_checksum
+ *
+ * Parameters:
+ *	data	32-bit aligned pointer to data to be checksummed
+ *	siz		size of the data to be checksummed in sizeof() units.
+ *
+ * Effect:
+ *	Returns a checksum of the specified block, which is assumed to be bytes
+ * in big-endian order.
+ *
+ * Notes:
+ *	In a big-endian host, things like the string table are stored as bytes
+ * in host order. But dllcreate always checksums in little-endian order.
+ * It is most efficient to just handle the difference a word at a time.
+ *
+ ********************************************************************** */
+u32 dload_reverse_checksum(void *data, unsigned siz)
+{
+	u32 sum, temp;
+	u32 *dp;
+	int left;
+
+	sum = 0;
+	dp = (u32 *) data;
+
+	for (left = siz; left > 0; left -= sizeof(u32)) {
+		temp = *dp++;
+		sum += temp << BITS_PER_BYTE * 3;
+		sum += temp >> BITS_PER_BYTE * 3;
+		sum += (temp >> BITS_PER_BYTE) & (BYTE_MASK << BITS_PER_BYTE);
+		sum += (temp & (BYTE_MASK << BITS_PER_BYTE)) << BITS_PER_BYTE;
+	}
+
+	return sum;
+}				/* dload_reverse_checksum */
+
+#if (TARGET_AU_BITS > 8) && (TARGET_AU_BITS < 32)
+u32 dload_reverse_checksum16(void *data, unsigned siz)
+{
+	uint_fast32_t sum, temp;
+	u32 *dp;
+	int left;
+
+	sum = 0;
+	dp = (u32 *) data;
+
+	for (left = siz; left > 0; left -= sizeof(u32)) {
+		temp = *dp++;
+		sum += temp << BITS_PER_BYTE * 2;
+		sum += temp >> BITS_PER_BYTE * 2;
+	}
+
+	return sum;
+}				/* dload_reverse_checksum16 */
+#endif
+#endif
+
+/*************************************************************************
+ * Procedure swap_words
+ *
+ * Parameters:
+ *	data	32-bit aligned pointer to data to be swapped
+ *	siz	size of the data to be swapped.
+ *	bitmap	Bit map of how to swap each 32-bit word; 1 => 2 shorts,
+ *		0 => 1 long
+ *
+ * Effect:
+ *	Swaps the specified data according to the specified map
+ *
+ *********************************************************************** */
+static void swap_words(void *data, unsigned siz, unsigned bitmap)
+{
+	register int i;
+#if TARGET_AU_BITS < 16
+	register u16 *sp;
+#endif
+	register u32 *lp;
+
+	siz /= sizeof(u16);
+
+#if TARGET_AU_BITS < 16
+	/* pass 1: do all the bytes */
+	i = siz;
+	sp = (u16 *) data;
+	do {
+		register u16 tmp;
+		tmp = *sp;
+		*sp++ = SWAP16BY8(tmp);
+	} while ((i -= 1) > 0);
+#endif
+
+#if TARGET_AU_BITS < 32
+	/* pass 2: fixup the 32-bit words */
+	i = siz >> 1;
+	lp = (u32 *) data;
+	do {
+		if ((bitmap & 1) == 0) {
+			register u32 tmp;
+			tmp = *lp;
+			*lp = SWAP32BY16(tmp);
+		}
+		lp += 1;
+		bitmap >>= 1;
+	} while ((i -= 1) > 0);
+#endif
+}				/* swap_words */
+
+/*************************************************************************
+ * Procedure copy_tgt_strings
+ *
+ * Parameters:
+ *	dstp		Destination address.  Assumed to be 32-bit aligned
+ *	srcp		Source address.  Assumed to be 32-bit aligned
+ *	charcount	Number of characters to copy.
+ *
+ * Effect:
+ *	Copies strings from the source (which is in usual .dof file order on
+ * the loading processor) to the destination buffer (which should be in proper
+ * target addressable unit order).  Makes sure the last string in the
+ * buffer is NULL terminated (for safety).
+ * Returns the first unused destination address.
+ *********************************************************************** */
+static char *copy_tgt_strings(void *dstp, void *srcp, unsigned charcount)
+{
+	register tgt_au_t *src = (tgt_au_t *) srcp;
+	register tgt_au_t *dst = (tgt_au_t *) dstp;
+	register int cnt = charcount;
+	do {
+#if TARGET_AU_BITS <= BITS_PER_AU
+		/* byte-swapping issues may exist for strings on target */
+		*dst++ = *src++;
+#else
+		*dst++ = *src++;
+#endif
+	} while ((cnt -= (sizeof(tgt_au_t) * BITS_PER_AU / BITS_PER_BYTE)) > 0);
+	/*apply force to make sure that the string table has null terminator */
+#if (BITS_PER_AU == BITS_PER_BYTE) && (TARGET_AU_BITS == BITS_PER_BYTE)
+	dst[-1] = 0;
+#else
+	/* little endian */
+	dst[-1] &= (1 << (BITS_PER_AU - BITS_PER_BYTE)) - 1;
+#endif
+	return (char *)dst;
+}				/* copy_tgt_strings */
+
+/*************************************************************************
+ * Procedure init_module_handle
+ *
+ * Parameters:
+ *	none
+ *
+ * Effect:
+ *	Initializes the module handle we use to enable unloading, and installs
+ * the debug information required by the target.
+ *
+ * Notes:
+ * The handle returned from dynamic_load_module needs to encapsulate all the
+ * allocations done for the module, and enable them plus the modules symbols to
+ * be deallocated.
+ *
+ *********************************************************************** */
+#ifndef _BIG_ENDIAN
+static const struct ldr_section_info dllview_info_init = { ".dllview", 0, 0,
+	(ldr_addr)-1, DBG_LIST_PAGE, DLOAD_DATA, 0
+};
+#else
+static const struct ldr_section_info dllview_info_init = { ".dllview", 0, 0,
+	(ldr_addr)-1, DLOAD_DATA, DBG_LIST_PAGE, 0
+};
+#endif
+static void init_module_handle(struct dload_state *dlthis)
+{
+	struct my_handle *hndl;
+	u16 curr_sect;
+	struct ldr_section_info *asecs;
+	struct dll_module *dbmod;
+	struct dll_sect *dbsec;
+	struct dbg_mirror_root *mlist;
+	register char *cp;
+	struct modules_header mhdr;
+	struct ldr_section_info dllview_info;
+	struct dynload_symbol *debug_mirror_sym;
+	hndl = dlthis->myhandle;
+	if (!hndl)
+		return;		/* must be errors detected, so forget it */
+
+	/*  Store the section count */
+	hndl->secn_count = dlthis->allocated_secn_count;
+
+	/*  If a trampoline section was created, add it in */
+	if (dlthis->tramp.tramp_sect_next_addr != 0)
+		hndl->secn_count += 1;
+
+	hndl->secn_count = hndl->secn_count << 1;
+
+	hndl->secn_count = dlthis->allocated_secn_count << 1;
+#ifndef TARGET_ENDIANNESS
+	if (dlthis->big_e_target)
+		hndl->secn_count += 1;	/* flag for big-endian */
+#endif
+	if (dlthis->dload_errcount)
+		return;		/* abandon if errors detected */
+	/* Locate the symbol that names the header for the CCS debug list
+	   of modules. If not found, we just don't generate the debug record.
+	   If found, we create our modules list.  We make sure to create the
+	   loader_dllview_root even if there is no relocation info to record,
+	   just to try to put both symbols in the same symbol table and
+	   module. */
+	debug_mirror_sym = dlthis->mysym->find_matching_symbol(dlthis->mysym,
+							loader_dllview_root);
+	if (!debug_mirror_sym) {
+		struct dynload_symbol *dlmodsym;
+		struct dbg_mirror_root *mlst;
+
+		/* our root symbol is not yet present;
+		   check if we have DLModules defined */
+		dlmodsym = dlthis->mysym->find_matching_symbol(dlthis->mysym,
+							LINKER_MODULES_HEADER);
+		if (!dlmodsym)
+			return;	/* no DLModules list so no debug info */
+		/* if we have DLModules defined, construct our header */
+		mlst = (struct dbg_mirror_root *)
+		    dlthis->mysym->dload_allocate(dlthis->mysym,
+						  sizeof(struct
+							 dbg_mirror_root));
+		if (!mlst) {
+			DL_ERROR(err_alloc, sizeof(struct dbg_mirror_root));
+			return;
+		}
+		mlst->hnext = NULL;
+		mlst->changes = 0;
+		mlst->refcount = 0;
+		mlst->dbthis = TDATA_TO_TADDR(dlmodsym->value);
+		/* add our root symbol */
+		debug_mirror_sym = dlthis->mysym->add_to_symbol_table
+		    (dlthis->mysym, loader_dllview_root,
+		     (unsigned)dlthis->myhandle);
+		if (!debug_mirror_sym) {
+			/* failed, recover memory */
+			dlthis->mysym->dload_deallocate(dlthis->mysym, mlst);
+			return;
+		}
+		debug_mirror_sym->value = (u32) mlst;
+	}
+	/* First create the DLLview record and stuff it into the buffer.
+	   Then write it to the DSP.  Record pertinent locations in our hndl,
+	   and add it to the per-processor list of handles with debug info. */
+#ifndef DEBUG_HEADER_IN_LOADER
+	mlist = (struct dbg_mirror_root *)debug_mirror_sym->value;
+	if (!mlist)
+		return;
+#else
+	mlist = (struct dbg_mirror_root *)&debug_list_header;
+#endif
+	hndl->dm.hroot = mlist;	/* set pointer to root into our handle */
+	if (!dlthis->allocated_secn_count)
+		return;		/* no load addresses to be recorded */
+	/* reuse temporary symbol storage */
+	dbmod = (struct dll_module *)dlthis->local_symtab;
+	/* Create the DLLview record in the memory we retain for our handle */
+	dbmod->num_sects = dlthis->allocated_secn_count;
+	dbmod->timestamp = dlthis->verify.dv_timdat;
+	dbmod->version = INIT_VERSION;
+	dbmod->verification = VERIFICATION;
+	asecs = dlthis->ldr_sections;
+	dbsec = dbmod->sects;
+	for (curr_sect = dlthis->allocated_secn_count;
+	     curr_sect > 0; curr_sect -= 1) {
+		dbsec->sect_load_adr = asecs->load_addr;
+		dbsec->sect_run_adr = asecs->run_addr;
+		dbsec += 1;
+		asecs += 1;
+	}
+
+	/*  If a trampoline section was created go ahead and add its info */
+	if (dlthis->tramp.tramp_sect_next_addr != 0) {
+		dbmod->num_sects++;
+		dbsec->sect_load_adr = asecs->load_addr;
+		dbsec->sect_run_adr = asecs->run_addr;
+		dbsec++;
+		asecs++;
+	}
+
+	/* now cram in the names */
+	cp = copy_tgt_strings(dbsec, dlthis->str_head,
+			      dlthis->debug_string_size);
+
+	/* If a trampoline section was created, add its name so DLLView
+	 * can show the user the section info. */
+	if (dlthis->tramp.tramp_sect_next_addr != 0) {
+		cp = copy_tgt_strings(cp,
+				      dlthis->tramp.final_string_table,
+				      strlen(dlthis->tramp.final_string_table) +
+				      1);
+	}
+
+	/* round off the size of the debug record, and remember same */
+	hndl->dm.dbsiz = HOST_TO_TDATA_ROUND(cp - (char *)dbmod);
+	*cp = 0;		/* strictly to make our test harness happy */
+	dllview_info = dllview_info_init;
+	dllview_info.size = TDATA_TO_TADDR(hndl->dm.dbsiz);
+	/* Initialize memory context to default heap */
+	dllview_info.context = 0;
+	hndl->dm.context = 0;
+	/* fill in next pointer and size */
+	if (mlist->hnext) {
+		dbmod->next_module = TADDR_TO_TDATA(mlist->hnext->dm.dbthis);
+		dbmod->next_module_size = mlist->hnext->dm.dbsiz;
+	} else {
+		dbmod->next_module_size = 0;
+		dbmod->next_module = 0;
+	}
+	/* allocate memory for on-DSP DLLview debug record */
+	if (!dlthis->myalloc)
+		return;
+	if (!dlthis->myalloc->dload_allocate(dlthis->myalloc, &dllview_info,
+					     HOST_TO_TADDR(sizeof(u32)))) {
+		return;
+	}
+	/* Store load address of .dllview section */
+	hndl->dm.dbthis = dllview_info.load_addr;
+	/* Store memory context (segid) in which .dllview section
+	 * was  allocated */
+	hndl->dm.context = dllview_info.context;
+	mlist->refcount += 1;
+	/* swap bytes in the entire debug record, but not the string table */
+	if (TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)) {
+		swap_words(dbmod, (char *)dbsec - (char *)dbmod,
+			   DLL_MODULE_BITMAP);
+	}
+	/* Update the DLLview list on the DSP write new record */
+	if (!dlthis->myio->writemem(dlthis->myio, dbmod,
+				    dllview_info.load_addr, &dllview_info,
+				    TADDR_TO_HOST(dllview_info.size))) {
+		return;
+	}
+	/* write new header */
+	mhdr.first_module_size = hndl->dm.dbsiz;
+	mhdr.first_module = TADDR_TO_TDATA(dllview_info.load_addr);
+	/* swap bytes in the module header, if needed */
+	if (TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)) {
+		swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
+			   MODULES_HEADER_BITMAP);
+	}
+	dllview_info = dllview_info_init;
+	if (!dlthis->myio->writemem(dlthis->myio, &mhdr, mlist->dbthis,
+				    &dllview_info,
+				    sizeof(struct modules_header) -
+				    sizeof(u16))) {
+		return;
+	}
+	/* Add the module handle to this processor's list
+	   of handles with debug info */
+	hndl->dm.hnext = mlist->hnext;
+	if (hndl->dm.hnext)
+		hndl->dm.hnext->dm.hprev = hndl;
+	hndl->dm.hprev = (struct my_handle *)mlist;
+	mlist->hnext = hndl;	/* insert after root */
+}				/* init_module_handle */
+
+/*************************************************************************
+ * Procedure dynamic_unload_module
+ *
+ * Parameters:
+ *	mhandle	A module handle from dynamic_load_module
+ *	syms	Host-side symbol table and malloc/free functions
+ *	alloc	Target-side memory allocation
+ *
+ * Effect:
+ *	The module specified by mhandle is unloaded.  Unloading causes all
+ * target memory to be deallocated, all symbols defined by the module to
+ * be purged, and any host-side storage used by the dynamic loader for
+ * this module to be released.
+ *
+ * Returns:
+ *	Zero for success. On error, the number of errors detected is returned.
+ * Individual errors are reported using syms->error_report().
+ *********************************************************************** */
+int dynamic_unload_module(void *mhandle,
+			  struct dynamic_loader_sym *syms,
+			  struct dynamic_loader_allocate *alloc,
+			  struct dynamic_loader_initialize *init)
+{
+	s16 curr_sect;
+	struct ldr_section_info *asecs;
+	struct my_handle *hndl;
+	struct dbg_mirror_root *root;
+	unsigned errcount = 0;
+	struct ldr_section_info dllview_info = dllview_info_init;
+	struct modules_header mhdr;
+
+	hndl = (struct my_handle *)mhandle;
+	if (!hndl)
+		return 0;	/* if handle is null, nothing to do */
+	/* Clear out the module symbols
+	 * Note that if this is the module that defined MODULES_HEADER
+	 (the head of the target debug list)
+	 * then this operation will blow away that symbol.
+	 It will therefore be impossible for subsequent
+	 * operations to add entries to this un-referenceable list. */
+	if (!syms)
+		return 1;
+	syms->purge_symbol_table(syms, (unsigned)hndl);
+	/* Deallocate target memory for sections
+	 * NOTE: The trampoline section, if created, gets deleted here, too */
+
+	asecs = hndl->secns;
+	if (alloc)
+		for (curr_sect = (hndl->secn_count >> 1); curr_sect > 0;
+		     curr_sect -= 1) {
+			asecs->name = NULL;
+			alloc->dload_deallocate(alloc, asecs++);
+		}
+	root = hndl->dm.hroot;
+	if (!root) {
+		/* there is a debug list containing this module */
+		goto func_end;
+	}
+	if (!hndl->dm.dbthis) {	/* target-side dllview record exists */
+		goto loop_end;
+	}
+	/* Retrieve memory context in which .dllview was allocated */
+	dllview_info.context = hndl->dm.context;
+	if (hndl->dm.hprev == hndl)
+		goto exitunltgt;
+
+	/* target-side dllview record is in list */
+	/* dequeue this record from our GPP-side mirror list */
+	hndl->dm.hprev->dm.hnext = hndl->dm.hnext;
+	if (hndl->dm.hnext)
+		hndl->dm.hnext->dm.hprev = hndl->dm.hprev;
+	/* Update next_module of previous entry in target list
+	 * We are using mhdr here as a surrogate for either a
+	 struct modules_header or a dll_module */
+	if (hndl->dm.hnext) {
+		mhdr.first_module = TADDR_TO_TDATA(hndl->dm.hnext->dm.dbthis);
+		mhdr.first_module_size = hndl->dm.hnext->dm.dbsiz;
+	} else {
+		mhdr.first_module = 0;
+		mhdr.first_module_size = 0;
+	}
+	if (!init)
+		goto exitunltgt;
+
+	if (!init->connect(init)) {
+		dload_syms_error(syms, iconnect);
+		errcount += 1;
+		goto exitunltgt;
+	}
+	/* swap bytes in the module header, if needed */
+	if (TARGET_ENDIANNESS_DIFFERS(hndl->secn_count & 0x1)) {
+		swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
+			   MODULES_HEADER_BITMAP);
+	}
+	if (!init->writemem(init, &mhdr, hndl->dm.hprev->dm.dbthis,
+			    &dllview_info, sizeof(struct modules_header) -
+			    sizeof(mhdr.update_flag))) {
+		dload_syms_error(syms, dlvwrite);
+		errcount += 1;
+	}
+	/* update change counter */
+	root->changes += 1;
+	if (!init->writemem(init, &(root->changes),
+			    root->dbthis + HOST_TO_TADDR
+			    (sizeof(mhdr.first_module) +
+			     sizeof(mhdr.first_module_size)),
+			    &dllview_info, sizeof(mhdr.update_flag))) {
+		dload_syms_error(syms, dlvwrite);
+		errcount += 1;
+	}
+	init->release(init);
+exitunltgt:
+	/* release target storage */
+	dllview_info.size = TDATA_TO_TADDR(hndl->dm.dbsiz);
+	dllview_info.load_addr = hndl->dm.dbthis;
+	if (alloc)
+		alloc->dload_deallocate(alloc, &dllview_info);
+	root->refcount -= 1;
+	/* target-side dllview record exists */
+loop_end:
+#ifndef DEBUG_HEADER_IN_LOADER
+	if (root->refcount <= 0) {
+		/* if all references gone, blow off the header */
+		/* our root symbol may be gone due to the Purge above,
+		   but if not, do not destroy the root */
+		if (syms->find_matching_symbol
+		    (syms, loader_dllview_root) == NULL)
+			syms->dload_deallocate(syms, root);
+	}
+#endif
+func_end:
+	/* there is a debug list containing this module */
+	syms->dload_deallocate(syms, mhandle);	/* release our storage */
+	return errcount;
+}				/* dynamic_unload_module */
+
+#if BITS_PER_AU > BITS_PER_BYTE
+/*************************************************************************
+ * Procedure unpack_name
+ *
+ * Parameters:
+ *	soffset	Byte offset into the string table
+ *
+ * Effect:
+ *	Returns a pointer to the string specified by the offset supplied, or
+ * NULL for error.
+ *
+ *********************************************************************** */
+static char *unpack_name(struct dload_state *dlthis, u32 soffset)
+{
+	u8 tmp, *src;
+	char *dst;
+
+	if (soffset >= dlthis->dfile_hdr.df_strtab_size) {
+		dload_error(dlthis, "Bad string table offset " FMT_UI32,
+			    soffset);
+		return NULL;
+	}
+	src = (uint_least8_t *) dlthis->str_head +
+	    (soffset >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE));
+	dst = dlthis->str_temp;
+	if (soffset & 1)
+		*dst++ = *src++;	/* only 1 character in first word */
+	do {
+		tmp = *src++;
+		*dst = (tmp >> BITS_PER_BYTE);
+		if (!(*dst++))
+			break;
+	} while ((*dst++ = tmp & BYTE_MASK));
+	dlthis->temp_len = dst - dlthis->str_temp;
+	/* squirrel away length including terminating null */
+	return dlthis->str_temp;
+}				/* unpack_name */
+#endif
diff --git a/drivers/staging/tidspbridge/dynload/dload_internal.h b/drivers/staging/tidspbridge/dynload/dload_internal.h
new file mode 100644
index 0000000..8037561
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/dload_internal.h
@@ -0,0 +1,351 @@
+/*
+ * dload_internal.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef _DLOAD_INTERNAL_
+#define _DLOAD_INTERNAL_
+
+#include <linux/types.h>
+
+/*
+ * Internal state definitions for the dynamic loader
+ */
+
+#define TRUE 1
+#define FALSE 0
+
+/* type used for relocation intermediate results */
+typedef s32 rvalue;
+
+/* unsigned version of same; must have at least as many bits */
+typedef u32 urvalue;
+
+/*
+ * Dynamic loader configuration constants
+ */
+/* error issued if input has more sections than this limit */
+#define REASONABLE_SECTION_LIMIT 100
+
+/* (Addressable unit) value used to clear BSS section */
+#define DLOAD_FILL_BSS 0
+
+/*
+ * Reorder maps explained (?)
+ *
+ * The doff file format defines a 32-bit pattern used to determine the
+ * byte order of an image being read.  That value is
+ * BYTE_RESHUFFLE_VALUE == 0x00010203
+ * For purposes of the reorder routine, we would rather have the all-is-OK
+ * for 32-bits pattern be 0x03020100.  This first macro makes the
+ * translation from doff file header value to MAP value: */
+#define REORDER_MAP(rawmap) ((rawmap) ^ 0x3030303)
+/* This translation is made in dload_headers.  Thereafter, the all-is-OK
+ * value for the maps stored in dlthis is REORDER_MAP(BYTE_RESHUFFLE_VALUE).
+ * But sadly, not all bits of the doff file are 32-bit integers.
+ * The notable exceptions are strings and image bits.
+ * Strings obey host byte order: */
+#if defined(_BIG_ENDIAN)
+#define HOST_BYTE_ORDER(cookedmap) ((cookedmap) ^ 0x3030303)
+#else
+#define HOST_BYTE_ORDER(cookedmap) (cookedmap)
+#endif
+/* Target bits consist of target AUs (could be bytes, or 16-bits,
+ * or 32-bits) stored as an array in host order.  A target order
+ * map is defined by: */
+#if !defined(_BIG_ENDIAN) || TARGET_AU_BITS > 16
+#define TARGET_ORDER(cookedmap) (cookedmap)
+#elif TARGET_AU_BITS > 8
+#define TARGET_ORDER(cookedmap) ((cookedmap) ^ 0x2020202)
+#else
+#define TARGET_ORDER(cookedmap) ((cookedmap) ^ 0x3030303)
+#endif
+
+/* forward declaration for handle returned by dynamic loader */
+struct my_handle;
+
+/*
+ * a list of module handles, which mirrors the debug list on the target
+ */
+struct dbg_mirror_root {
+	/* must be same as dbg_mirror_list; __DLModules address on target */
+	u32 dbthis;
+	struct my_handle *hnext;	/* must be same as dbg_mirror_list */
+	u16 changes;		/* change counter */
+	u16 refcount;		/* number of modules referencing this root */
+};
+
+struct dbg_mirror_list {
+	u32 dbthis;
+	struct my_handle *hnext, *hprev;
+	struct dbg_mirror_root *hroot;
+	u16 dbsiz;
+	u32 context;	/* Save context for .dllview memory allocation */
+};
+
+#define VARIABLE_SIZE 1
+/*
+ * the structure we actually return as an opaque module handle
+ */
+struct my_handle {
+	struct dbg_mirror_list dm;	/* !!! must be first !!! */
+	/* sections following << 1, LSB is set for big-endian target */
+	u16 secn_count;
+	struct ldr_section_info secns[VARIABLE_SIZE];
+};
+#define MY_HANDLE_SIZE (sizeof(struct my_handle) -\
+			sizeof(struct ldr_section_info))
+/* real size of my_handle */
+
+/*
+ * reduced symbol structure used for symbols during relocation
+ */
+struct local_symbol {
+	s32 value;		/* Relocated symbol value */
+	s32 delta;		/* Original value in input file */
+	s16 secnn;		/* section number */
+	s16 sclass;		/* symbol class */
+};
+
+/*
+ * Trampoline data structures
+ */
+#define TRAMP_NO_GEN_AVAIL              65535
+#define TRAMP_SYM_PREFIX                "__$dbTR__"
+#define TRAMP_SECT_NAME                 ".dbTR"
+/* MUST MATCH THE LENGTH ABOVE!! */
+#define TRAMP_SYM_PREFIX_LEN            9
+/* Includes NULL termination */
+#define TRAMP_SYM_HEX_ASCII_LEN         9
+
+#define GET_CONTAINER(ptr, type, field) ((type *)((unsigned long)ptr -\
+				(unsigned long)(&((type *)0)->field)))
+#ifndef FIELD_OFFSET
+#define FIELD_OFFSET(type, field)       ((unsigned long)(&((type *)0)->field))
+#endif
+
+/*
+    The trampoline code for the target is located in a table called
+    "tramp_gen_info" with is indexed by looking up the index in the table
+    "tramp_map".  The tramp_map index is acquired using the target
+    HASH_FUNC on the relocation type that caused the trampoline.  Each
+    trampoline code table entry MUST follow this format:
+
+    |----------------------------------------------|
+    |  tramp_gen_code_hdr                          |
+    |----------------------------------------------|
+    |  Trampoline image code                       |
+    |  (the raw instruction code for the target)   |
+    |----------------------------------------------|
+    |  Relocation entries for the image code       |
+    |----------------------------------------------|
+
+    This is very similar to how image data is laid out in the DOFF file
+    itself.
+ */
+struct tramp_gen_code_hdr {
+	u32 tramp_code_size;	/*  in BYTES */
+	u32 num_relos;
+	u32 relo_offset;	/*  in BYTES */
+};
+
+struct tramp_img_pkt {
+	struct tramp_img_pkt *next;	/*  MUST BE FIRST */
+	u32 base;
+	struct tramp_gen_code_hdr hdr;
+	u8 payload[VARIABLE_SIZE];
+};
+
+struct tramp_img_dup_relo {
+	struct tramp_img_dup_relo *next;
+	struct reloc_record_t relo;
+};
+
+struct tramp_img_dup_pkt {
+	struct tramp_img_dup_pkt *next;	/*  MUST BE FIRST */
+	s16 secnn;
+	u32 offset;
+	struct image_packet_t img_pkt;
+	struct tramp_img_dup_relo *relo_chain;
+
+	/*  PAYLOAD OF IMG PKT FOLLOWS */
+};
+
+struct tramp_sym {
+	struct tramp_sym *next;	/*  MUST BE FIRST */
+	u32 index;
+	u32 str_index;
+	struct local_symbol sym_info;
+};
+
+struct tramp_string {
+	struct tramp_string *next;	/*  MUST BE FIRST */
+	u32 index;
+	char str[VARIABLE_SIZE];	/*  NULL terminated */
+};
+
+struct tramp_info {
+	u32 tramp_sect_next_addr;
+	struct ldr_section_info sect_info;
+
+	struct tramp_sym *symbol_head;
+	struct tramp_sym *symbol_tail;
+	u32 tramp_sym_next_index;
+	struct local_symbol *final_sym_table;
+
+	struct tramp_string *string_head;
+	struct tramp_string *string_tail;
+	u32 tramp_string_next_index;
+	u32 tramp_string_size;
+	char *final_string_table;
+
+	struct tramp_img_pkt *tramp_pkts;
+	struct tramp_img_dup_pkt *dup_pkts;
+};
+
+/*
+ * States of the .cinit state machine
+ */
+enum cinit_mode {
+	CI_COUNT = 0,		/* expecting a count */
+	CI_ADDRESS,		/* expecting an address */
+#if CINIT_ALIGN < CINIT_ADDRESS	/* handle case of partial address field */
+	CI_PARTADDRESS,		/* have only part of the address */
+#endif
+	CI_COPY,		/* in the middle of copying data */
+	CI_DONE			/* end of .cinit table */
+};
+
+/*
+ * The internal state of the dynamic loader, which is passed around as
+ * an object
+ */
+struct dload_state {
+	struct dynamic_loader_stream *strm;	/* The module input stream */
+	struct dynamic_loader_sym *mysym;	/* Symbols for this session */
+	/* target memory allocator */
+	struct dynamic_loader_allocate *myalloc;
+	struct dynamic_loader_initialize *myio;	/* target memory initializer */
+	unsigned myoptions;	/* Options parameter dynamic_load_module */
+
+	char *str_head;		/* Pointer to string table */
+#if BITS_PER_AU > BITS_PER_BYTE
+	char *str_temp;		/* Pointer to temporary buffer for strings */
+	/* big enough to hold longest string */
+	unsigned temp_len;	/* length of last temporary string */
+	char *xstrings;		/* Pointer to buffer for expanded */
+	/* strings for sec names */
+#endif
+	/* Total size of strings for DLLView section names */
+	unsigned debug_string_size;
+	/* Pointer to parallel section info for allocated sections only */
+	struct doff_scnhdr_t *sect_hdrs;	/* Pointer to section table */
+	struct ldr_section_info *ldr_sections;
+#if TMS32060
+	/* The address of the start of the .bss section */
+	ldr_addr bss_run_base;
+#endif
+	struct local_symbol *local_symtab;	/* Relocation symbol table */
+
+	/* pointer to DL section info for the section being relocated */
+	struct ldr_section_info *image_secn;
+	/* change in run address for current section during relocation */
+	ldr_addr delta_runaddr;
+	ldr_addr image_offset;	/* offset of current packet in section */
+	enum cinit_mode cinit_state;	/* current state of cload_cinit() */
+	int cinit_count;	/* the current count */
+	ldr_addr cinit_addr;	/* the current address */
+	s16 cinit_page;		/* the current page */
+	/* Handle to be returned by dynamic_load_module */
+	struct my_handle *myhandle;
+	unsigned dload_errcount;	/* Total # of errors reported so far */
+	/* Number of target sections that require allocation and relocation */
+	unsigned allocated_secn_count;
+#ifndef TARGET_ENDIANNESS
+	int big_e_target;	/* Target data in big-endian format */
+#endif
+	/* map for reordering bytes, 0 if not needed */
+	u32 reorder_map;
+	struct doff_filehdr_t dfile_hdr;	/* DOFF file header structure */
+	struct doff_verify_rec_t verify;	/* Verify record */
+
+	struct tramp_info tramp;	/* Trampoline data, if needed */
+
+	int relstkidx;		/* index into relocation value stack */
+	/* relocation value stack used in relexp.c */
+	rvalue relstk[STATIC_EXPR_STK_SIZE];
+
+};
+
+#ifdef TARGET_ENDIANNESS
+#define TARGET_BIG_ENDIAN TARGET_ENDIANNESS
+#else
+#define TARGET_BIG_ENDIAN (dlthis->big_e_target)
+#endif
+
+/*
+ * Exports from cload.c to rest of the world
+ */
+extern void dload_error(struct dload_state *dlthis, const char *errtxt, ...);
+extern void dload_syms_error(struct dynamic_loader_sym *syms,
+			     const char *errtxt, ...);
+extern void dload_headers(struct dload_state *dlthis);
+extern void dload_strings(struct dload_state *dlthis, bool sec_names_only);
+extern void dload_sections(struct dload_state *dlthis);
+extern void dload_reorder(void *data, int dsiz, u32 map);
+extern u32 dload_checksum(void *data, unsigned siz);
+
+#if HOST_ENDIANNESS
+extern uint32_t dload_reverse_checksum(void *data, unsigned siz);
+#if (TARGET_AU_BITS > 8) && (TARGET_AU_BITS < 32)
+extern uint32_t dload_reverse_checksum16(void *data, unsigned siz);
+#endif
+#endif
+
+#define IS_DATA_SCN(zzz) (DLOAD_SECTION_TYPE((zzz)->type) != DLOAD_TEXT)
+#define IS_DATA_SCN_NUM(zzz) \
+		(DLOAD_SECT_TYPE(&dlthis->sect_hdrs[(zzz)-1]) != DLOAD_TEXT)
+
+/*
+ * exported by reloc.c
+ */
+extern void dload_relocate(struct dload_state *dlthis, tgt_au_t * data,
+			   struct reloc_record_t *rp, bool * tramps_generated,
+			   bool second_pass);
+
+extern rvalue dload_unpack(struct dload_state *dlthis, tgt_au_t * data,
+			   int fieldsz, int offset, unsigned sgn);
+
+extern int dload_repack(struct dload_state *dlthis, rvalue val, tgt_au_t * data,
+			int fieldsz, int offset, unsigned sgn);
+
+/*
+ * exported by tramp.c
+ */
+extern bool dload_tramp_avail(struct dload_state *dlthis,
+			      struct reloc_record_t *rp);
+
+int dload_tramp_generate(struct dload_state *dlthis, s16 secnn,
+			 u32 image_offset, struct image_packet_t *ipacket,
+			 struct reloc_record_t *rp);
+
+extern int dload_tramp_pkt_udpate(struct dload_state *dlthis,
+				  s16 secnn, u32 image_offset,
+				  struct image_packet_t *ipacket);
+
+extern int dload_tramp_finalize(struct dload_state *dlthis);
+
+extern void dload_tramp_cleanup(struct dload_state *dlthis);
+
+#endif /* _DLOAD_INTERNAL_ */
diff --git a/drivers/staging/tidspbridge/dynload/doff.h b/drivers/staging/tidspbridge/dynload/doff.h
new file mode 100644
index 0000000..5bf9924
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/doff.h
@@ -0,0 +1,344 @@
+/*
+ * doff.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Structures & definitions used for dynamically loaded modules file format.
+ * This format is a reformatted version of COFF. It optimizes the layout for
+ * the dynamic loader.
+ *
+ * .dof files, when viewed as a sequence of 32-bit integers, look the same
+ * on big-endian and little-endian machines.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef _DOFF_H
+#define _DOFF_H
+
+#ifndef UINT32_C
+#define UINT32_C(zzz) ((u32)zzz)
+#endif
+
+#define BYTE_RESHUFFLE_VALUE UINT32_C(0x00010203)
+
+/* DOFF file header containing fields categorizing the remainder of the file */
+struct doff_filehdr_t {
+
+	/* string table size, including filename, in bytes */
+	u32 df_strtab_size;
+
+	/* entry point if one exists */
+	u32 df_entrypt;
+
+	/* identifies byte ordering of file;
+	 * always set to BYTE_RESHUFFLE_VALUE */
+	u32 df_byte_reshuffle;
+
+	/* Size of the string table up to and including the last section name */
+	/* Size includes the name of the COFF file also */
+	u32 df_scn_name_size;
+
+#ifndef _BIG_ENDIAN
+	/* number of symbols */
+	u16 df_no_syms;
+
+	/* length in bytes of the longest string, including terminating NULL */
+	/* excludes the name of the file */
+	u16 df_max_str_len;
+
+	/* total number of sections including no-load ones */
+	u16 df_no_scns;
+
+	/* number of sections containing target code allocated or downloaded */
+	u16 df_target_scns;
+
+	/* unique id for dll file format & version */
+	u16 df_doff_version;
+
+	/* identifies ISA */
+	u16 df_target_id;
+
+	/* useful file flags */
+	u16 df_flags;
+
+	/* section reference for entry point, N_UNDEF for none, */
+	/* N_ABS for absolute address */
+	s16 df_entry_secn;
+#else
+	/* length of the longest string, including terminating NULL */
+	u16 df_max_str_len;
+
+	/* number of symbols */
+	u16 df_no_syms;
+
+	/* number of sections containing target code allocated or downloaded */
+	u16 df_target_scns;
+
+	/* total number of sections including no-load ones */
+	u16 df_no_scns;
+
+	/* identifies ISA */
+	u16 df_target_id;
+
+	/* unique id for dll file format & version */
+	u16 df_doff_version;
+
+	/* section reference for entry point, N_UNDEF for none, */
+	/* N_ABS for absolute address */
+	s16 df_entry_secn;
+
+	/* useful file flags */
+	u16 df_flags;
+#endif
+	/* checksum for file header record */
+	u32 df_checksum;
+
+};
+
+/* flags in the df_flags field */
+#define  DF_LITTLE   0x100
+#define  DF_BIG      0x200
+#define  DF_BYTE_ORDER (DF_LITTLE | DF_BIG)
+
+/* Supported processors */
+#define TMS470_ID   0x97
+#define LEAD_ID     0x98
+#define TMS32060_ID 0x99
+#define LEAD3_ID    0x9c
+
+/* Primary processor for loading */
+#if TMS32060
+#define TARGET_ID   TMS32060_ID
+#endif
+
+/* Verification record containing values used to test integrity of the bits */
+struct doff_verify_rec_t {
+
+	/* time and date stamp */
+	u32 dv_timdat;
+
+	/* checksum for all section records */
+	u32 dv_scn_rec_checksum;
+
+	/* checksum for string table */
+	u32 dv_str_tab_checksum;
+
+	/* checksum for symbol table */
+	u32 dv_sym_tab_checksum;
+
+	/* checksum for verification record */
+	u32 dv_verify_rec_checksum;
+
+};
+
+/* String table is an array of null-terminated strings.  The first entry is
+ * the filename, which is added by DLLcreate.  No new structure definitions
+ * are required.
+ */
+
+/* Section Records including information on the corresponding image packets */
+/*
+ *      !!WARNING!!
+ *
+ * This structure is expected to match in form ldr_section_info in
+ * dynamic_loader.h
+ */
+
+struct doff_scnhdr_t {
+
+	s32 ds_offset;		/* offset into string table of name */
+	s32 ds_paddr;		/* RUN address, in target AU */
+	s32 ds_vaddr;		/* LOAD address, in target AU */
+	s32 ds_size;		/* section size, in target AU */
+#ifndef _BIG_ENDIAN
+	u16 ds_page;		/* memory page id */
+	u16 ds_flags;		/* section flags */
+#else
+	u16 ds_flags;		/* section flags */
+	u16 ds_page;		/* memory page id */
+#endif
+	u32 ds_first_pkt_offset;
+	/* Absolute byte offset into the file */
+	/* where the first image record resides */
+
+	s32 ds_nipacks;		/* number of image packets */
+
+};
+
+/* Symbol table entry */
+struct doff_syment_t {
+
+	s32 dn_offset;		/* offset into string table of name */
+	s32 dn_value;		/* value of symbol */
+#ifndef _BIG_ENDIAN
+	s16 dn_scnum;		/* section number */
+	s16 dn_sclass;		/* storage class */
+#else
+	s16 dn_sclass;		/* storage class */
+	s16 dn_scnum;		/* section number, 1-based */
+#endif
+
+};
+
+/* special values for dn_scnum */
+#define  DN_UNDEF  0		/* undefined symbol */
+#define  DN_ABS    (-1)		/* value of symbol is absolute */
+/* special values for dn_sclass */
+#define DN_EXT     2
+#define DN_STATLAB 20
+#define DN_EXTLAB  21
+
+/* Default value of image bits in packet */
+/* Configurable by user on the command line */
+#define IMAGE_PACKET_SIZE 1024
+
+/* An image packet contains a chunk of data from a section along with */
+/* information necessary for its processing. */
+struct image_packet_t {
+
+	s32 num_relocs;		/* number of relocations for */
+	/* this packet */
+
+	s32 packet_size;	/* number of bytes in array */
+	/* "bits" occupied  by */
+	/* valid data.  Could be */
+	/* < IMAGE_PACKET_SIZE to */
+	/* prevent splitting a */
+	/* relocation across packets. */
+	/* Last packet of a section */
+	/* will most likely contain */
+	/* < IMAGE_PACKET_SIZE bytes */
+	/* of valid data */
+
+	s32 img_chksum;		/* Checksum for image packet */
+	/* and the corresponding */
+	/* relocation records */
+
+	u8 *img_data;		/* Actual data in section */
+
+};
+
+/* The relocation structure definition matches the COFF version.  Offsets */
+/* however are relative to the image packet base not the section base. */
+struct reloc_record_t {
+
+	s32 vaddr;
+
+	/* expressed in target AUs */
+
+	union {
+		struct {
+#ifndef _BIG_ENDIAN
+			u8 _offset;	/* bit offset of rel fld */
+			u8 _fieldsz;	/* size of rel fld */
+			u8 _wordsz;	/* # bytes containing rel fld */
+			u8 _dum1;
+			u16 _dum2;
+			u16 _type;
+#else
+			unsigned _dum1:8;
+			unsigned _wordsz:8;	/* # bytes containing rel fld */
+			unsigned _fieldsz:8;	/* size of rel fld */
+			unsigned _offset:8;	/* bit offset of rel fld */
+			u16 _type;
+			u16 _dum2;
+#endif
+		} _r_field;
+
+		struct {
+			u32 _spc;	/* image packet relative PC */
+#ifndef _BIG_ENDIAN
+			u16 _dum;
+			u16 _type;	/* relocation type */
+#else
+			u16 _type;	/* relocation type */
+			u16 _dum;
+#endif
+		} _r_spc;
+
+		struct {
+			u32 _uval;	/* constant value */
+#ifndef _BIG_ENDIAN
+			u16 _dum;
+			u16 _type;	/* relocation type */
+#else
+			u16 _type;	/* relocation type */
+			u16 _dum;
+#endif
+		} _r_uval;
+
+		struct {
+			s32 _symndx;	/* 32-bit sym tbl index */
+#ifndef _BIG_ENDIAN
+			u16 _disp;	/* extra addr encode data */
+			u16 _type;	/* relocation type */
+#else
+			u16 _type;	/* relocation type */
+			u16 _disp;	/* extra addr encode data */
+#endif
+		} _r_sym;
+	} _u_reloc;
+
+};
+
+/* abbreviations for convenience */
+#ifndef TYPE
+#define TYPE      _u_reloc._r_sym._type
+#define UVAL      _u_reloc._r_uval._uval
+#define SYMNDX    _u_reloc._r_sym._symndx
+#define OFFSET    _u_reloc._r_field._offset
+#define FIELDSZ   _u_reloc._r_field._fieldsz
+#define WORDSZ    _u_reloc._r_field._wordsz
+#define R_DISP      _u_reloc._r_sym._disp
+#endif
+
+/**************************************************************************** */
+/* */
+/* Important DOFF macros used for file processing */
+/* */
+/**************************************************************************** */
+
+/* DOFF Versions */
+#define         DOFF0                       0
+
+/* Return the address/size >= to addr that is at a 32-bit boundary */
+/* This assumes that a byte is 8 bits */
+#define         DOFF_ALIGN(addr)            (((addr) + 3) & ~UINT32_C(3))
+
+/**************************************************************************** */
+/* */
+/* The DOFF section header flags field is laid out as follows: */
+/* */
+/*  Bits 0-3 : Section Type */
+/*  Bit    4 : Set when section requires target memory to be allocated by DL */
+/*  Bit    5 : Set when section requires downloading */
+/*  Bits 8-11: Alignment, same as COFF */
+/* */
+/**************************************************************************** */
+
+/* Enum for DOFF section types (bits 0-3 of flag): See dynamic_loader.h */
+
+/* Macros to help processing of sections */
+#define DLOAD_SECT_TYPE(s_hdr)      ((s_hdr)->ds_flags & 0xF)
+
+/* DS_ALLOCATE indicates whether a section needs space on the target */
+#define DS_ALLOCATE_MASK            0x10
+#define DS_NEEDS_ALLOCATION(s_hdr)  ((s_hdr)->ds_flags & DS_ALLOCATE_MASK)
+
+/* DS_DOWNLOAD indicates that the loader needs to copy bits */
+#define DS_DOWNLOAD_MASK            0x20
+#define DS_NEEDS_DOWNLOAD(s_hdr)    ((s_hdr)->ds_flags & DS_DOWNLOAD_MASK)
+
+/* Section alignment requirement in AUs */
+#define DS_ALIGNMENT(ds_flags) (1 << (((ds_flags) >> 8) & 0xF))
+
+#endif /* _DOFF_H */
diff --git a/drivers/staging/tidspbridge/dynload/getsection.c b/drivers/staging/tidspbridge/dynload/getsection.c
new file mode 100644
index 0000000..029898f
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/getsection.c
@@ -0,0 +1,416 @@
+/*
+ * getsection.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <dspbridge/getsection.h>
+#include "header.h"
+
+/*
+ * Error strings
+ */
+static const char readstrm[] = { "Error reading %s from input stream" };
+static const char seek[] = { "Set file position to %d failed" };
+static const char isiz[] = { "Bad image packet size %d" };
+static const char err_checksum[] = { "Checksum failed on %s" };
+
+static const char err_reloc[] = { "dload_get_section unable to read"
+	    "sections containing relocation entries"
+};
+
+#if BITS_PER_AU > BITS_PER_BYTE
+static const char err_alloc[] = { "Syms->dload_allocate( %d ) failed" };
+static const char stbl[] = { "Bad string table offset " FMT_UI32 };
+#endif
+
+/*
+ * we use the fact that DOFF section records are shaped just like
+ * ldr_section_info to reduce our section storage usage.  These macros
+ * marks the places where that assumption is made
+ */
+#define DOFFSEC_IS_LDRSEC(pdoffsec) ((struct ldr_section_info *)(pdoffsec))
+#define LDRSEC_IS_DOFFSEC(ldrsec) ((struct doff_scnhdr_t *)(ldrsec))
+
+/************************************************************** */
+/********************* SUPPORT FUNCTIONS ********************** */
+/************************************************************** */
+
+#if BITS_PER_AU > BITS_PER_BYTE
+/**************************************************************************
+ * Procedure unpack_sec_name
+ *
+ * Parameters:
+ *  dlthis		Handle from dload_module_open for this module
+ *	soffset	    Byte offset into the string table
+ *  dst         Place to store the expanded string
+ *
+ * Effect:
+ *	Stores a string from the string table into the destination, expanding
+ * it in the process.  Returns a pointer just past the end of the stored
+ * string on success, or NULL on failure.
+ *
+ ************************************************************************ */
+static char *unpack_sec_name(struct dload_state *dlthis, u32 soffset, char *dst)
+{
+	u8 tmp, *src;
+
+	if (soffset >= dlthis->dfile_hdr.df_scn_name_size) {
+		dload_error(dlthis, stbl, soffset);
+		return NULL;
+	}
+	src = (u8 *) dlthis->str_head +
+	    (soffset >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE));
+	if (soffset & 1)
+		*dst++ = *src++;	/* only 1 character in first word */
+	do {
+		tmp = *src++;
+		*dst = (tmp >> BITS_PER_BYTE)
+		    if (!(*dst++))
+			break;
+	} while ((*dst++ = tmp & BYTE_MASK));
+
+	return dst;
+}
+
+/**************************************************************************
+ * Procedure expand_sec_names
+ *
+ * Parameters:
+ *  dlthis		Handle from dload_module_open for this module
+ *
+ * Effect:
+ *    Allocates a buffer, unpacks and copies strings from string table into it.
+ * Stores a pointer to the buffer into a state variable.
+ ************************************************************************* */
+static void expand_sec_names(struct dload_state *dlthis)
+{
+	char *xstrings, *curr, *next;
+	u32 xsize;
+	u16 sec;
+	struct ldr_section_info *shp;
+	/* assume worst-case size requirement */
+	xsize = dlthis->dfile_hdr.df_max_str_len * dlthis->dfile_hdr.df_no_scns;
+	xstrings = (char *)dlthis->mysym->dload_allocate(dlthis->mysym, xsize);
+	if (xstrings == NULL) {
+		dload_error(dlthis, err_alloc, xsize);
+		return;
+	}
+	dlthis->xstrings = xstrings;
+	/* For each sec, copy and expand its name */
+	curr = xstrings;
+	for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
+		shp = DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
+		next = unpack_sec_name(dlthis, *(u32 *) &shp->name, curr);
+		if (next == NULL)
+			break;	/* error */
+		shp->name = curr;
+		curr = next;
+	}
+}
+
+#endif
+
+/************************************************************** */
+/********************* EXPORTED FUNCTIONS ********************* */
+/************************************************************** */
+
+/**************************************************************************
+ * Procedure dload_module_open
+ *
+ * Parameters:
+ *	module	The input stream that supplies the module image
+ *	syms	Host-side malloc/free and error reporting functions.
+ *			Other methods are unused.
+ *
+ * Effect:
+ *	Reads header information from a dynamic loader module using the
+    specified
+ * stream object, and returns a handle for the module information.  This
+ * handle may be used in subsequent query calls to obtain information
+ * contained in the module.
+ *
+ * Returns:
+ *	NULL if an error is encountered, otherwise a module handle for use
+ * in subsequent operations.
+ ************************************************************************* */
+void *dload_module_open(struct dynamic_loader_stream *module,
+				    struct dynamic_loader_sym *syms)
+{
+	struct dload_state *dlthis;	/* internal state for this call */
+	unsigned *dp, sz;
+	u32 sec_start;
+#if BITS_PER_AU <= BITS_PER_BYTE
+	u16 sec;
+#endif
+
+	/* Check that mandatory arguments are present */
+	if (!module || !syms) {
+		if (syms != NULL)
+			dload_syms_error(syms, "Required parameter is NULL");
+
+		return NULL;
+	}
+
+	dlthis = (struct dload_state *)
+	    syms->dload_allocate(syms, sizeof(struct dload_state));
+	if (!dlthis) {
+		/* not enough storage */
+		dload_syms_error(syms, "Can't allocate module info");
+		return NULL;
+	}
+
+	/* clear our internal state */
+	dp = (unsigned *)dlthis;
+	for (sz = sizeof(struct dload_state) / sizeof(unsigned);
+	     sz > 0; sz -= 1)
+		*dp++ = 0;
+
+	dlthis->strm = module;
+	dlthis->mysym = syms;
+
+	/* read in the doff image and store in our state variable */
+	dload_headers(dlthis);
+
+	if (!dlthis->dload_errcount)
+		dload_strings(dlthis, true);
+
+	/* skip ahead past the unread portion of the string table */
+	sec_start = sizeof(struct doff_filehdr_t) +
+	    sizeof(struct doff_verify_rec_t) +
+	    BYTE_TO_HOST(DOFF_ALIGN(dlthis->dfile_hdr.df_strtab_size));
+
+	if (dlthis->strm->set_file_posn(dlthis->strm, sec_start) != 0) {
+		dload_error(dlthis, seek, sec_start);
+		return NULL;
+	}
+
+	if (!dlthis->dload_errcount)
+		dload_sections(dlthis);
+
+	if (dlthis->dload_errcount) {
+		dload_module_close(dlthis);	/* errors, blow off our state */
+		dlthis = NULL;
+		return NULL;
+	}
+#if BITS_PER_AU > BITS_PER_BYTE
+	/* Expand all section names from the string table into the */
+	/* state variable, and convert section names from a relative */
+	/* string table offset to a pointers to the expanded string. */
+	expand_sec_names(dlthis);
+#else
+	/* Convert section names from a relative string table offset */
+	/* to a pointer into the string table. */
+	for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
+		struct ldr_section_info *shp =
+		    DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
+		shp->name = dlthis->str_head + *(u32 *) &shp->name;
+	}
+#endif
+
+	return dlthis;
+}
+
+/***************************************************************************
+ * Procedure dload_get_section_info
+ *
+ * Parameters:
+ *  minfo		Handle from dload_module_open for this module
+ *	sectionName	Pointer to the string name of the section desired
+ *	sectionInfo	Address of a section info structure pointer to be
+ *			initialized
+ *
+ * Effect:
+ *	Finds the specified section in the module information, and initializes
+ * the provided struct ldr_section_info pointer.
+ *
+ * Returns:
+ *	true for success, false for section not found
+ ************************************************************************* */
+int dload_get_section_info(void *minfo, const char *sectionName,
+			   const struct ldr_section_info **const sectionInfo)
+{
+	struct dload_state *dlthis;
+	struct ldr_section_info *shp;
+	u16 sec;
+
+	dlthis = (struct dload_state *)minfo;
+	if (!dlthis)
+		return false;
+
+	for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
+		shp = DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
+		if (strcmp(sectionName, shp->name) == 0) {
+			*sectionInfo = shp;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+#define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
+#define REVERSE_REORDER_MAP(rawmap) ((rawmap) ^ 0x3030303)
+
+/**************************************************************************
+ * Procedure dload_get_section
+ *
+ * Parameters:
+ *  minfo		Handle from dload_module_open for this module
+ *	sectionInfo	Pointer to a section info structure for the desired
+ *			section
+ *	sectionData	Buffer to contain the section initialized data
+ *
+ * Effect:
+ *	Copies the initialized data for the specified section into the
+ * supplied buffer.
+ *
+ * Returns:
+ *	true for success, false for section not found
+ ************************************************************************* */
+int dload_get_section(void *minfo,
+		      const struct ldr_section_info *sectionInfo,
+		      void *sectionData)
+{
+	struct dload_state *dlthis;
+	u32 pos;
+	struct doff_scnhdr_t *sptr = NULL;
+	s32 nip;
+	struct image_packet_t ipacket;
+	s32 ipsize;
+	u32 checks;
+	s8 *dest = (s8 *) sectionData;
+
+	dlthis = (struct dload_state *)minfo;
+	if (!dlthis)
+		return false;
+	sptr = LDRSEC_IS_DOFFSEC(sectionInfo);
+	if (sptr == NULL)
+		return false;
+
+	/* skip ahead to the start of the first packet */
+	pos = BYTE_TO_HOST(DOFF_ALIGN((u32) sptr->ds_first_pkt_offset));
+	if (dlthis->strm->set_file_posn(dlthis->strm, pos) != 0) {
+		dload_error(dlthis, seek, pos);
+		return false;
+	}
+
+	nip = sptr->ds_nipacks;
+	while ((nip -= 1) >= 0) {	/* for each packet */
+		/* get the fixed header bits */
+		if (dlthis->strm->read_buffer(dlthis->strm, &ipacket,
+					      IPH_SIZE) != IPH_SIZE) {
+			dload_error(dlthis, readstrm, "image packet");
+			return false;
+		}
+		/* reorder the header if need be */
+		if (dlthis->reorder_map)
+			dload_reorder(&ipacket, IPH_SIZE, dlthis->reorder_map);
+
+		/* Now read the packet image bits. Note: round the size up to
+		 * the next multiple of 4 bytes; this is what checksum
+		 * routines want. */
+		ipsize = BYTE_TO_HOST(DOFF_ALIGN(ipacket.packet_size));
+		if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) {
+			dload_error(dlthis, isiz, ipsize);
+			return false;
+		}
+		if (dlthis->strm->read_buffer
+		    (dlthis->strm, dest, ipsize) != ipsize) {
+			dload_error(dlthis, readstrm, "image packet");
+			return false;
+		}
+		/* reorder the bytes if need be */
+#if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
+		if (dlthis->reorder_map)
+			dload_reorder(dest, ipsize, dlthis->reorder_map);
+
+		checks = dload_checksum(dest, ipsize);
+#else
+		if (dlthis->dfile_hdr.df_byte_reshuffle !=
+		    TARGET_ORDER(REORDER_MAP(BYTE_RESHUFFLE_VALUE))) {
+			/* put image bytes in big-endian order, not PC order */
+			dload_reorder(dest, ipsize,
+				      TARGET_ORDER(dlthis->
+						dfile_hdr.df_byte_reshuffle));
+		}
+#if TARGET_AU_BITS > 8
+		checks = dload_reverse_checksum16(dest, ipsize);
+#else
+		checks = dload_reverse_checksum(dest, ipsize);
+#endif
+#endif
+		checks += dload_checksum(&ipacket, IPH_SIZE);
+
+		/* NYI: unable to handle relocation entries here.  Reloc
+		 * entries referring to fields that span the packet boundaries
+		 * may result in packets of sizes that are not multiple of
+		 * 4 bytes. Our checksum implementation works on 32-bit words
+		 * only. */
+		if (ipacket.num_relocs != 0) {
+			dload_error(dlthis, err_reloc, ipsize);
+			return false;
+		}
+
+		if (~checks) {
+			dload_error(dlthis, err_checksum, "image packet");
+			return false;
+		}
+
+		/*Advance destination ptr by the size of the just-read packet */
+		dest += ipsize;
+	}
+
+	return true;
+}
+
+/***************************************************************************
+ * Procedure dload_module_close
+ *
+ * Parameters:
+ *  minfo		Handle from dload_module_open for this module
+ *
+ * Effect:
+ *	Releases any storage associated with the module handle.  On return,
+ * the module handle is invalid.
+ *
+ * Returns:
+ *	Zero for success. On error, the number of errors detected is returned.
+ * Individual errors are reported using syms->error_report(), where syms was
+ * an argument to dload_module_open
+ ************************************************************************* */
+void dload_module_close(void *minfo)
+{
+	struct dload_state *dlthis;
+
+	dlthis = (struct dload_state *)minfo;
+	if (!dlthis)
+		return;
+
+	if (dlthis->str_head)
+		dlthis->mysym->dload_deallocate(dlthis->mysym,
+						dlthis->str_head);
+
+	if (dlthis->sect_hdrs)
+		dlthis->mysym->dload_deallocate(dlthis->mysym,
+						dlthis->sect_hdrs);
+
+#if BITS_PER_AU > BITS_PER_BYTE
+	if (dlthis->xstrings)
+		dlthis->mysym->dload_deallocate(dlthis->mysym,
+						dlthis->xstrings);
+
+#endif
+
+	dlthis->mysym->dload_deallocate(dlthis->mysym, dlthis);
+}
diff --git a/drivers/staging/tidspbridge/dynload/header.h b/drivers/staging/tidspbridge/dynload/header.h
new file mode 100644
index 0000000..5cef360
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/header.h
@@ -0,0 +1,55 @@
+/*
+ * header.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define TRUE 1
+#define FALSE 0
+#ifndef NULL
+#define NULL 0
+#endif
+
+#include <linux/string.h>
+#define DL_STRCMP  strcmp
+
+/* maximum parenthesis nesting in relocation stack expressions */
+#define STATIC_EXPR_STK_SIZE 10
+
+#include <linux/types.h>
+
+#include "doff.h"
+#include <dspbridge/dynamic_loader.h>
+#include "params.h"
+#include "dload_internal.h"
+#include "reloc_table.h"
+
+/*
+ * Plausibility limits
+ *
+ * These limits are imposed upon the input DOFF file as a check for validity.
+ * They are hard limits, in that the load will fail if they are exceeded.
+ * The numbers selected are arbitrary, in that the loader implementation does
+ * not require these limits.
+ */
+
+/* maximum number of bytes in string table */
+#define MAX_REASONABLE_STRINGTAB (0x100000)
+/* maximum number of code,data,etc. sections */
+#define MAX_REASONABLE_SECTIONS (200)
+/* maximum number of linker symbols */
+#define MAX_REASONABLE_SYMBOLS (100000)
+
+/* shift count to align F_BIG with DLOAD_LITTLE */
+#define ALIGN_COFF_ENDIANNESS 7
+#define ENDIANNESS_MASK (DF_BYTE_ORDER >> ALIGN_COFF_ENDIANNESS)
diff --git a/drivers/staging/tidspbridge/dynload/module_list.h b/drivers/staging/tidspbridge/dynload/module_list.h
new file mode 100644
index 0000000..a216bb1
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/module_list.h
@@ -0,0 +1,159 @@
+/*
+ * dspbridge/mpu_driver/src/dynload/module_list.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * This C header file gives the layout of the data structure created by the
+ * dynamic loader to describe the set of modules loaded into the DSP.
+ *
+ * Linked List Structure:
+ * ----------------------
+ * The data structure defined here is a singly-linked list.  The list
+ * represents the set of modules which are currently loaded in the DSP memory.
+ * The first entry in the list is a header record which contains a flag
+ * representing the state of the list.  The rest of the entries in the list
+ * are module records.
+ *
+ * Global symbol  _DLModules designates the first record in the list (i.e. the
+ * header record).  This symbol must be defined in any program that wishes to
+ * use DLLview plug-in.
+ *
+ * String Representation:
+ * ----------------------
+ * The string names of the module and its sections are stored in a block of
+ * memory which follows the module record itself.  The strings are ordered:
+ * module name first, followed by section names in order from the first
+ * section to the last.  String names are tightly packed arrays of 8-bit
+ * characters (two characters per 16-bit word on the C55x).  Strings are
+ * zero-byte-terminated.
+ *
+ * Creating and updating the list:
+ * -------------------------------
+ * Upon loading a new module into the DSP memory the dynamic loader inserts a
+ * new module record as the first module record in the list.  The fields of
+ * this module record are initialized to reflect the properties of the module.
+ * The dynamic loader does NOT increment the flag/counter in the list's header
+ * record.
+ *
+ * Upon unloading a module from the DSP memory the dynamic loader removes the
+ * module's record from this list.  The dynamic loader also increments the
+ * flag/counter in the list's header record to indicate that the list has been
+ * changed.
+ */
+
+#ifndef _MODULE_LIST_H_
+#define _MODULE_LIST_H_
+
+#include <linux/types.h>
+
+/* Global pointer to the modules_header structure */
+#define MODULES_HEADER "_DLModules"
+#define MODULES_HEADER_NO_UNDERSCORE "DLModules"
+
+/* Initial version number */
+#define INIT_VERSION 1
+
+/* Verification number -- to be recorded in each module record */
+#define VERIFICATION 0x79
+
+/* forward declarations */
+struct dll_module;
+struct dll_sect;
+
+/* the first entry in the list is the modules_header record;
+ * its address is contained in the global _DLModules pointer */
+struct modules_header {
+
+	/*
+	 * Address of the first dll_module record in the list or NULL.
+	 * Note: for C55x this is a word address (C55x data is
+	 * word-addressable)
+	 */
+	u32 first_module;
+
+	/* Combined storage size (in target addressable units) of the
+	 * dll_module record which follows this header record, or zero
+	 * if the list is empty.  This size includes the module's string table.
+	 * Note: for C55x the unit is a 16-bit word */
+	u16 first_module_size;
+
+	/* Counter is incremented whenever a module record is removed from
+	 * the list */
+	u16 update_flag;
+
+};
+
+/* for each 32-bits in above structure, a bitmap, LSB first, whose bits are:
+ * 0 => a 32-bit value, 1 => 2 16-bit values */
+/* swapping bitmap for type modules_header */
+#define MODULES_HEADER_BITMAP 0x2
+
+/* information recorded about each section in a module */
+struct dll_sect {
+
+	/* Load-time address of the section.
+	 * Note: for C55x this is a byte address for program sections, and
+	 * a word address for data sections.  C55x program memory is
+	 * byte-addressable, while data memory is word-addressable. */
+	u32 sect_load_adr;
+
+	/* Run-time address of the section.
+	 * Note 1: for C55x this is a byte address for program sections, and
+	 * a word address for data sections.
+	 * Note 2: for C55x two most significant bits of this field indicate
+	 * the section type: '00' for a code section, '11' for a data section
+	 * (C55 addresses are really only 24-bits wide). */
+	u32 sect_run_adr;
+
+};
+
+/* the rest of the entries in the list are module records */
+struct dll_module {
+
+	/* Address of the next dll_module record in the list, or 0 if this is
+	 * the last record in the list.
+	 * Note: for C55x this is a word address (C55x data is
+	 * word-addressable) */
+	u32 next_module;
+
+	/* Combined storage size (in target addressable units) of the
+	 * dll_module record which follows this one, or zero if this is the
+	 * last record in the list.  This size includes the module's string
+	 * table.
+	 * Note: for C55x the unit is a 16-bit word. */
+	u16 next_module_size;
+
+	/* version number of the tooling; set to INIT_VERSION for Phase 1 */
+	u16 version;
+
+	/* the verification word; set to VERIFICATION */
+	u16 verification;
+
+	/* Number of sections in the sects array */
+	u16 num_sects;
+
+	/* Module's "unique" id; copy of the timestamp from the host
+	 * COFF file */
+	u32 timestamp;
+
+	/* Array of num_sects elements of the module's section records */
+	struct dll_sect sects[1];
+};
+
+/* for each 32 bits in above structure, a bitmap, LSB first, whose bits are:
+ * 0 => a 32-bit value, 1 => 2 16-bit values */
+#define DLL_MODULE_BITMAP 0x6	/* swapping bitmap for type dll_module */
+
+#endif /* _MODULE_LIST_H_ */
diff --git a/drivers/staging/tidspbridge/dynload/params.h b/drivers/staging/tidspbridge/dynload/params.h
new file mode 100644
index 0000000..d797fcd
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/params.h
@@ -0,0 +1,226 @@
+/*
+ * params.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * This file defines host and target properties for all machines
+ * supported by the dynamic loader.  To be tedious...
+ *
+ * host: the machine on which the dynamic loader runs
+ * target: the machine that the dynamic loader is loading
+ *
+ * Host and target may or may not be the same, depending upon the particular
+ * use.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/******************************************************************************
+ *
+ *							Host Properties
+ *
+ **************************************************************************** */
+
+#define BITS_PER_BYTE 8		/* bits in the standard PC/SUN byte */
+#define LOG_BITS_PER_BYTE 3	/* log base 2 of same */
+#define BYTE_MASK ((1U<<BITS_PER_BYTE)-1)
+
+#if defined(__TMS320C55X__) || defined(_TMS320C5XX)
+#define BITS_PER_AU 16
+#define LOG_BITS_PER_AU 4
+ /* use this print string in error messages for uint32_t */
+#define FMT_UI32 "0x%lx"
+#define FMT8_UI32 "%08lx"	/* same but no 0x, fixed width field */
+#else
+/* bits in the smallest addressable data storage unit */
+#define BITS_PER_AU 8
+/* log base 2 of the same; useful for shift counts */
+#define LOG_BITS_PER_AU 3
+#define FMT_UI32 "0x%x"
+#define FMT8_UI32 "%08x"
+#endif
+
+/* generic fastest method for swapping bytes and shorts */
+#define SWAP32BY16(zz) (((zz) << 16) | ((zz) >> 16))
+#define SWAP16BY8(zz) (((zz) << 8) | ((zz) >> 8))
+
+/* !! don't be tempted to insert type definitions here; use <stdint.h> !! */
+
+/******************************************************************************
+ *
+ *							Target Properties
+ *
+ **************************************************************************** */
+
+/*-------------------------------------------------------------------------- */
+/* TMS320C6x Target Specific Parameters (byte-addressable) */
+/*-------------------------------------------------------------------------- */
+#if TMS32060
+#define MEMORG          0x0L	/* Size of configured memory */
+#define MEMSIZE         0x0L	/* (full address space) */
+
+#define CINIT_ALIGN     8	/* alignment of cinit record in TDATA AUs */
+#define CINIT_COUNT	4	/* width of count field in TDATA AUs */
+#define CINIT_ADDRESS	4	/* width of address field in TDATA AUs */
+#define CINIT_PAGE_BITS	0	/* Number of LSBs of address that
+				 * are page number */
+
+#define LENIENT_SIGNED_RELEXPS 0	/* DOES SIGNED ALLOW MAX UNSIGNED */
+
+#undef TARGET_ENDIANNESS	/* may be big or little endian */
+
+/* align a target address to a word boundary */
+#define TARGET_WORD_ALIGN(zz) (((zz) + 0x3) & -0x4)
+#endif
+
+/*--------------------------------------------------------------------------
+ *
+ *			DEFAULT SETTINGS and DERIVED PROPERTIES
+ *
+ * This section establishes defaults for values not specified above
+ *-------------------------------------------------------------------------- */
+#ifndef TARGET_AU_BITS
+#define TARGET_AU_BITS 8	/* width of the target addressable unit */
+#define LOG_TARGET_AU_BITS 3	/* log2 of same */
+#endif
+
+#ifndef CINIT_DEFAULT_PAGE
+#define CINIT_DEFAULT_PAGE 0	/* default .cinit page number */
+#endif
+
+#ifndef DATA_RUN2LOAD
+#define DATA_RUN2LOAD(zz) (zz)	/* translate data run address to load address */
+#endif
+
+#ifndef DBG_LIST_PAGE
+#define DBG_LIST_PAGE 0		/* page number for .dllview section */
+#endif
+
+#ifndef TARGET_WORD_ALIGN
+/* align a target address to a word boundary */
+#define TARGET_WORD_ALIGN(zz) (zz)
+#endif
+
+#ifndef TDATA_TO_TADDR
+#define TDATA_TO_TADDR(zz) (zz)	/* target data address to target AU address */
+#define TADDR_TO_TDATA(zz) (zz)	/* target AU address to target data address */
+#define TDATA_AU_BITS	TARGET_AU_BITS	/* bits per data AU */
+#define LOG_TDATA_AU_BITS	LOG_TARGET_AU_BITS
+#endif
+
+/*
+ *
+ * Useful properties and conversions derived from the above
+ *
+ */
+
+/*
+ * Conversions between host and target addresses
+ */
+#if LOG_BITS_PER_AU == LOG_TARGET_AU_BITS
+/* translate target addressable unit to host address */
+#define TADDR_TO_HOST(x) (x)
+/* translate host address to target addressable unit */
+#define HOST_TO_TADDR(x) (x)
+#elif LOG_BITS_PER_AU > LOG_TARGET_AU_BITS
+#define TADDR_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU-LOG_TARGET_AU_BITS))
+#define HOST_TO_TADDR(x) ((x) << (LOG_BITS_PER_AU-LOG_TARGET_AU_BITS))
+#else
+#define TADDR_TO_HOST(x) ((x) << (LOG_TARGET_AU_BITS-LOG_BITS_PER_AU))
+#define HOST_TO_TADDR(x) ((x) >> (LOG_TARGET_AU_BITS-LOG_BITS_PER_AU))
+#endif
+
+#if LOG_BITS_PER_AU == LOG_TDATA_AU_BITS
+/* translate target addressable unit to host address */
+#define TDATA_TO_HOST(x) (x)
+/* translate host address to target addressable unit */
+#define HOST_TO_TDATA(x) (x)
+/* translate host address to target addressable unit, round up */
+#define HOST_TO_TDATA_ROUND(x) (x)
+/* byte offset to host offset, rounded up for TDATA size */
+#define BYTE_TO_HOST_TDATA_ROUND(x) BYTE_TO_HOST_ROUND(x)
+#elif LOG_BITS_PER_AU > LOG_TDATA_AU_BITS
+#define TDATA_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
+#define HOST_TO_TDATA(x) ((x) << (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
+#define HOST_TO_TDATA_ROUND(x) ((x) << (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
+#define BYTE_TO_HOST_TDATA_ROUND(x) BYTE_TO_HOST_ROUND(x)
+#else
+#define TDATA_TO_HOST(x) ((x) << (LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
+#define HOST_TO_TDATA(x) ((x) >> (LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
+#define HOST_TO_TDATA_ROUND(x) (((x) +\
+				(1<<(LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))-1) >>\
+				(LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
+#define BYTE_TO_HOST_TDATA_ROUND(x) (BYTE_TO_HOST((x) +\
+	(1<<(LOG_TDATA_AU_BITS-LOG_BITS_PER_BYTE))-1) &\
+	-(TDATA_AU_BITS/BITS_PER_AU))
+#endif
+
+/*
+ * Input in DOFF format is always expresed in bytes, regardless of loading host
+ * so we wind up converting from bytes to target and host units even when the
+ * host is not a byte machine.
+ */
+#if LOG_BITS_PER_AU == LOG_BITS_PER_BYTE
+#define BYTE_TO_HOST(x) (x)
+#define BYTE_TO_HOST_ROUND(x) (x)
+#define HOST_TO_BYTE(x) (x)
+#elif LOG_BITS_PER_AU >= LOG_BITS_PER_BYTE
+#define BYTE_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
+#define BYTE_TO_HOST_ROUND(x) ((x + (BITS_PER_AU/BITS_PER_BYTE-1)) >>\
+			      (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
+#define HOST_TO_BYTE(x) ((x) << (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
+#else
+/* lets not try to deal with sub-8-bit byte machines */
+#endif
+
+#if LOG_TARGET_AU_BITS == LOG_BITS_PER_BYTE
+/* translate target addressable unit to byte address */
+#define TADDR_TO_BYTE(x) (x)
+/* translate byte address to target addressable unit */
+#define BYTE_TO_TADDR(x) (x)
+#elif LOG_TARGET_AU_BITS > LOG_BITS_PER_BYTE
+#define TADDR_TO_BYTE(x) ((x) << (LOG_TARGET_AU_BITS-LOG_BITS_PER_BYTE))
+#define BYTE_TO_TADDR(x) ((x) >> (LOG_TARGET_AU_BITS-LOG_BITS_PER_BYTE))
+#else
+/* lets not try to deal with sub-8-bit byte machines */
+#endif
+
+#ifdef _BIG_ENDIAN
+#define HOST_ENDIANNESS 1
+#else
+#define HOST_ENDIANNESS 0
+#endif
+
+#ifdef TARGET_ENDIANNESS
+#define TARGET_ENDIANNESS_DIFFERS(rtend) (HOST_ENDIANNESS^TARGET_ENDIANNESS)
+#elif HOST_ENDIANNESS
+#define TARGET_ENDIANNESS_DIFFERS(rtend) (!(rtend))
+#else
+#define TARGET_ENDIANNESS_DIFFERS(rtend) (rtend)
+#endif
+
+/* the unit in which we process target image data */
+#if TARGET_AU_BITS <= 8
+typedef u8 tgt_au_t;
+#elif TARGET_AU_BITS <= 16
+typedef u16 tgt_au_t;
+#else
+typedef u32 tgt_au_t;
+#endif
+
+/* size of that unit */
+#if TARGET_AU_BITS < BITS_PER_AU
+#define TGTAU_BITS BITS_PER_AU
+#define LOG_TGTAU_BITS LOG_BITS_PER_AU
+#else
+#define TGTAU_BITS TARGET_AU_BITS
+#define LOG_TGTAU_BITS LOG_TARGET_AU_BITS
+#endif
diff --git a/drivers/staging/tidspbridge/dynload/reloc.c b/drivers/staging/tidspbridge/dynload/reloc.c
new file mode 100644
index 0000000..316a38c
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/reloc.c
@@ -0,0 +1,484 @@
+/*
+ * reloc.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "header.h"
+
+#if TMS32060
+/* the magic symbol for the start of BSS */
+static const char bsssymbol[] = { ".bss" };
+#endif
+
+#if TMS32060
+#include "reloc_table_c6000.c"
+#endif
+
+#if TMS32060
+/* From coff.h - ignore these relocation operations */
+#define R_C60ALIGN     0x76	/* C60: Alignment info for compressor */
+#define R_C60FPHEAD    0x77	/* C60: Explicit assembly directive */
+#define R_C60NOCMP    0x100	/* C60: Don't compress this code scn */
+#endif
+
+/**************************************************************************
+ * Procedure dload_unpack
+ *
+ * Parameters:
+ *	data	pointer to storage unit containing lowest host address of
+ *		image data
+ *	fieldsz	Size of bit field, 0 < fieldsz <= sizeof(rvalue)*BITS_PER_AU
+ *	offset	Offset from LSB, 0 <= offset < BITS_PER_AU
+ *	sgn	Signedness of the field (ROP_SGN, ROP_UNS, ROP_MAX, ROP_ANY)
+ *
+ * Effect:
+ *	Extracts the specified field and returns it.
+ ************************************************************************* */
+rvalue dload_unpack(struct dload_state *dlthis, tgt_au_t * data, int fieldsz,
+		    int offset, unsigned sgn)
+{
+	register rvalue objval;
+	register int shift, direction;
+	register tgt_au_t *dp = data;
+
+	fieldsz -= 1;	/* avoid nastiness with 32-bit shift of 32-bit value */
+	/* * collect up enough bits to contain the desired field */
+	if (TARGET_BIG_ENDIAN) {
+		dp += (fieldsz + offset) >> LOG_TGTAU_BITS;
+		direction = -1;
+	} else
+		direction = 1;
+	objval = *dp >> offset;
+	shift = TGTAU_BITS - offset;
+	while (shift <= fieldsz) {
+		dp += direction;
+		objval += (rvalue) *dp << shift;
+		shift += TGTAU_BITS;
+	}
+
+	/* * sign or zero extend the value appropriately */
+	if (sgn == ROP_UNS)
+		objval &= (2 << fieldsz) - 1;
+	else {
+		shift = sizeof(rvalue) * BITS_PER_AU - 1 - fieldsz;
+		objval = (objval << shift) >> shift;
+	}
+
+	return objval;
+
+}				/* dload_unpack */
+
+/**************************************************************************
+ * Procedure dload_repack
+ *
+ * Parameters:
+ *	val		Value to insert
+ *	data	Pointer to storage unit containing lowest host address of
+ * 		image data
+ *	fieldsz	Size of bit field, 0 < fieldsz <= sizeof(rvalue)*BITS_PER_AU
+ *	offset	Offset from LSB, 0 <= offset < BITS_PER_AU
+ *	sgn	Signedness of the field (ROP_SGN, ROP_UNS, ROP_MAX, ROP_ANY)
+ *
+ * Effect:
+ *	Stuffs the specified value in the specified field.  Returns 0 for
+ *	success
+ * or 1 if the value will not fit in the specified field according to the
+ * specified signedness rule.
+ ************************************************************************* */
+static const unsigned char ovf_limit[] = { 1, 2, 2 };
+
+int dload_repack(struct dload_state *dlthis, rvalue val, tgt_au_t * data,
+		 int fieldsz, int offset, unsigned sgn)
+{
+	register urvalue objval, mask;
+	register int shift, direction;
+	register tgt_au_t *dp = data;
+
+	fieldsz -= 1;	/* avoid nastiness with 32-bit shift of 32-bit value */
+	/* clip the bits */
+	mask = ((UINT32_C(2) << fieldsz) - 1);
+	objval = (val & mask);
+	/* * store the bits through the specified mask */
+	if (TARGET_BIG_ENDIAN) {
+		dp += (fieldsz + offset) >> LOG_TGTAU_BITS;
+		direction = -1;
+	} else
+		direction = 1;
+
+	/* insert LSBs */
+	*dp = (*dp & ~(mask << offset)) + (objval << offset);
+	shift = TGTAU_BITS - offset;
+	/* align mask and objval with AU boundary */
+	objval >>= shift;
+	mask >>= shift;
+
+	while (mask) {
+		dp += direction;
+		*dp = (*dp & ~mask) + objval;
+		objval >>= TGTAU_BITS;
+		mask >>= TGTAU_BITS;
+	}
+
+	/*
+	 * check for overflow
+	 */
+	if (sgn) {
+		unsigned tmp = (val >> fieldsz) + (sgn & 0x1);
+		if (tmp > ovf_limit[sgn - 1])
+			return 1;
+	}
+	return 0;
+
+}				/* dload_repack */
+
+/* lookup table for the scaling amount in a C6x instruction */
+#if TMS32060
+#define SCALE_BITS 4		/* there are 4 bits in the scale field */
+#define SCALE_MASK 0x7		/* we really only use the bottom 3 bits */
+static const u8 c60_scale[SCALE_MASK + 1] = {
+	1, 0, 0, 0, 1, 1, 2, 2
+};
+#endif
+
+/**************************************************************************
+ * Procedure dload_relocate
+ *
+ * Parameters:
+ *	data	Pointer to base of image data
+ *	rp		Pointer to relocation operation
+ *
+ * Effect:
+ *	Performs the specified relocation operation
+ ************************************************************************* */
+void dload_relocate(struct dload_state *dlthis, tgt_au_t * data,
+		    struct reloc_record_t *rp, bool * tramps_genereted,
+		    bool second_pass)
+{
+	rvalue val, reloc_amt, orig_val = 0;
+	unsigned int fieldsz = 0;
+	unsigned int offset = 0;
+	unsigned int reloc_info = 0;
+	unsigned int reloc_action = 0;
+	register int rx = 0;
+	rvalue *stackp = NULL;
+	int top;
+	struct local_symbol *svp = NULL;
+#ifdef RFV_SCALE
+	unsigned int scale = 0;
+#endif
+	struct image_packet_t *img_pkt = NULL;
+
+	/* The image packet data struct is only used during first pass
+	 * relocation in the event that a trampoline is needed.  2nd pass
+	 * relocation doesn't guarantee that data is coming from an
+	 * image_packet_t structure. See cload.c, dload_data for how img_data is
+	 * set. If that changes this needs to be updated!!! */
+	if (second_pass == false)
+		img_pkt = (struct image_packet_t *)((u8 *) data -
+						    sizeof(struct
+							   image_packet_t));
+
+	rx = HASH_FUNC(rp->TYPE);
+	while (rop_map1[rx] != rp->TYPE) {
+		rx = HASH_L(rop_map2[rx]);
+		if (rx < 0) {
+#if TMS32060
+			switch (rp->TYPE) {
+			case R_C60ALIGN:
+			case R_C60NOCMP:
+			case R_C60FPHEAD:
+				/* Ignore these reloc types and return */
+				break;
+			default:
+				/* Unknown reloc type, print error and return */
+				dload_error(dlthis, "Bad coff operator 0x%x",
+					    rp->TYPE);
+			}
+#else
+			dload_error(dlthis, "Bad coff operator 0x%x", rp->TYPE);
+#endif
+			return;
+		}
+	}
+	rx = HASH_I(rop_map2[rx]);
+	if ((rx < (sizeof(rop_action) / sizeof(u16)))
+	    && (rx < (sizeof(rop_info) / sizeof(u16))) && (rx > 0)) {
+		reloc_action = rop_action[rx];
+		reloc_info = rop_info[rx];
+	} else {
+		dload_error(dlthis, "Buffer Overflow - Array Index Out "
+			    "of Bounds");
+	}
+
+	/* Compute the relocation amount for the referenced symbol, if any */
+	reloc_amt = rp->UVAL;
+	if (RFV_SYM(reloc_info)) {	/* relocation uses a symbol reference */
+		/* If this is first pass, use the module local symbol table,
+		 * else use the trampoline symbol table. */
+		if (second_pass == false) {
+			if ((u32) rp->SYMNDX < dlthis->dfile_hdr.df_no_syms) {
+				/* real symbol reference */
+				svp = &dlthis->local_symtab[rp->SYMNDX];
+				reloc_amt = (RFV_SYM(reloc_info) == ROP_SYMD) ?
+				    svp->delta : svp->value;
+			}
+			/* reloc references current section */
+			else if (rp->SYMNDX == -1) {
+				reloc_amt = (RFV_SYM(reloc_info) == ROP_SYMD) ?
+				    dlthis->delta_runaddr :
+				    dlthis->image_secn->run_addr;
+			}
+		}
+	}
+	/* relocation uses a symbol reference */
+	/* Handle stack adjustment */
+	val = 0;
+	top = RFV_STK(reloc_info);
+	if (top) {
+		top += dlthis->relstkidx - RSTK_UOP;
+		if (top >= STATIC_EXPR_STK_SIZE) {
+			dload_error(dlthis,
+				    "Expression stack overflow in %s at offset "
+				    FMT_UI32, dlthis->image_secn->name,
+				    rp->vaddr + dlthis->image_offset);
+			return;
+		}
+		val = dlthis->relstk[dlthis->relstkidx];
+		dlthis->relstkidx = top;
+		stackp = &dlthis->relstk[top];
+	}
+	/* Derive field position and size, if we need them */
+	if (reloc_info & ROP_RW) {	/* read or write action in our future */
+		fieldsz = RFV_WIDTH(reloc_action);
+		if (fieldsz) {	/* field info from table */
+			offset = RFV_POSN(reloc_action);
+			if (TARGET_BIG_ENDIAN)
+				/* make sure vaddr is the lowest target
+				 * address containing bits */
+				rp->vaddr += RFV_BIGOFF(reloc_info);
+		} else {	/* field info from relocation op */
+			fieldsz = rp->FIELDSZ;
+			offset = rp->OFFSET;
+			if (TARGET_BIG_ENDIAN)
+				/* make sure vaddr is the lowest target
+				   address containing bits */
+				rp->vaddr += (rp->WORDSZ - offset - fieldsz)
+				    >> LOG_TARGET_AU_BITS;
+		}
+		data = (tgt_au_t *) ((char *)data + TADDR_TO_HOST(rp->vaddr));
+		/* compute lowest host location of referenced data */
+#if BITS_PER_AU > TARGET_AU_BITS
+		/* conversion from target address to host address may lose
+		   address bits; add loss to offset */
+		if (TARGET_BIG_ENDIAN) {
+			offset += -((rp->vaddr << LOG_TARGET_AU_BITS) +
+				    offset + fieldsz) &
+			    (BITS_PER_AU - TARGET_AU_BITS);
+		} else {
+			offset += (rp->vaddr << LOG_TARGET_AU_BITS) &
+			    (BITS_PER_AU - 1);
+		}
+#endif
+#ifdef RFV_SCALE
+		scale = RFV_SCALE(reloc_info);
+#endif
+	}
+	/* read the object value from the current image, if so ordered */
+	if (reloc_info & ROP_R) {
+		/* relocation reads current image value */
+		val = dload_unpack(dlthis, data, fieldsz, offset,
+				   RFV_SIGN(reloc_info));
+		/* Save off the original value in case the relo overflows and
+		 * we can trampoline it. */
+		orig_val = val;
+
+#ifdef RFV_SCALE
+		val <<= scale;
+#endif
+	}
+	/* perform the necessary arithmetic */
+	switch (RFV_ACTION(reloc_action)) {	/* relocation actions */
+	case RACT_VAL:
+		break;
+	case RACT_ASGN:
+		val = reloc_amt;
+		break;
+	case RACT_ADD:
+		val += reloc_amt;
+		break;
+	case RACT_PCR:
+		/*-----------------------------------------------------------
+		 * Handle special cases of jumping from absolute sections
+		 * (special reloc type) or to absolute destination
+		 * (symndx == -1).  In either case, set the appropriate
+		 * relocation amount to 0.
+		 *----------------------------------------------------------- */
+		if (rp->SYMNDX == -1)
+			reloc_amt = 0;
+		val += reloc_amt - dlthis->delta_runaddr;
+		break;
+	case RACT_ADDISP:
+		val += rp->R_DISP + reloc_amt;
+		break;
+	case RACT_ASGPC:
+		val = dlthis->image_secn->run_addr + reloc_amt;
+		break;
+	case RACT_PLUS:
+		if (stackp != NULL)
+			val += *stackp;
+		break;
+	case RACT_SUB:
+		if (stackp != NULL)
+			val = *stackp - val;
+		break;
+	case RACT_NEG:
+		val = -val;
+		break;
+	case RACT_MPY:
+		if (stackp != NULL)
+			val *= *stackp;
+		break;
+	case RACT_DIV:
+		if (stackp != NULL)
+			val = *stackp / val;
+		break;
+	case RACT_MOD:
+		if (stackp != NULL)
+			val = *stackp % val;
+		break;
+	case RACT_SR:
+		if (val >= sizeof(rvalue) * BITS_PER_AU)
+			val = 0;
+		else if (stackp != NULL)
+			val = (urvalue) *stackp >> val;
+		break;
+	case RACT_ASR:
+		if (val >= sizeof(rvalue) * BITS_PER_AU)
+			val = sizeof(rvalue) * BITS_PER_AU - 1;
+		else if (stackp != NULL)
+			val = *stackp >> val;
+		break;
+	case RACT_SL:
+		if (val >= sizeof(rvalue) * BITS_PER_AU)
+			val = 0;
+		else if (stackp != NULL)
+			val = *stackp << val;
+		break;
+	case RACT_AND:
+		if (stackp != NULL)
+			val &= *stackp;
+		break;
+	case RACT_OR:
+		if (stackp != NULL)
+			val |= *stackp;
+		break;
+	case RACT_XOR:
+		if (stackp != NULL)
+			val ^= *stackp;
+		break;
+	case RACT_NOT:
+		val = ~val;
+		break;
+#if TMS32060
+	case RACT_C6SECT:
+		/* actually needed address of secn containing symbol */
+		if (svp != NULL) {
+			if (rp->SYMNDX >= 0)
+				if (svp->secnn > 0)
+					reloc_amt = dlthis->ldr_sections
+					    [svp->secnn - 1].run_addr;
+		}
+		/* !!! FALL THRU !!! */
+	case RACT_C6BASE:
+		if (dlthis->bss_run_base == 0) {
+			struct dynload_symbol *symp;
+			symp = dlthis->mysym->find_matching_symbol
+			    (dlthis->mysym, bsssymbol);
+			/* lookup value of global BSS base */
+			if (symp)
+				dlthis->bss_run_base = symp->value;
+			else
+				dload_error(dlthis,
+					    "Global BSS base referenced in %s "
+					    "offset" FMT_UI32 " but not "
+					    "defined",
+					    dlthis->image_secn->name,
+					    rp->vaddr + dlthis->image_offset);
+		}
+		reloc_amt -= dlthis->bss_run_base;
+		/* !!! FALL THRU !!! */
+	case RACT_C6DSPL:
+		/* scale factor determined by 3 LSBs of field */
+		scale = c60_scale[val & SCALE_MASK];
+		offset += SCALE_BITS;
+		fieldsz -= SCALE_BITS;
+		val >>= SCALE_BITS;	/* ignore the scale field hereafter */
+		val <<= scale;
+		val += reloc_amt;	/* do the usual relocation */
+		if (((1 << scale) - 1) & val)
+			dload_error(dlthis,
+				    "Unaligned reference in %s offset "
+				    FMT_UI32, dlthis->image_secn->name,
+				    rp->vaddr + dlthis->image_offset);
+		break;
+#endif
+	}			/* relocation actions */
+	/* * Put back result as required */
+	if (reloc_info & ROP_W) {	/* relocation writes image value */
+#ifdef RFV_SCALE
+		val >>= scale;
+#endif
+		if (dload_repack(dlthis, val, data, fieldsz, offset,
+				 RFV_SIGN(reloc_info))) {
+			/* Check to see if this relo can be trampolined,
+			 * but only in first phase relocation.  2nd phase
+			 * relocation cannot trampoline. */
+			if ((second_pass == false) &&
+			    (dload_tramp_avail(dlthis, rp) == true)) {
+
+				/* Before generating the trampoline, restore
+				 * the value to its original so the 2nd pass
+				 *  relo will work. */
+				dload_repack(dlthis, orig_val, data, fieldsz,
+					     offset, RFV_SIGN(reloc_info));
+				if (!dload_tramp_generate(dlthis,
+							(dlthis->image_secn -
+							 dlthis->ldr_sections),
+							 dlthis->image_offset,
+							 img_pkt, rp)) {
+					dload_error(dlthis,
+						    "Failed to "
+						    "generate trampoline for "
+						    "bit overflow");
+					dload_error(dlthis,
+						    "Relocation val " FMT_UI32
+						    " overflows %d bits in %s "
+						    "offset " FMT_UI32, val,
+						    fieldsz,
+						    dlthis->image_secn->name,
+						    dlthis->image_offset +
+						    rp->vaddr);
+				} else
+					*tramps_genereted = true;
+			} else {
+				dload_error(dlthis, "Relocation value "
+					    FMT_UI32 " overflows %d bits in %s"
+					    " offset " FMT_UI32, val, fieldsz,
+					    dlthis->image_secn->name,
+					    dlthis->image_offset + rp->vaddr);
+			}
+		}
+	} else if (top)
+		*stackp = val;
+}				/* reloc_value */
diff --git a/drivers/staging/tidspbridge/dynload/reloc_table.h b/drivers/staging/tidspbridge/dynload/reloc_table.h
new file mode 100644
index 0000000..6aab03d
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/reloc_table.h
@@ -0,0 +1,102 @@
+/*
+ * reloc_table.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef _RELOC_TABLE_H_
+#define _RELOC_TABLE_H_
+/*
+ * Table of relocation operator properties
+ */
+#include <linux/types.h>
+
+/* How does this relocation operation access the program image? */
+#define ROP_N	0		/* does not access image */
+#define ROP_R	1		/* read from image */
+#define ROP_W	2		/* write to image */
+#define ROP_RW	3		/* read from and write to image */
+
+/* For program image access, what are the overflow rules for the bit field? */
+/* Beware! Procedure repack depends on this encoding */
+#define ROP_ANY	0		/* no overflow ever, just truncate the value */
+#define ROP_SGN	1		/* signed field */
+#define ROP_UNS	2		/* unsigned field */
+#define ROP_MAX 3	/* allow maximum range of either signed or unsigned */
+
+/* How does the relocation operation use the symbol reference */
+#define ROP_IGN	0		/* no symbol is referenced */
+#define ROP_LIT 0		/* use rp->UVAL literal field */
+#define ROP_SYM	1		/* symbol value is used in relocation */
+#define ROP_SYMD 2		/* delta value vs last link is used */
+
+/* How does the reloc op use the stack? */
+#define RSTK_N 0		/* Does not use */
+#define RSTK_POP 1		/* Does a POP */
+#define RSTK_UOP 2		/* Unary op, stack position unaffected */
+#define RSTK_PSH 3		/* Does a push */
+
+/*
+ * Computational actions performed by the dynamic loader
+ */
+enum dload_actions {
+	/* don't alter the current val (from stack or mem fetch) */
+	RACT_VAL,
+	/* set value to reference amount (from symbol reference) */
+	RACT_ASGN,
+	RACT_ADD,		/* add reference to value */
+	RACT_PCR,		/* add reference minus PC delta to value */
+	RACT_ADDISP,		/* add reference plus R_DISP */
+	RACT_ASGPC,		/* set value to section addr plus reference */
+
+	RACT_PLUS,		/* stack + */
+	RACT_SUB,		/* stack - */
+	RACT_NEG,		/* stack unary - */
+
+	RACT_MPY,		/* stack * */
+	RACT_DIV,		/* stack / */
+	RACT_MOD,		/* stack % */
+
+	RACT_SR,		/* stack unsigned >> */
+	RACT_ASR,		/* stack signed >> */
+	RACT_SL,		/* stack << */
+	RACT_AND,		/* stack & */
+	RACT_OR,		/* stack | */
+	RACT_XOR,		/* stack ^ */
+	RACT_NOT,		/* stack ~ */
+	RACT_C6SECT,		/* for C60 R_SECT op */
+	RACT_C6BASE,		/* for C60 R_BASE op */
+	RACT_C6DSPL,		/* for C60 scaled 15-bit displacement */
+	RACT_PCR23T		/* for ARM Thumb long branch */
+};
+
+/*
+ * macros used to extract values
+ */
+#define RFV_POSN(aaa) ((aaa) & 0xF)
+#define RFV_WIDTH(aaa) (((aaa) >> 4) & 0x3F)
+#define RFV_ACTION(aaa) ((aaa) >> 10)
+
+#define RFV_SIGN(iii) (((iii) >> 2) & 0x3)
+#define RFV_SYM(iii) (((iii) >> 4) & 0x3)
+#define RFV_STK(iii) (((iii) >> 6) & 0x3)
+#define RFV_ACCS(iii) ((iii) & 0x3)
+
+#if (TMS32060)
+#define RFV_SCALE(iii) ((iii) >> 11)
+#define RFV_BIGOFF(iii) (((iii) >> 8) & 0x7)
+#else
+#define RFV_BIGOFF(iii) ((iii) >> 8)
+#endif
+
+#endif /* _RELOC_TABLE_H_ */
diff --git a/drivers/staging/tidspbridge/dynload/reloc_table_c6000.c b/drivers/staging/tidspbridge/dynload/reloc_table_c6000.c
new file mode 100644
index 0000000..8ae3b38
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/reloc_table_c6000.c
@@ -0,0 +1,257 @@
+/*
+ * reloc_table_c6000.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* Tables generated for c6000 */
+
+#define HASH_FUNC(zz) (((((zz) + 1) * UINT32_C(1845)) >> 11) & 63)
+#define HASH_L(zz) ((zz) >> 8)
+#define HASH_I(zz) ((zz) & 0xFF)
+
+static const u16 rop_map1[] = {
+	0,
+	1,
+	2,
+	20,
+	4,
+	5,
+	6,
+	15,
+	80,
+	81,
+	82,
+	83,
+	84,
+	85,
+	86,
+	87,
+	17,
+	18,
+	19,
+	21,
+	16,
+	16394,
+	16404,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	32,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	40,
+	112,
+	113,
+	65535,
+	16384,
+	16385,
+	16386,
+	16387,
+	16388,
+	16389,
+	16390,
+	16391,
+	16392,
+	16393,
+	16395,
+	16396,
+	16397,
+	16398,
+	16399,
+	16400,
+	16401,
+	16402,
+	16403,
+	16405,
+	16406,
+	65535,
+	65535,
+	65535
+};
+
+static const s16 rop_map2[] = {
+	-256,
+	-255,
+	-254,
+	-245,
+	-253,
+	-252,
+	-251,
+	-250,
+	-241,
+	-240,
+	-239,
+	-238,
+	-237,
+	-236,
+	1813,
+	5142,
+	-248,
+	-247,
+	778,
+	-244,
+	-249,
+	-221,
+	-211,
+	-1,
+	-1,
+	-1,
+	-1,
+	-1,
+	-1,
+	-243,
+	-1,
+	-1,
+	-1,
+	-1,
+	-1,
+	-1,
+	-242,
+	-233,
+	-232,
+	-1,
+	-231,
+	-230,
+	-229,
+	-228,
+	-227,
+	-226,
+	-225,
+	-224,
+	-223,
+	5410,
+	-220,
+	-219,
+	-218,
+	-217,
+	-216,
+	-215,
+	-214,
+	-213,
+	5676,
+	-210,
+	-209,
+	-1,
+	-1,
+	-1
+};
+
+static const u16 rop_action[] = {
+	2560,
+	2304,
+	2304,
+	2432,
+	2432,
+	2560,
+	2176,
+	2304,
+	2560,
+	3200,
+	3328,
+	3584,
+	3456,
+	2304,
+	4208,
+	20788,
+	21812,
+	3415,
+	3245,
+	2311,
+	4359,
+	19764,
+	2311,
+	3191,
+	3280,
+	6656,
+	7680,
+	8704,
+	9728,
+	10752,
+	11776,
+	12800,
+	13824,
+	14848,
+	15872,
+	16896,
+	17920,
+	18944,
+	0,
+	0,
+	0,
+	0,
+	1536,
+	1536,
+	1536,
+	5632,
+	512,
+	0
+};
+
+static const u16 rop_info[] = {
+	0,
+	35,
+	35,
+	35,
+	35,
+	35,
+	35,
+	35,
+	35,
+	39,
+	39,
+	39,
+	39,
+	35,
+	34,
+	283,
+	299,
+	4135,
+	4391,
+	291,
+	33059,
+	283,
+	295,
+	4647,
+	4135,
+	64,
+	64,
+	128,
+	64,
+	64,
+	64,
+	64,
+	64,
+	64,
+	64,
+	64,
+	64,
+	128,
+	201,
+	197,
+	74,
+	70,
+	208,
+	196,
+	200,
+	192,
+	192,
+	66
+};
diff --git a/drivers/staging/tidspbridge/dynload/tramp.c b/drivers/staging/tidspbridge/dynload/tramp.c
new file mode 100644
index 0000000..7b593fc
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/tramp.c
@@ -0,0 +1,1143 @@
+/*
+ * tramp.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "header.h"
+
+#if TMS32060
+#include "tramp_table_c6000.c"
+#endif
+
+#define MAX_RELOS_PER_PASS	4
+
+/*
+ * Function:	priv_tramp_sect_tgt_alloc
+ * Description: Allocate target memory for the trampoline section.  The
+ *	  target mem size is easily obtained as the next available address.
+ */
+static int priv_tramp_sect_tgt_alloc(struct dload_state *dlthis)
+{
+	int ret_val = 0;
+	struct ldr_section_info *sect_info;
+
+	/*  Populate the trampoline loader section and allocate it on the
+	 * target.  The section name is ALWAYS the first string in the final
+	 * string table for trampolines.  The trampoline section is always
+	 * 1 beyond the total number of allocated sections. */
+	sect_info = &dlthis->ldr_sections[dlthis->allocated_secn_count];
+
+	sect_info->name = dlthis->tramp.final_string_table;
+	sect_info->size = dlthis->tramp.tramp_sect_next_addr;
+	sect_info->context = 0;
+	sect_info->type =
+	    (4 << 8) | DLOAD_TEXT | DS_ALLOCATE_MASK | DS_DOWNLOAD_MASK;
+	sect_info->page = 0;
+	sect_info->run_addr = 0;
+	sect_info->load_addr = 0;
+	ret_val = dlthis->myalloc->dload_allocate(dlthis->myalloc,
+						  sect_info,
+						  DS_ALIGNMENT
+						  (sect_info->type));
+
+	if (ret_val == 0)
+		dload_error(dlthis, "Failed to allocate target memory for"
+			    " trampoline");
+
+	return ret_val;
+}
+
+/*
+ * Function:	priv_h2a
+ * Description: Helper function to convert a hex value to its ASCII
+ *	  representation.  Used for trampoline symbol name generation.
+ */
+static u8 priv_h2a(u8 value)
+{
+	if (value > 0xF)
+		return 0xFF;
+
+	if (value <= 9)
+		value += 0x30;
+	else
+		value += 0x37;
+
+	return value;
+}
+
+/*
+ * Function:	priv_tramp_sym_gen_name
+ * Description: Generate a trampoline symbol name (ASCII) using the value
+ *	  of the symbol.  This places the new name into the user buffer.
+ *	  The name is fixed in length and of the form: __$dbTR__xxxxxxxx
+ *	  (where "xxxxxxxx" is the hex value.
+ */
+static void priv_tramp_sym_gen_name(u32 value, char *dst)
+{
+	u32 i;
+	volatile char *prefix = TRAMP_SYM_PREFIX;
+	volatile char *dst_local = dst;
+	u8 tmp;
+
+	/*  Clear out the destination, including the ending NULL */
+	for (i = 0; i < (TRAMP_SYM_PREFIX_LEN + TRAMP_SYM_HEX_ASCII_LEN); i++)
+		*(dst_local + i) = 0;
+
+	/*  Copy the prefix to start */
+	for (i = 0; i < strlen(TRAMP_SYM_PREFIX); i++) {
+		*dst_local = *(prefix + i);
+		dst_local++;
+	}
+
+	/*  Now convert the value passed in to a string equiv of the hex */
+	for (i = 0; i < sizeof(value); i++) {
+#ifndef _BIG_ENDIAN
+		tmp = *(((u8 *) &value) + (sizeof(value) - 1) - i);
+		*dst_local = priv_h2a((tmp & 0xF0) >> 4);
+		dst_local++;
+		*dst_local = priv_h2a(tmp & 0x0F);
+		dst_local++;
+#else
+		tmp = *(((u8 *) &value) + i);
+		*dst_local = priv_h2a((tmp & 0xF0) >> 4);
+		dst_local++;
+		*dst_local = priv_h2a(tmp & 0x0F);
+		dst_local++;
+#endif
+	}
+
+	/*  NULL terminate */
+	*dst_local = 0;
+}
+
+/*
+ * Function:	priv_tramp_string_create
+ * Description: Create a new string specific to the trampoline loading and add
+ *	  it to the trampoline string list.  This list contains the
+ *	  trampoline section name and trampoline point symbols.
+ */
+static struct tramp_string *priv_tramp_string_create(struct dload_state *dlthis,
+						     u32 str_len, char *str)
+{
+	struct tramp_string *new_string = NULL;
+	u32 i;
+
+	/*  Create a new string object with the specified size. */
+	new_string =
+	    (struct tramp_string *)dlthis->mysym->dload_allocate(dlthis->mysym,
+								 (sizeof
+								  (struct
+								   tramp_string)
+								  + str_len +
+								  1));
+	if (new_string != NULL) {
+		/*  Clear the string first.  This ensures the ending NULL is
+		 * present and the optimizer won't touch it. */
+		for (i = 0; i < (sizeof(struct tramp_string) + str_len + 1);
+		     i++)
+			*((u8 *) new_string + i) = 0;
+
+		/*  Add this string to our virtual table by assigning it the
+		 * next index and pushing it to the tail of the list. */
+		new_string->index = dlthis->tramp.tramp_string_next_index;
+		dlthis->tramp.tramp_string_next_index++;
+		dlthis->tramp.tramp_string_size += str_len + 1;
+
+		new_string->next = NULL;
+		if (dlthis->tramp.string_head == NULL)
+			dlthis->tramp.string_head = new_string;
+		else
+			dlthis->tramp.string_tail->next = new_string;
+
+		dlthis->tramp.string_tail = new_string;
+
+		/*  Copy the string over to the new object */
+		for (i = 0; i < str_len; i++)
+			new_string->str[i] = str[i];
+	}
+
+	return new_string;
+}
+
+/*
+ * Function:	priv_tramp_string_find
+ * Description: Walk the trampoline string list and find a match for the
+ *	  provided string.  If not match is found, NULL is returned.
+ */
+static struct tramp_string *priv_tramp_string_find(struct dload_state *dlthis,
+						   char *str)
+{
+	struct tramp_string *cur_str = NULL;
+	struct tramp_string *ret_val = NULL;
+	u32 i;
+	u32 str_len = strlen(str);
+
+	for (cur_str = dlthis->tramp.string_head;
+	     (ret_val == NULL) && (cur_str != NULL); cur_str = cur_str->next) {
+		/*  If the string lengths aren't equal, don't bother
+		 * comparing */
+		if (str_len != strlen(cur_str->str))
+			continue;
+
+		/*  Walk the strings until one of them ends */
+		for (i = 0; i < str_len; i++) {
+			/*  If they don't match in the current position then
+			 * break out now, no sense in continuing to look at
+			 * this string. */
+			if (str[i] != cur_str->str[i])
+				break;
+		}
+
+		if (i == str_len)
+			ret_val = cur_str;
+	}
+
+	return ret_val;
+}
+
+/*
+ * Function:	priv_string_tbl_finalize
+ * Description: Flatten the trampoline string list into a table of NULL
+ *	  terminated strings.  This is the same format of string table
+ *	  as used by the COFF/DOFF file.
+ */
+static int priv_string_tbl_finalize(struct dload_state *dlthis)
+{
+	int ret_val = 0;
+	struct tramp_string *cur_string;
+	char *cur_loc;
+	char *tmp;
+
+	/*  Allocate enough space for all strings that have been created.  The
+	 * table is simply all strings concatenated together will NULL
+	 * endings. */
+	dlthis->tramp.final_string_table =
+	    (char *)dlthis->mysym->dload_allocate(dlthis->mysym,
+						  dlthis->tramp.
+						  tramp_string_size);
+	if (dlthis->tramp.final_string_table != NULL) {
+		/*  We got our buffer, walk the list and release the nodes as*
+		 * we go */
+		cur_loc = dlthis->tramp.final_string_table;
+		cur_string = dlthis->tramp.string_head;
+		while (cur_string != NULL) {
+			/*  Move the head/tail pointers */
+			dlthis->tramp.string_head = cur_string->next;
+			if (dlthis->tramp.string_tail == cur_string)
+				dlthis->tramp.string_tail = NULL;
+
+			/*  Copy the string contents */
+			for (tmp = cur_string->str;
+			     *tmp != '\0'; tmp++, cur_loc++)
+				*cur_loc = *tmp;
+
+			/*  Pick up the NULL termination since it was missed by
+			 * breaking using it to end the above loop. */
+			*cur_loc = '\0';
+			cur_loc++;
+
+			/*  Free the string node, we don't need it any more. */
+			dlthis->mysym->dload_deallocate(dlthis->mysym,
+							cur_string);
+
+			/*  Move our pointer to the next one */
+			cur_string = dlthis->tramp.string_head;
+		}
+
+		/*  Update our return value to success */
+		ret_val = 1;
+	} else
+		dload_error(dlthis, "Failed to allocate trampoline "
+			    "string table");
+
+	return ret_val;
+}
+
+/*
+ * Function:	priv_tramp_sect_alloc
+ * Description: Virtually allocate space from the trampoline section.  This
+ *	  function returns the next offset within the trampoline section
+ *	  that is available and moved the next available offset by the
+ *	  requested size.  NO TARGET ALLOCATION IS DONE AT THIS TIME.
+ */
+static u32 priv_tramp_sect_alloc(struct dload_state *dlthis, u32 tramp_size)
+{
+	u32 ret_val;
+
+	/*  If the next available address is 0, this is our first allocation.
+	 * Create a section name string to go into the string table . */
+	if (dlthis->tramp.tramp_sect_next_addr == 0) {
+		dload_syms_error(dlthis->mysym, "*** WARNING ***  created "
+				 "dynamic TRAMPOLINE section for module %s",
+				 dlthis->str_head);
+	}
+
+	/*  Reserve space for the new trampoline */
+	ret_val = dlthis->tramp.tramp_sect_next_addr;
+	dlthis->tramp.tramp_sect_next_addr += tramp_size;
+	return ret_val;
+}
+
+/*
+ * Function:	priv_tramp_sym_create
+ * Description: Allocate and create a new trampoline specific symbol and add
+ *	  it to the trampoline symbol list.  These symbols will include
+ *	  trampoline points as well as the external symbols they
+ *	  reference.
+ */
+static struct tramp_sym *priv_tramp_sym_create(struct dload_state *dlthis,
+					       u32 str_index,
+					       struct local_symbol *tmp_sym)
+{
+	struct tramp_sym *new_sym = NULL;
+	u32 i;
+
+	/*  Allocate new space for the symbol in the symbol table. */
+	new_sym =
+	    (struct tramp_sym *)dlthis->mysym->dload_allocate(dlthis->mysym,
+					      sizeof(struct tramp_sym));
+	if (new_sym != NULL) {
+		for (i = 0; i != sizeof(struct tramp_sym); i++)
+			*((char *)new_sym + i) = 0;
+
+		/*  Assign this symbol the next symbol index for easier
+		 * reference later during relocation. */
+		new_sym->index = dlthis->tramp.tramp_sym_next_index;
+		dlthis->tramp.tramp_sym_next_index++;
+
+		/*  Populate the symbol information.  At this point any
+		 * trampoline symbols will be the offset location, not the
+		 * final.  Copy over the symbol info to start, then be sure to
+		 * get the string index from the trampoline string table. */
+		new_sym->sym_info = *tmp_sym;
+		new_sym->str_index = str_index;
+
+		/*  Push the new symbol to the tail of the symbol table list */
+		new_sym->next = NULL;
+		if (dlthis->tramp.symbol_head == NULL)
+			dlthis->tramp.symbol_head = new_sym;
+		else
+			dlthis->tramp.symbol_tail->next = new_sym;
+
+		dlthis->tramp.symbol_tail = new_sym;
+	}
+
+	return new_sym;
+}
+
+/*
+ * Function:	priv_tramp_sym_get
+ * Description: Search for the symbol with the matching string index (from
+ *	  the trampoline string table) and return the trampoline
+ *	  symbol object, if found.  Otherwise return NULL.
+ */
+static struct tramp_sym *priv_tramp_sym_get(struct dload_state *dlthis,
+					    u32 string_index)
+{
+	struct tramp_sym *sym_found = NULL;
+
+	/*  Walk the symbol table list and search vs. the string index */
+	for (sym_found = dlthis->tramp.symbol_head;
+	     sym_found != NULL; sym_found = sym_found->next) {
+		if (sym_found->str_index == string_index)
+			break;
+	}
+
+	return sym_found;
+}
+
+/*
+ * Function:	priv_tramp_sym_find
+ * Description: Search for a trampoline symbol based on the string name of
+ *	  the symbol.  Return the symbol object, if found, otherwise
+ *	  return NULL.
+ */
+static struct tramp_sym *priv_tramp_sym_find(struct dload_state *dlthis,
+					     char *string)
+{
+	struct tramp_sym *sym_found = NULL;
+	struct tramp_string *str_found = NULL;
+
+	/*  First, search for the string, then search for the sym based on the
+	   string index. */
+	str_found = priv_tramp_string_find(dlthis, string);
+	if (str_found != NULL)
+		sym_found = priv_tramp_sym_get(dlthis, str_found->index);
+
+	return sym_found;
+}
+
+/*
+ * Function:	priv_tramp_sym_finalize
+ * Description: Allocate a flat symbol table for the trampoline section,
+ *	  put each trampoline symbol into the table, adjust the
+ *	  symbol value based on the section address on the target and
+ *	  free the trampoline symbol list nodes.
+ */
+static int priv_tramp_sym_finalize(struct dload_state *dlthis)
+{
+	int ret_val = 0;
+	struct tramp_sym *cur_sym;
+	struct ldr_section_info *tramp_sect =
+	    &dlthis->ldr_sections[dlthis->allocated_secn_count];
+	struct local_symbol *new_sym;
+
+	/*  Allocate a table to hold a flattened version of all symbols
+	 * created. */
+	dlthis->tramp.final_sym_table =
+	    (struct local_symbol *)dlthis->mysym->dload_allocate(dlthis->mysym,
+				 (sizeof(struct local_symbol) * dlthis->tramp.
+						  tramp_sym_next_index));
+	if (dlthis->tramp.final_sym_table != NULL) {
+		/*  Walk the list of all symbols, copy it over to the flattened
+		 * table. After it has been copied, the node can be freed as
+		 * it is no longer needed. */
+		new_sym = dlthis->tramp.final_sym_table;
+		cur_sym = dlthis->tramp.symbol_head;
+		while (cur_sym != NULL) {
+			/*  Pop it off the list */
+			dlthis->tramp.symbol_head = cur_sym->next;
+			if (cur_sym == dlthis->tramp.symbol_tail)
+				dlthis->tramp.symbol_tail = NULL;
+
+			/*  Copy the symbol contents into the flat table */
+			*new_sym = cur_sym->sym_info;
+
+			/*  Now finaize the symbol.  If it is in the tramp
+			 * section, we need to adjust for the section start.
+			 * If it is external then we don't need to adjust at
+			 * all.
+			 * NOTE: THIS CODE ASSUMES THAT THE TRAMPOLINE IS
+			 * REFERENCED LIKE A CALL TO AN EXTERNAL SO VALUE AND
+			 * DELTA ARE THE SAME.  SEE THE FUNCTION dload_symbols
+			 * WHERE DN_UNDEF IS HANDLED FOR MORE REFERENCE. */
+			if (new_sym->secnn < 0) {
+				new_sym->value += tramp_sect->load_addr;
+				new_sym->delta = new_sym->value;
+			}
+
+			/*  Let go of the symbol node */
+			dlthis->mysym->dload_deallocate(dlthis->mysym, cur_sym);
+
+			/*  Move to the next node */
+			cur_sym = dlthis->tramp.symbol_head;
+			new_sym++;
+		}
+
+		ret_val = 1;
+	} else
+		dload_error(dlthis, "Failed to alloc trampoline sym table");
+
+	return ret_val;
+}
+
+/*
+ * Function:	priv_tgt_img_gen
+ * Description: Allocate storage for and copy the target specific image data
+ *	and fix up its relocations for the new external symbol.  If
+ *	a trampoline image packet was successfully created it is added
+ *	to the trampoline list.
+ */
+static int priv_tgt_img_gen(struct dload_state *dlthis, u32 base,
+			    u32 gen_index, struct tramp_sym *new_ext_sym)
+{
+	struct tramp_img_pkt *new_img_pkt = NULL;
+	u32 i;
+	u32 pkt_size = tramp_img_pkt_size_get();
+	u8 *gen_tbl_entry;
+	u8 *pkt_data;
+	struct reloc_record_t *cur_relo;
+	int ret_val = 0;
+
+	/*  Allocate a new image packet and set it up. */
+	new_img_pkt =
+	    (struct tramp_img_pkt *)dlthis->mysym->dload_allocate(dlthis->mysym,
+								  pkt_size);
+	if (new_img_pkt != NULL) {
+		/*  Save the base, this is where it goes in the section */
+		new_img_pkt->base = base;
+
+		/*  Copy over the image data and relos from the target table */
+		pkt_data = (u8 *) &new_img_pkt->hdr;
+		gen_tbl_entry = (u8 *) &tramp_gen_info[gen_index];
+		for (i = 0; i < pkt_size; i++) {
+			*pkt_data = *gen_tbl_entry;
+			pkt_data++;
+			gen_tbl_entry++;
+		}
+
+		/*  Update the relocations to point to the external symbol */
+		cur_relo =
+		    (struct reloc_record_t *)((u8 *) &new_img_pkt->hdr +
+					      new_img_pkt->hdr.relo_offset);
+		for (i = 0; i < new_img_pkt->hdr.num_relos; i++)
+			cur_relo[i].SYMNDX = new_ext_sym->index;
+
+		/*  Add it to the trampoline list. */
+		new_img_pkt->next = dlthis->tramp.tramp_pkts;
+		dlthis->tramp.tramp_pkts = new_img_pkt;
+
+		ret_val = 1;
+	}
+
+	return ret_val;
+}
+
+/*
+ * Function:	priv_pkt_relo
+ * Description: Take the provided image data and the collection of relocations
+ *	  for it and perform the relocations.  Note that all relocations
+ *	  at this stage are considered SECOND PASS since the original
+ *	  image has already been processed in the first pass.  This means
+ *	  TRAMPOLINES ARE TREATED AS 2ND PASS even though this is really
+ *	  the first (and only) relocation that will be performed on them.
+ */
+static int priv_pkt_relo(struct dload_state *dlthis, tgt_au_t * data,
+			 struct reloc_record_t *rp[], u32 relo_count)
+{
+	int ret_val = 1;
+	u32 i;
+	bool tmp;
+
+	/*  Walk through all of the relos and process them.  This function is
+	 * the equivalent of relocate_packet() from cload.c, but specialized
+	 * for trampolines and 2nd phase relocations. */
+	for (i = 0; i < relo_count; i++)
+		dload_relocate(dlthis, data, rp[i], &tmp, true);
+
+	return ret_val;
+}
+
+/*
+ * Function:	priv_tramp_pkt_finalize
+ * Description: Walk the list of all trampoline packets and finalize them.
+ *	  Each trampoline image packet will be relocated now that the
+ *	  trampoline section has been allocated on the target.  Once
+ *	  all of the relocations are done the trampoline image data
+ *	  is written into target memory and the trampoline packet
+ *	  is freed: it is no longer needed after this point.
+ */
+static int priv_tramp_pkt_finalize(struct dload_state *dlthis)
+{
+	int ret_val = 1;
+	struct tramp_img_pkt *cur_pkt = NULL;
+	struct reloc_record_t *relos[MAX_RELOS_PER_PASS];
+	u32 relos_done;
+	u32 i;
+	struct reloc_record_t *cur_relo;
+	struct ldr_section_info *sect_info =
+	    &dlthis->ldr_sections[dlthis->allocated_secn_count];
+
+	/*  Walk the list of trampoline packets and relocate each packet.  This
+	 * function is the trampoline equivalent of dload_data() from
+	 * cload.c. */
+	cur_pkt = dlthis->tramp.tramp_pkts;
+	while ((ret_val != 0) && (cur_pkt != NULL)) {
+		/*  Remove the pkt from the list */
+		dlthis->tramp.tramp_pkts = cur_pkt->next;
+
+		/*  Setup section and image offset information for the relo */
+		dlthis->image_secn = sect_info;
+		dlthis->image_offset = cur_pkt->base;
+		dlthis->delta_runaddr = sect_info->run_addr;
+
+		/*  Walk through all relos for the packet */
+		relos_done = 0;
+		cur_relo = (struct reloc_record_t *)((u8 *) &cur_pkt->hdr +
+						     cur_pkt->hdr.relo_offset);
+		while (relos_done < cur_pkt->hdr.num_relos) {
+#ifdef ENABLE_TRAMP_DEBUG
+			dload_syms_error(dlthis->mysym,
+					 "===> Trampoline %x branches to %x",
+					 sect_info->run_addr +
+					 dlthis->image_offset,
+					 dlthis->
+					 tramp.final_sym_table[cur_relo->
+							       SYMNDX].value);
+#endif
+
+			for (i = 0;
+			     ((i < MAX_RELOS_PER_PASS) &&
+			      ((i + relos_done) < cur_pkt->hdr.num_relos)); i++)
+				relos[i] = cur_relo + i;
+
+			/*  Do the actual relo */
+			ret_val = priv_pkt_relo(dlthis,
+						(tgt_au_t *) &cur_pkt->payload,
+						relos, i);
+			if (ret_val == 0) {
+				dload_error(dlthis,
+					    "Relocation of trampoline pkt at %x"
+					    " failed", cur_pkt->base +
+					    sect_info->run_addr);
+				break;
+			}
+
+			relos_done += i;
+			cur_relo += i;
+		}
+
+		/*  Make sure we didn't hit a problem */
+		if (ret_val != 0) {
+			/*  Relos are done for the packet, write it to the
+			 * target */
+			ret_val = dlthis->myio->writemem(dlthis->myio,
+							 &cur_pkt->payload,
+							 sect_info->load_addr +
+							 cur_pkt->base,
+							 sect_info,
+							 BYTE_TO_HOST
+							 (cur_pkt->hdr.
+							  tramp_code_size));
+			if (ret_val == 0) {
+				dload_error(dlthis,
+					    "Write to " FMT_UI32 " failed",
+					    sect_info->load_addr +
+					    cur_pkt->base);
+			}
+
+			/*  Done with the pkt, let it go */
+			dlthis->mysym->dload_deallocate(dlthis->mysym, cur_pkt);
+
+			/*  Get the next packet to process */
+			cur_pkt = dlthis->tramp.tramp_pkts;
+		}
+	}
+
+	return ret_val;
+}
+
+/*
+ * Function:	priv_dup_pkt_finalize
+ * Description: Walk the list of duplicate image packets and finalize them.
+ *	  Each duplicate packet will be relocated again for the
+ *	  relocations that previously failed and have been adjusted
+ *	  to point at a trampoline.  Once all relocations for a packet
+ *	  have been done, write the packet into target memory.  The
+ *	  duplicate packet and its relocation chain are all freed
+ *	  after use here as they are no longer needed after this.
+ */
+static int priv_dup_pkt_finalize(struct dload_state *dlthis)
+{
+	int ret_val = 1;
+	struct tramp_img_dup_pkt *cur_pkt;
+	struct tramp_img_dup_relo *cur_relo;
+	struct reloc_record_t *relos[MAX_RELOS_PER_PASS];
+	struct doff_scnhdr_t *sect_hdr = NULL;
+	s32 i;
+
+	/* Similar to the trampoline pkt finalize, this function walks each dup
+	 * pkt that was generated and performs all relocations that were
+	 * deferred to a 2nd pass.  This is the equivalent of dload_data() from
+	 * cload.c, but does not need the additional reorder and checksum
+	 * processing as it has already been done. */
+	cur_pkt = dlthis->tramp.dup_pkts;
+	while ((ret_val != 0) && (cur_pkt != NULL)) {
+		/*  Remove the node from the list, we'll be freeing it
+		 * shortly */
+		dlthis->tramp.dup_pkts = cur_pkt->next;
+
+		/*  Setup the section and image offset for relocation */
+		dlthis->image_secn = &dlthis->ldr_sections[cur_pkt->secnn];
+		dlthis->image_offset = cur_pkt->offset;
+
+		/*  In order to get the delta run address, we need to reference
+		 * the original section header.  It's a bit ugly, but needed
+		 * for relo. */
+		i = (s32) (dlthis->image_secn - dlthis->ldr_sections);
+		sect_hdr = dlthis->sect_hdrs + i;
+		dlthis->delta_runaddr = sect_hdr->ds_paddr;
+
+		/*  Walk all relos in the chain and process each. */
+		cur_relo = cur_pkt->relo_chain;
+		while (cur_relo != NULL) {
+			/*  Process them a chunk at a time to be efficient */
+			for (i = 0; (i < MAX_RELOS_PER_PASS)
+			     && (cur_relo != NULL);
+			     i++, cur_relo = cur_relo->next) {
+				relos[i] = &cur_relo->relo;
+				cur_pkt->relo_chain = cur_relo->next;
+			}
+
+			/*  Do the actual relo */
+			ret_val = priv_pkt_relo(dlthis,
+						cur_pkt->img_pkt.img_data,
+						relos, i);
+			if (ret_val == 0) {
+				dload_error(dlthis,
+					    "Relocation of dup pkt at %x"
+					    " failed", cur_pkt->offset +
+					    dlthis->image_secn->run_addr);
+				break;
+			}
+
+			/*  Release all of these relos, we're done with them */
+			while (i > 0) {
+				dlthis->mysym->dload_deallocate(dlthis->mysym,
+						GET_CONTAINER
+						(relos[i - 1],
+						 struct tramp_img_dup_relo,
+						 relo));
+				i--;
+			}
+
+			/*  DO NOT ADVANCE cur_relo, IT IS ALREADY READY TO
+			 * GO! */
+		}
+
+		/* Done with all relos.  Make sure we didn't have a problem and
+		 * write it out to the target */
+		if (ret_val != 0) {
+			ret_val = dlthis->myio->writemem(dlthis->myio,
+							 cur_pkt->img_pkt.
+							 img_data,
+							 dlthis->image_secn->
+							 load_addr +
+							 cur_pkt->offset,
+							 dlthis->image_secn,
+							 BYTE_TO_HOST
+							 (cur_pkt->img_pkt.
+							  packet_size));
+			if (ret_val == 0) {
+				dload_error(dlthis,
+					    "Write to " FMT_UI32 " failed",
+					    dlthis->image_secn->load_addr +
+					    cur_pkt->offset);
+			}
+
+			dlthis->mysym->dload_deallocate(dlthis->mysym, cur_pkt);
+
+			/*  Advance to the next packet */
+			cur_pkt = dlthis->tramp.dup_pkts;
+		}
+	}
+
+	return ret_val;
+}
+
+/*
+ * Function:	priv_dup_find
+ * Description: Walk the list of existing duplicate packets and find a
+ *	  match based on the section number and image offset.  Return
+ *	  the duplicate packet if found, otherwise NULL.
+ */
+static struct tramp_img_dup_pkt *priv_dup_find(struct dload_state *dlthis,
+					       s16 secnn, u32 image_offset)
+{
+	struct tramp_img_dup_pkt *cur_pkt = NULL;
+
+	for (cur_pkt = dlthis->tramp.dup_pkts;
+	     cur_pkt != NULL; cur_pkt = cur_pkt->next) {
+		if ((cur_pkt->secnn == secnn) &&
+		    (cur_pkt->offset == image_offset)) {
+			/*  Found a match, break out */
+			break;
+		}
+	}
+
+	return cur_pkt;
+}
+
+/*
+ * Function:	priv_img_pkt_dup
+ * Description: Duplicate the original image packet.  If this is the first
+ *	  time this image packet has been seen (based on section number
+ *	  and image offset), create a new duplicate packet and add it
+ *	  to the dup packet list.  If not, just get the existing one and
+ *	  update it with the current packet contents (since relocation
+ *	  on the packet is still ongoing in first pass.)  Create a
+ *	  duplicate of the provided relocation, but update it to point
+ *	  to the new trampoline symbol.  Add the new relocation dup to
+ *	  the dup packet's relo chain for 2nd pass relocation later.
+ */
+static int priv_img_pkt_dup(struct dload_state *dlthis,
+			    s16 secnn, u32 image_offset,
+			    struct image_packet_t *ipacket,
+			    struct reloc_record_t *rp,
+			    struct tramp_sym *new_tramp_sym)
+{
+	struct tramp_img_dup_pkt *dup_pkt = NULL;
+	u32 new_dup_size;
+	s32 i;
+	int ret_val = 0;
+	struct tramp_img_dup_relo *dup_relo = NULL;
+
+	/*  Determinne if this image packet is already being tracked in the
+	   dup list for other trampolines. */
+	dup_pkt = priv_dup_find(dlthis, secnn, image_offset);
+
+	if (dup_pkt == NULL) {
+		/*  This image packet does not exist in our tracking, so create
+		 * a new one and add it to the head of the list. */
+		new_dup_size = sizeof(struct tramp_img_dup_pkt) +
+		    ipacket->packet_size;
+
+		dup_pkt = (struct tramp_img_dup_pkt *)
+		    dlthis->mysym->dload_allocate(dlthis->mysym, new_dup_size);
+		if (dup_pkt != NULL) {
+			/*  Save off the section and offset information */
+			dup_pkt->secnn = secnn;
+			dup_pkt->offset = image_offset;
+			dup_pkt->relo_chain = NULL;
+
+			/*  Copy the original packet content */
+			dup_pkt->img_pkt = *ipacket;
+			dup_pkt->img_pkt.img_data = (u8 *) (dup_pkt + 1);
+			for (i = 0; i < ipacket->packet_size; i++)
+				*(dup_pkt->img_pkt.img_data + i) =
+				    *(ipacket->img_data + i);
+
+			/*  Add the packet to the dup list */
+			dup_pkt->next = dlthis->tramp.dup_pkts;
+			dlthis->tramp.dup_pkts = dup_pkt;
+		} else
+			dload_error(dlthis, "Failed to create dup packet!");
+	} else {
+		/*  The image packet contents could have changed since
+		 * trampoline detection happens during relocation of the image
+		 * packets.  So, we need to update the image packet contents
+		 * before adding relo information. */
+		for (i = 0; i < dup_pkt->img_pkt.packet_size; i++)
+			*(dup_pkt->img_pkt.img_data + i) =
+			    *(ipacket->img_data + i);
+	}
+
+	/*  Since the previous code may have allocated a new dup packet for us,
+	   double check that we actually have one. */
+	if (dup_pkt != NULL) {
+		/*  Allocate a new node for the relo chain.  Each image packet
+		 * can potentially have multiple relocations that cause a
+		 * trampoline to be generated.  So, we keep them in a chain,
+		 * order is not important. */
+		dup_relo = dlthis->mysym->dload_allocate(dlthis->mysym,
+					 sizeof(struct tramp_img_dup_relo));
+		if (dup_relo != NULL) {
+			/*  Copy the relo contents, adjust for the new
+			 * trampoline and add it to the list. */
+			dup_relo->relo = *rp;
+			dup_relo->relo.SYMNDX = new_tramp_sym->index;
+
+			dup_relo->next = dup_pkt->relo_chain;
+			dup_pkt->relo_chain = dup_relo;
+
+			/*  That's it, we're done.  Make sure we update our
+			 * return value to be success since everything finished
+			 * ok */
+			ret_val = 1;
+		} else
+			dload_error(dlthis, "Unable to alloc dup relo");
+	}
+
+	return ret_val;
+}
+
+/*
+ * Function:	dload_tramp_avail
+ * Description: Check to see if the target supports a trampoline for this type
+ *	  of relocation.  Return true if it does, otherwise false.
+ */
+bool dload_tramp_avail(struct dload_state *dlthis, struct reloc_record_t *rp)
+{
+	bool ret_val = false;
+	u16 map_index;
+	u16 gen_index;
+
+	/*  Check type hash vs. target tramp table */
+	map_index = HASH_FUNC(rp->TYPE);
+	gen_index = tramp_map[map_index];
+	if (gen_index != TRAMP_NO_GEN_AVAIL)
+		ret_val = true;
+
+	return ret_val;
+}
+
+/*
+ * Function:	dload_tramp_generate
+ * Description: Create a new trampoline for the provided image packet and
+ *	  relocation causing problems.  This will create the trampoline
+ *	  as well as duplicate/update the image packet and relocation
+ *	  causing the problem, which will be relo'd again during
+ *	  finalization.
+ */
+int dload_tramp_generate(struct dload_state *dlthis, s16 secnn,
+			 u32 image_offset, struct image_packet_t *ipacket,
+			 struct reloc_record_t *rp)
+{
+	u16 map_index;
+	u16 gen_index;
+	int ret_val = 1;
+	char tramp_sym_str[TRAMP_SYM_PREFIX_LEN + TRAMP_SYM_HEX_ASCII_LEN];
+	struct local_symbol *ref_sym;
+	struct tramp_sym *new_tramp_sym;
+	struct tramp_sym *new_ext_sym;
+	struct tramp_string *new_tramp_str;
+	u32 new_tramp_base;
+	struct local_symbol tmp_sym;
+	struct local_symbol ext_tmp_sym;
+
+	/*  Hash the relo type to get our generator information */
+	map_index = HASH_FUNC(rp->TYPE);
+	gen_index = tramp_map[map_index];
+	if (gen_index != TRAMP_NO_GEN_AVAIL) {
+		/*  If this is the first trampoline, create the section name in
+		 * our string table for debug help later. */
+		if (dlthis->tramp.string_head == NULL) {
+			priv_tramp_string_create(dlthis,
+						 strlen(TRAMP_SECT_NAME),
+						 TRAMP_SECT_NAME);
+		}
+#ifdef ENABLE_TRAMP_DEBUG
+		dload_syms_error(dlthis->mysym,
+				 "Trampoline at img loc %x, references %x",
+				 dlthis->ldr_sections[secnn].run_addr +
+				 image_offset + rp->vaddr,
+				 dlthis->local_symtab[rp->SYMNDX].value);
+#endif
+
+		/*  Generate the trampoline string, check if already defined.
+		 * If the relo symbol index is -1, it means we need the section
+		 * info for relo later.  To do this we'll dummy up a symbol
+		 * with the section delta and run addresses. */
+		if (rp->SYMNDX == -1) {
+			ext_tmp_sym.value =
+			    dlthis->ldr_sections[secnn].run_addr;
+			ext_tmp_sym.delta = dlthis->sect_hdrs[secnn].ds_paddr;
+			ref_sym = &ext_tmp_sym;
+		} else
+			ref_sym = &(dlthis->local_symtab[rp->SYMNDX]);
+
+		priv_tramp_sym_gen_name(ref_sym->value, tramp_sym_str);
+		new_tramp_sym = priv_tramp_sym_find(dlthis, tramp_sym_str);
+		if (new_tramp_sym == NULL) {
+			/*  If tramp string not defined, create it and a new
+			 * string, and symbol for it as well as the original
+			 * symbol which caused the trampoline. */
+			new_tramp_str = priv_tramp_string_create(dlthis,
+								strlen
+								(tramp_sym_str),
+								 tramp_sym_str);
+			if (new_tramp_str == NULL) {
+				dload_error(dlthis, "Failed to create new "
+					    "trampoline string\n");
+				ret_val = 0;
+			} else {
+				/*  Allocate tramp section space for the new
+				 * tramp from the target */
+				new_tramp_base = priv_tramp_sect_alloc(dlthis,
+						       tramp_size_get());
+
+				/*  We have a string, create the new symbol and
+				 * duplicate the external. */
+				tmp_sym.value = new_tramp_base;
+				tmp_sym.delta = 0;
+				tmp_sym.secnn = -1;
+				tmp_sym.sclass = 0;
+				new_tramp_sym = priv_tramp_sym_create(dlthis,
+							      new_tramp_str->
+							      index,
+							      &tmp_sym);
+
+				new_ext_sym = priv_tramp_sym_create(dlthis, -1,
+								    ref_sym);
+
+				if ((new_tramp_sym != NULL) &&
+				    (new_ext_sym != NULL)) {
+					/*  Call the image generator to get the
+					 * new image data and fix up its
+					 * relocations for the external
+					 * symbol. */
+					ret_val = priv_tgt_img_gen(dlthis,
+								 new_tramp_base,
+								 gen_index,
+								 new_ext_sym);
+
+					/*  Add generated image data to tramp
+					 * image list */
+					if (ret_val != 1) {
+						dload_error(dlthis, "Failed to "
+							    "create img pkt for"
+							    " trampoline\n");
+					}
+				} else {
+					dload_error(dlthis, "Failed to create "
+						    "new tramp syms "
+						    "(%8.8X, %8.8X)\n",
+						    new_tramp_sym, new_ext_sym);
+					ret_val = 0;
+				}
+			}
+		}
+
+		/*  Duplicate the image data and relo record that caused the
+		 * tramp, including update the relo data to point to the tramp
+		 * symbol. */
+		if (ret_val == 1) {
+			ret_val = priv_img_pkt_dup(dlthis, secnn, image_offset,
+						   ipacket, rp, new_tramp_sym);
+			if (ret_val != 1) {
+				dload_error(dlthis, "Failed to create dup of "
+					    "original img pkt\n");
+			}
+		}
+	}
+
+	return ret_val;
+}
+
+/*
+ * Function:	dload_tramp_pkt_update
+ * Description: Update the duplicate copy of this image packet, which the
+ *	  trampoline layer is already tracking.  This is call is critical
+ *	  to make if trampolines were generated anywhere within the
+ *	  packet and first pass relo continued on the remainder.  The
+ *	  trampoline layer needs the updates image data so when 2nd
+ *	  pass relo is done during finalize the image packet can be
+ *	  written to the target since all relo is done.
+ */
+int dload_tramp_pkt_udpate(struct dload_state *dlthis, s16 secnn,
+			   u32 image_offset, struct image_packet_t *ipacket)
+{
+	struct tramp_img_dup_pkt *dup_pkt = NULL;
+	s32 i;
+	int ret_val = 0;
+
+	/*  Find the image packet in question, the caller needs us to update it
+	   since a trampoline was previously generated. */
+	dup_pkt = priv_dup_find(dlthis, secnn, image_offset);
+	if (dup_pkt != NULL) {
+		for (i = 0; i < dup_pkt->img_pkt.packet_size; i++)
+			*(dup_pkt->img_pkt.img_data + i) =
+			    *(ipacket->img_data + i);
+
+		ret_val = 1;
+	} else {
+		dload_error(dlthis,
+			    "Unable to find existing DUP pkt for %x, offset %x",
+			    secnn, image_offset);
+
+	}
+
+	return ret_val;
+}
+
+/*
+ * Function:	dload_tramp_finalize
+ * Description: If any trampolines were created, finalize everything on the
+ *	  target by allocating the trampoline section on the target,
+ *	  finalizing the trampoline symbols, finalizing the trampoline
+ *	  packets (write the new section to target memory) and finalize
+ *	  the duplicate packets by doing 2nd pass relo over them.
+ */
+int dload_tramp_finalize(struct dload_state *dlthis)
+{
+	int ret_val = 1;
+
+	if (dlthis->tramp.tramp_sect_next_addr != 0) {
+		/*  Finalize strings into a flat table.  This is needed so it
+		 * can be added to the debug string table later. */
+		ret_val = priv_string_tbl_finalize(dlthis);
+
+		/*  Do target allocation for section BEFORE finalizing
+		 * symbols. */
+		if (ret_val != 0)
+			ret_val = priv_tramp_sect_tgt_alloc(dlthis);
+
+		/*  Finalize symbols with their correct target information and
+		 * flatten */
+		if (ret_val != 0)
+			ret_val = priv_tramp_sym_finalize(dlthis);
+
+		/*  Finalize all trampoline packets.  This performs the
+		 * relocation on the packets as well as writing them to target
+		 * memory. */
+		if (ret_val != 0)
+			ret_val = priv_tramp_pkt_finalize(dlthis);
+
+		/*  Perform a 2nd pass relocation on the dup list. */
+		if (ret_val != 0)
+			ret_val = priv_dup_pkt_finalize(dlthis);
+	}
+
+	return ret_val;
+}
+
+/*
+ * Function:	dload_tramp_cleanup
+ * Description: Release all temporary resources used in the trampoline layer.
+ *	  Note that the target memory which may have been allocated and
+ *	  written to store the trampolines is NOT RELEASED HERE since it
+ *	  is potentially still in use.  It is automatically released
+ *	  when the module is unloaded.
+ */
+void dload_tramp_cleanup(struct dload_state *dlthis)
+{
+	struct tramp_info *tramp = &dlthis->tramp;
+	struct tramp_sym *cur_sym;
+	struct tramp_string *cur_string;
+	struct tramp_img_pkt *cur_tramp_pkt;
+	struct tramp_img_dup_pkt *cur_dup_pkt;
+	struct tramp_img_dup_relo *cur_dup_relo;
+
+	/*  If there were no tramps generated, just return */
+	if (tramp->tramp_sect_next_addr == 0)
+		return;
+
+	/*  Destroy all tramp information */
+	for (cur_sym = tramp->symbol_head;
+	     cur_sym != NULL; cur_sym = tramp->symbol_head) {
+		tramp->symbol_head = cur_sym->next;
+		if (tramp->symbol_tail == cur_sym)
+			tramp->symbol_tail = NULL;
+
+		dlthis->mysym->dload_deallocate(dlthis->mysym, cur_sym);
+	}
+
+	if (tramp->final_sym_table != NULL)
+		dlthis->mysym->dload_deallocate(dlthis->mysym,
+						tramp->final_sym_table);
+
+	for (cur_string = tramp->string_head;
+	     cur_string != NULL; cur_string = tramp->string_head) {
+		tramp->string_head = cur_string->next;
+		if (tramp->string_tail == cur_string)
+			tramp->string_tail = NULL;
+
+		dlthis->mysym->dload_deallocate(dlthis->mysym, cur_string);
+	}
+
+	if (tramp->final_string_table != NULL)
+		dlthis->mysym->dload_deallocate(dlthis->mysym,
+						tramp->final_string_table);
+
+	for (cur_tramp_pkt = tramp->tramp_pkts;
+	     cur_tramp_pkt != NULL; cur_tramp_pkt = tramp->tramp_pkts) {
+		tramp->tramp_pkts = cur_tramp_pkt->next;
+		dlthis->mysym->dload_deallocate(dlthis->mysym, cur_tramp_pkt);
+	}
+
+	for (cur_dup_pkt = tramp->dup_pkts;
+	     cur_dup_pkt != NULL; cur_dup_pkt = tramp->dup_pkts) {
+		tramp->dup_pkts = cur_dup_pkt->next;
+
+		for (cur_dup_relo = cur_dup_pkt->relo_chain;
+		     cur_dup_relo != NULL;
+		     cur_dup_relo = cur_dup_pkt->relo_chain) {
+			cur_dup_pkt->relo_chain = cur_dup_relo->next;
+			dlthis->mysym->dload_deallocate(dlthis->mysym,
+							cur_dup_relo);
+		}
+
+		dlthis->mysym->dload_deallocate(dlthis->mysym, cur_dup_pkt);
+	}
+}
diff --git a/drivers/staging/tidspbridge/dynload/tramp_table_c6000.c b/drivers/staging/tidspbridge/dynload/tramp_table_c6000.c
new file mode 100644
index 0000000..e38d631
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/tramp_table_c6000.c
@@ -0,0 +1,164 @@
+/*
+ * tramp_table_c6000.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "dload_internal.h"
+
+/*  These are defined in coff.h, but may not be available on all platforms
+	so we'll go ahead and define them here. */
+#ifndef R_C60LO16
+#define R_C60LO16	  0x54	/* C60: MVK Low Half Register */
+#define R_C60HI16	  0x55	/* C60: MVKH/MVKLH High Half Register */
+#endif
+
+#define C6X_TRAMP_WORD_COUNT			8
+#define C6X_TRAMP_MAX_RELOS			 8
+
+/*  THIS HASH FUNCTION MUST MATCH THE ONE IN reloc_table_c6000.c */
+#define HASH_FUNC(zz) (((((zz) + 1) * UINT32_C(1845)) >> 11) & 63)
+
+/*  THIS MUST MATCH reloc_record_t FOR A SYMBOL BASED RELO */
+struct c6000_relo_record {
+	s32 vaddr;
+	s32 symndx;
+#ifndef _BIG_ENDIAN
+	u16 disp;
+	u16 type;
+#else
+	u16 type;
+	u16 disp;
+#endif
+};
+
+struct c6000_gen_code {
+	struct tramp_gen_code_hdr hdr;
+	u32 tramp_instrs[C6X_TRAMP_WORD_COUNT];
+	struct c6000_relo_record relos[C6X_TRAMP_MAX_RELOS];
+};
+
+/*  Hash mapping for relos that can cause trampolines. */
+static const u16 tramp_map[] = {
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	0,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535,
+	65535
+};
+
+static const struct c6000_gen_code tramp_gen_info[] = {
+	/*  Tramp caused by R_C60PCR21 */
+	{
+	 /*  Header - 8 instructions, 2 relos */
+	 {
+	  sizeof(u32) * C6X_TRAMP_WORD_COUNT,
+	  2,
+	  FIELD_OFFSET(struct c6000_gen_code, relos)
+	  },
+
+	 /*  Trampoline instructions */
+	 {
+	  0x053C54F7,		/*       STW.D2T2  B10, *sp--[2] */
+	  0x0500002A,		/*  || MVK.S2   <blank>, B10 */
+	  0x0500006A,		/*       MVKH.S2   <blank>, B10 */
+	  0x00280362,		/*       B.S2     B10 */
+	  0x053C52E6,		/*       LDW.D2T2  *++sp[2], B10 */
+	  0x00006000,		/*       NOP       4 */
+	  0x00000000,		/*       NOP */
+	  0x00000000		/*       NOP */
+	  },
+
+	 /*  Relocations */
+	 {
+	  {4, 0, 0, R_C60LO16},
+	  {8, 0, 0, R_C60HI16},
+	  {0, 0, 0, 0x0000},
+	  {0, 0, 0, 0x0000},
+	  {0, 0, 0, 0x0000},
+	  {0, 0, 0, 0x0000},
+	  {0, 0, 0, 0x0000},
+	  {0, 0, 0, 0x0000}
+	  }
+	 }
+};
+
+/*  TARGET SPECIFIC FUNCTIONS THAT MUST BE DEFINED */
+static u32 tramp_size_get(void)
+{
+	return sizeof(u32) * C6X_TRAMP_WORD_COUNT;
+}
+
+static u32 tramp_img_pkt_size_get(void)
+{
+	return sizeof(struct c6000_gen_code);
+}
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ