summaryrefslogtreecommitdiffstats
path: root/drivers/staging/tidspbridge/dynload/cload.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/tidspbridge/dynload/cload.c')
-rw-r--r--drivers/staging/tidspbridge/dynload/cload.c1952
1 files changed, 0 insertions, 1952 deletions
diff --git a/drivers/staging/tidspbridge/dynload/cload.c b/drivers/staging/tidspbridge/dynload/cload.c
deleted file mode 100644
index 9d54744805b8..000000000000
--- a/drivers/staging/tidspbridge/dynload/cload.c
+++ /dev/null
@@ -1,1952 +0,0 @@
-/*
- * 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 <linux/slab.h>
-
-#include "header.h"
-
-#include "module_list.h"
-#define LINKER_MODULES_HEADER ("_" MODULES_HEADER)
-
-/*
- * 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.next = hndl->dm.prev = hndl; /* circular list */
- hndl->dm.root = 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)
- ((struct ldr_section_info *)shp)->name =
- dlthis->str_head + soffset;
- else {
- dload_error(dlthis, "Bad name offset in section %d",
- curr_sect);
- ((struct ldr_section_info *)shp)->name = NULL;
- }
-#endif
- /* allocate target storage for sections that require it */
- if (ds_needs_allocation(shp)) {
- *asecs = *(struct ldr_section_info *)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;
- struct doff_syment_t *my_sym_buf;
-
- 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 doesn'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;
-
- my_sym_buf = kzalloc(sizeof(*my_sym_buf) * MY_SYM_BUF_SIZ, GFP_KERNEL);
- if (!my_sym_buf)
- return;
-
- do { /* read all symbols */
- char *sname;
- u32 val;
- s32 delta;
- struct doff_syment_t *input_sym;
- unsigned syms_in_buf;
-
- 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);
- goto free_sym_buf;
- }
- 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);
- goto free_sym_buf;
- }
- }
-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");
-
-free_sym_buf:
- kfree(my_sym_buf);
- return;
-} /* 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 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" };
-
-struct img_buffer {
- struct image_packet_t ipacket;
- u8 bufr[BYTE_TO_HOST(IMAGE_PACKET_SIZE)];
-};
-
-/*************************************************************************
- * 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;
- struct img_buffer *ibuf;
- u8 *dest;
-
- /* Indicates whether CINIT processing has occurred */
- bool cinit_processed = false;
-
- ibuf = kzalloc(sizeof(*ibuf), GFP_KERNEL);
- if (!ibuf)
- return;
-
- /* 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 = (struct ldr_section_info *)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);
- goto free_ibuf;
- }
- /* 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);
- goto free_ibuf;
- }
- dest = ibuf->bufr;
- /* End of determination */
-
- if (dlthis->strm->read_buffer(dlthis->strm,
- ibuf->bufr,
- ipsize) !=
- ipsize) {
- DL_ERROR(readstrm, imagepak);
- goto free_ibuf;
- }
- 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))
- goto free_ibuf; /* 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_check_type(sptr,
- DLOAD_CINIT)) {
- cload_cinit(dlthis,
- &ibuf->ipacket);
- cinit_processed = true;
- } else {
- /* 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);
- }
- }
- }
- 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_check_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_check_type(sptr, DLOAD_BSS))
- goto loop_cont;
-
- if (!(dlthis->myoptions & DLOAD_INITBSS))
- goto loop_cont;
-
- if (curr_sect >= dlthis->allocated_secn_count)
- lptr = (struct ldr_section_info *)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);
- }
-free_ibuf:
- kfree(ibuf);
- return;
-} /* 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->next = 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.root = 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->next) {
- dbmod->next_module = TADDR_TO_TDATA(mlist->next->dm.dbthis);
- dbmod->next_module_size = mlist->next->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.next = mlist->next;
- if (hndl->dm.next)
- hndl->dm.next->dm.prev = hndl;
- hndl->dm.prev = (struct my_handle *)mlist;
- mlist->next = 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.root;
- 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.prev == hndl)
- goto exitunltgt;
-
- /* target-side dllview record is in list */
- /* dequeue this record from our GPP-side mirror list */
- hndl->dm.prev->dm.next = hndl->dm.next;
- if (hndl->dm.next)
- hndl->dm.next->dm.prev = hndl->dm.prev;
- /* 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.next) {
- mhdr.first_module = TADDR_TO_TDATA(hndl->dm.next->dm.dbthis);
- mhdr.first_module_size = hndl->dm.next->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.prev->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