All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ohad Ben-Cohen <ohad@wizery.com>
To: Greg KH <greg@kroah.com>
Cc: <linux-kernel@vger.kernel.org>, <linux-omap@vger.kernel.org>,
	Hebbar Shivananda <x0hebbar@ti.com>,
	Ramos Falcon Ernesto <ernesto@ti.com>, Anna Suman <s-anna@ti.com>,
	Kanigeri Hari <h-kanigeri2@ti.com>,
	Felipe Contreras <felipe.contreras@gmail.com>,
	Felipe Balbi <felipe.balbi@nokia.com>,
	Hiroshi DOYU <Hiroshi.DOYU@nokia.com>,
	Gupta Ramesh <grgupta@ti.com>,
	Guzman Lugo Fernando <fernando.lugo@ti.com>,
	Tony Lindgren <tony@atomide.com>,
	Ameya Palande <ameya.palande@nokia.com>,
	Gomez Castellanos Ivan <ivan.gomez@ti.com>,
	Andy Shevchenko <ext-andriy.shevchenko@nokia.com>,
	Armando Uribe De Leon <x0095078@ti.com>,
	Deepak Chitriki <deepak.chitriki@ti.com>,
	Menon Nishanth <nm@ti.com>,
	Phil Carmody <ext-phil.2.carmody@nokia.com>,
	Pitney Gilbert <gpitney@ti.com>, Bhavin Shah <bshah@ti.com>,
	Omar Ramirez Luna <omar.ramirez@ti.com>,
	Ohad Ben-Cohen <ohad@wizery.com>
Subject: [PATCH 08/11] staging: ti dspbridge: add DOFF binaries loader
Date: Wed, 23 Jun 2010 16:02:02 +0300	[thread overview]
Message-ID: <1277298125-17991-9-git-send-email-ohad@wizery.com> (raw)
In-Reply-To: <1277298125-17991-1-git-send-email-ohad@wizery.com>

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

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

Signed-off-by: Omar Ramirez Luna <omar.ramirez@ti.com>
Signed-off-by: Kanigeri, Hari <h-kanigeri2@ti.com>
Signed-off-by: Ameya Palande <ameya.palande@nokia.com>
Signed-off-by: Guzman Lugo, Fernando <fernando.lugo@ti.com>
Signed-off-by: Hebbar, Shivananda <x0hebbar@ti.com>
Signed-off-by: Ramos Falcon, Ernesto <ernesto@ti.com>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
Signed-off-by: Anna, Suman <s-anna@ti.com>
Signed-off-by: Gupta, Ramesh <grgupta@ti.com>
Signed-off-by: Gomez Castellanos, Ivan <ivan.gomez@ti.com>
Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>
Signed-off-by: Armando Uribe De Leon <x0095078@ti.com>
Signed-off-by: Deepak Chitriki <deepak.chitriki@ti.com>
Signed-off-by: Menon, Nishanth <nm@ti.com>
Signed-off-by: Phil Carmody <ext-phil.2.carmody@nokia.com>
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.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


WARNING: multiple messages have this Message-ID (diff)
From: Ohad Ben-Cohen <ohad@wizery.com>
To: Greg KH <greg@kroah.com>
Cc: linux-kernel@vger.kernel.org, linux-omap@vger.kernel.org,
	Hebbar Shivananda <x0hebbar@ti.com>,
	Ramos Falcon Ernesto <ernesto@ti.com>, Anna Suman <s-anna@ti.com>,
	Kanigeri Hari <h-kanigeri2@ti.com>,
	Felipe Contreras <felipe.contreras@gmail.com>,
	Felipe Balbi <felipe.balbi@nokia.com>,
	Hiroshi DOYU <Hiroshi.DOYU@nokia.com>,
	Gupta Ramesh <grgupta@ti.com>,
	Guzman Lugo Fernando <fernando.lugo@ti.com>,
	Tony Lindgren <tony@atomide.com>,
	Ameya Palande <ameya.palande@nokia.com>,
	Gomez Castellanos Ivan <ivan.gomez@ti.com>,
	Andy Shevchenko <ext-andriy.shevchenko@nokia.com>,
	Armando Uribe De Leon <x0095078@ti.com>,
	Deepak Chitriki <deepak.chitriki@ti.com>,
	Menon Nishanth <nm@ti.com>,
	Phil Carmody <ext-phil.2.carmody@nokia.com>,
	Pitney Gilbert <gpitney@ti.com>, Bhavin Shah <bshah@ti.com>,
	Omar Ramirez Luna <omar.ramirez@ti.com>,
	Ohad Ben-Cohen <ohad@wizery.com>
Subject: [PATCH 08/11] staging: ti dspbridge: add DOFF binaries loader
Date: Wed, 23 Jun 2010 16:02:02 +0300	[thread overview]
Message-ID: <1277298125-17991-9-git-send-email-ohad@wizery.com> (raw)
In-Reply-To: <1277298125-17991-1-git-send-email-ohad@wizery.com>

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

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

Signed-off-by: Omar Ramirez Luna <omar.ramirez@ti.com>
Signed-off-by: Kanigeri, Hari <h-kanigeri2@ti.com>
Signed-off-by: Ameya Palande <ameya.palande@nokia.com>
Signed-off-by: Guzman Lugo, Fernando <fernando.lugo@ti.com>
Signed-off-by: Hebbar, Shivananda <x0hebbar@ti.com>
Signed-off-by: Ramos Falcon, Ernesto <ernesto@ti.com>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
Signed-off-by: Anna, Suman <s-anna@ti.com>
Signed-off-by: Gupta, Ramesh <grgupta@ti.com>
Signed-off-by: Gomez Castellanos, Ivan <ivan.gomez@ti.com>
Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>
Signed-off-by: Armando Uribe De Leon <x0095078@ti.com>
Signed-off-by: Deepak Chitriki <deepak.chitriki@ti.com>
Signed-off-by: Menon, Nishanth <nm@ti.com>
Signed-off-by: Phil Carmody <ext-phil.2.carmody@nokia.com>
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.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

  parent reply	other threads:[~2010-06-23 13:04 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-06-23 13:01 [PATCH 00/11] staging: add ti dspbridge driver Ohad Ben-Cohen
2010-06-23 13:01 ` Ohad Ben-Cohen
2010-06-23 13:01 ` [PATCH 01/11] staging: ti dspbridge: add driver documentation Ohad Ben-Cohen
2010-06-23 13:01   ` Ohad Ben-Cohen
2010-06-23 13:01 ` [PATCH 02/11] staging: ti dspbridge: add core driver sources Ohad Ben-Cohen
2010-06-23 13:01   ` Ohad Ben-Cohen
2010-06-23 13:01 ` [PATCH 03/11] staging: ti dspbridge: add platform manager code Ohad Ben-Cohen
2010-06-23 13:01   ` Ohad Ben-Cohen
2010-06-23 13:01 ` [PATCH 04/11] staging: ti dspbridge: add resource manager Ohad Ben-Cohen
2010-06-23 13:01   ` Ohad Ben-Cohen
2010-06-23 13:01 ` [PATCH 05/11] staging: ti dspbridge: add MMU support Ohad Ben-Cohen
2010-06-23 13:01   ` Ohad Ben-Cohen
2010-06-23 13:02 ` [PATCH 06/11] staging: ti dspbridge: add generic utilities Ohad Ben-Cohen
2010-06-23 13:02   ` Ohad Ben-Cohen
2010-06-23 15:43   ` Andy Shevchenko
2010-06-24  7:09     ` Ohad Ben-Cohen
2010-07-06 15:08       ` [PATCH] staging: tidspbridge: gen: simplify and clean up Andy Shevchenko
2010-06-23 13:02 ` [PATCH 07/11] staging: ti dspbridge: add services Ohad Ben-Cohen
2010-06-23 13:02   ` Ohad Ben-Cohen
2010-06-23 13:02 ` Ohad Ben-Cohen [this message]
2010-06-23 13:02   ` [PATCH 08/11] staging: ti dspbridge: add DOFF binaries loader Ohad Ben-Cohen
2010-06-23 13:12 ` [PATCH 09/11] staging: ti dspbridge: add header files Ohad Ben-Cohen
2010-06-23 13:12   ` Ohad Ben-Cohen
2010-06-23 13:13 ` [PATCH 10/11] staging: ti dspbridge: add TODO file Ohad Ben-Cohen
2010-06-23 13:13   ` Ohad Ben-Cohen
2010-06-23 13:14 ` [PATCH 11/11] staging: ti dspbridge: enable driver building Ohad Ben-Cohen
2010-06-23 13:14   ` Ohad Ben-Cohen
2010-06-23 22:41   ` Greg KH
2010-06-24 13:40     ` Ohad Ben-Cohen
2010-06-24 13:40       ` Ohad Ben-Cohen
2010-07-04 10:53     ` Felipe Contreras
2010-07-04 10:53       ` Felipe Contreras
2010-07-06 15:52       ` Omar Ramirez Luna
2010-07-06 15:52         ` Omar Ramirez Luna
2010-07-07  9:31         ` Felipe Contreras
2010-07-07 10:18           ` Ohad Ben-Cohen
2010-07-07 20:43           ` Ramirez Luna, Omar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1277298125-17991-9-git-send-email-ohad@wizery.com \
    --to=ohad@wizery.com \
    --cc=Hiroshi.DOYU@nokia.com \
    --cc=ameya.palande@nokia.com \
    --cc=bshah@ti.com \
    --cc=deepak.chitriki@ti.com \
    --cc=ernesto@ti.com \
    --cc=ext-andriy.shevchenko@nokia.com \
    --cc=ext-phil.2.carmody@nokia.com \
    --cc=felipe.balbi@nokia.com \
    --cc=felipe.contreras@gmail.com \
    --cc=fernando.lugo@ti.com \
    --cc=gpitney@ti.com \
    --cc=greg@kroah.com \
    --cc=grgupta@ti.com \
    --cc=h-kanigeri2@ti.com \
    --cc=ivan.gomez@ti.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-omap@vger.kernel.org \
    --cc=nm@ti.com \
    --cc=omar.ramirez@ti.com \
    --cc=s-anna@ti.com \
    --cc=tony@atomide.com \
    --cc=x0095078@ti.com \
    --cc=x0hebbar@ti.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.