aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/tidspbridge/dynload
diff options
context:
space:
mode:
authorOmar Ramirez Luna <omar.ramirez@ti.com>2010-06-23 09:02:02 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-06-23 18:39:08 -0400
commit26f8db7d2e20218272cbf889edfdb8328b4cd9c3 (patch)
tree67a45300822a63cddae83fb8d120a3001fd830ff /drivers/staging/tidspbridge/dynload
parent6a88a4fe0937325f1fc3df835f3e9b1698992899 (diff)
staging: ti dspbridge: add DOFF binaries loader
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> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/tidspbridge/dynload')
-rw-r--r--drivers/staging/tidspbridge/dynload/cload.c1960
-rw-r--r--drivers/staging/tidspbridge/dynload/dload_internal.h351
-rw-r--r--drivers/staging/tidspbridge/dynload/doff.h344
-rw-r--r--drivers/staging/tidspbridge/dynload/getsection.c416
-rw-r--r--drivers/staging/tidspbridge/dynload/header.h55
-rw-r--r--drivers/staging/tidspbridge/dynload/module_list.h159
-rw-r--r--drivers/staging/tidspbridge/dynload/params.h226
-rw-r--r--drivers/staging/tidspbridge/dynload/reloc.c484
-rw-r--r--drivers/staging/tidspbridge/dynload/reloc_table.h102
-rw-r--r--drivers/staging/tidspbridge/dynload/reloc_table_c6000.c257
-rw-r--r--drivers/staging/tidspbridge/dynload/tramp.c1143
-rw-r--r--drivers/staging/tidspbridge/dynload/tramp_table_c6000.c164
12 files changed, 5661 insertions, 0 deletions
diff --git a/drivers/staging/tidspbridge/dynload/cload.c b/drivers/staging/tidspbridge/dynload/cload.c
new file mode 100644
index 00000000000..d4f71b585a5
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/cload.c
@@ -0,0 +1,1960 @@
1/*
2 * cload.c
3 *
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5 *
6 * Copyright (C) 2005-2006 Texas Instruments, Inc.
7 *
8 * This package is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15 */
16
17#include "header.h"
18
19#include "module_list.h"
20#define LINKER_MODULES_HEADER ("_" MODULES_HEADER)
21
22/*
23 * we use the fact that DOFF section records are shaped just like
24 * ldr_section_info to reduce our section storage usage. This macro marks
25 * the places where that assumption is made
26 */
27#define DOFFSEC_IS_LDRSEC(pdoffsec) ((struct ldr_section_info *)(pdoffsec))
28
29/*
30 * forward references
31 */
32static void dload_symbols(struct dload_state *dlthis);
33static void dload_data(struct dload_state *dlthis);
34static void allocate_sections(struct dload_state *dlthis);
35static void string_table_free(struct dload_state *dlthis);
36static void symbol_table_free(struct dload_state *dlthis);
37static void section_table_free(struct dload_state *dlthis);
38static void init_module_handle(struct dload_state *dlthis);
39#if BITS_PER_AU > BITS_PER_BYTE
40static char *unpack_name(struct dload_state *dlthis, u32 soffset);
41#endif
42
43static const char cinitname[] = { ".cinit" };
44static const char loader_dllview_root[] = { "?DLModules?" };
45
46/*
47 * Error strings
48 */
49static const char readstrm[] = { "Error reading %s from input stream" };
50static const char err_alloc[] = { "Syms->dload_allocate( %d ) failed" };
51static const char tgtalloc[] = {
52 "Target memory allocate failed, section %s size " FMT_UI32 };
53static const char initfail[] = { "%s to target address " FMT_UI32 " failed" };
54static const char dlvwrite[] = { "Write to DLLview list failed" };
55static const char iconnect[] = { "Connect call to init interface failed" };
56static const char err_checksum[] = { "Checksum failed on %s" };
57
58/*************************************************************************
59 * Procedure dload_error
60 *
61 * Parameters:
62 * errtxt description of the error, printf style
63 * ... additional information
64 *
65 * Effect:
66 * Reports or records the error as appropriate.
67 *********************************************************************** */
68void dload_error(struct dload_state *dlthis, const char *errtxt, ...)
69{
70 va_list args;
71
72 va_start(args, errtxt);
73 dlthis->mysym->error_report(dlthis->mysym, errtxt, args);
74 va_end(args);
75 dlthis->dload_errcount += 1;
76
77} /* dload_error */
78
79#define DL_ERROR(zza, zzb) dload_error(dlthis, zza, zzb)
80
81/*************************************************************************
82 * Procedure dload_syms_error
83 *
84 * Parameters:
85 * errtxt description of the error, printf style
86 * ... additional information
87 *
88 * Effect:
89 * Reports or records the error as appropriate.
90 *********************************************************************** */
91void dload_syms_error(struct dynamic_loader_sym *syms, const char *errtxt, ...)
92{
93 va_list args;
94
95 va_start(args, errtxt);
96 syms->error_report(syms, errtxt, args);
97 va_end(args);
98}
99
100/*************************************************************************
101 * Procedure dynamic_load_module
102 *
103 * Parameters:
104 * module The input stream that supplies the module image
105 * syms Host-side symbol table and malloc/free functions
106 * alloc Target-side memory allocation
107 * init Target-side memory initialization
108 * options Option flags DLOAD_*
109 * mhandle A module handle for use with Dynamic_Unload
110 *
111 * Effect:
112 * The module image is read using *module. Target storage for the new
113 * image is
114 * obtained from *alloc. Symbols defined and referenced by the module are
115 * managed using *syms. The image is then relocated and references
116 * resolved as necessary, and the resulting executable bits are placed
117 * into target memory using *init.
118 *
119 * Returns:
120 * On a successful load, a module handle is placed in *mhandle,
121 * and zero is returned. On error, the number of errors detected is
122 * returned. Individual errors are reported during the load process
123 * using syms->error_report().
124 ********************************************************************** */
125int dynamic_load_module(struct dynamic_loader_stream *module,
126 struct dynamic_loader_sym *syms,
127 struct dynamic_loader_allocate *alloc,
128 struct dynamic_loader_initialize *init,
129 unsigned options, void **mhandle)
130{
131 register unsigned *dp, sz;
132 struct dload_state dl_state; /* internal state for this call */
133
134 /* blast our internal state */
135 dp = (unsigned *)&dl_state;
136 for (sz = sizeof(dl_state) / sizeof(unsigned); sz > 0; sz -= 1)
137 *dp++ = 0;
138
139 /* Enable _only_ BSS initialization if enabled by user */
140 if ((options & DLOAD_INITBSS) == DLOAD_INITBSS)
141 dl_state.myoptions = DLOAD_INITBSS;
142
143 /* Check that mandatory arguments are present */
144 if (!module || !syms) {
145 dload_error(&dl_state, "Required parameter is NULL");
146 } else {
147 dl_state.strm = module;
148 dl_state.mysym = syms;
149 dload_headers(&dl_state);
150 if (!dl_state.dload_errcount)
151 dload_strings(&dl_state, false);
152 if (!dl_state.dload_errcount)
153 dload_sections(&dl_state);
154
155 if (init && !dl_state.dload_errcount) {
156 if (init->connect(init)) {
157 dl_state.myio = init;
158 dl_state.myalloc = alloc;
159 /* do now, before reducing symbols */
160 allocate_sections(&dl_state);
161 } else
162 dload_error(&dl_state, iconnect);
163 }
164
165 if (!dl_state.dload_errcount) {
166 /* fix up entry point address */
167 unsigned sref = dl_state.dfile_hdr.df_entry_secn - 1;
168 if (sref < dl_state.allocated_secn_count)
169 dl_state.dfile_hdr.df_entrypt +=
170 dl_state.ldr_sections[sref].run_addr;
171
172 dload_symbols(&dl_state);
173 }
174
175 if (init && !dl_state.dload_errcount)
176 dload_data(&dl_state);
177
178 init_module_handle(&dl_state);
179
180 /* dl_state.myio is init or 0 at this point. */
181 if (dl_state.myio) {
182 if ((!dl_state.dload_errcount) &&
183 (dl_state.dfile_hdr.df_entry_secn != DN_UNDEF) &&
184 (!init->execute(init,
185 dl_state.dfile_hdr.df_entrypt)))
186 dload_error(&dl_state, "Init->Execute Failed");
187 init->release(init);
188 }
189
190 symbol_table_free(&dl_state);
191 section_table_free(&dl_state);
192 string_table_free(&dl_state);
193 dload_tramp_cleanup(&dl_state);
194
195 if (dl_state.dload_errcount) {
196 dynamic_unload_module(dl_state.myhandle, syms, alloc,
197 init);
198 dl_state.myhandle = NULL;
199 }
200 }
201
202 if (mhandle)
203 *mhandle = dl_state.myhandle; /* give back the handle */
204
205 return dl_state.dload_errcount;
206} /* DLOAD_File */
207
208/*************************************************************************
209 * Procedure dynamic_open_module
210 *
211 * Parameters:
212 * module The input stream that supplies the module image
213 * syms Host-side symbol table and malloc/free functions
214 * alloc Target-side memory allocation
215 * init Target-side memory initialization
216 * options Option flags DLOAD_*
217 * mhandle A module handle for use with Dynamic_Unload
218 *
219 * Effect:
220 * The module image is read using *module. Target storage for the new
221 * image is
222 * obtained from *alloc. Symbols defined and referenced by the module are
223 * managed using *syms. The image is then relocated and references
224 * resolved as necessary, and the resulting executable bits are placed
225 * into target memory using *init.
226 *
227 * Returns:
228 * On a successful load, a module handle is placed in *mhandle,
229 * and zero is returned. On error, the number of errors detected is
230 * returned. Individual errors are reported during the load process
231 * using syms->error_report().
232 ********************************************************************** */
233int
234dynamic_open_module(struct dynamic_loader_stream *module,
235 struct dynamic_loader_sym *syms,
236 struct dynamic_loader_allocate *alloc,
237 struct dynamic_loader_initialize *init,
238 unsigned options, void **mhandle)
239{
240 register unsigned *dp, sz;
241 struct dload_state dl_state; /* internal state for this call */
242
243 /* blast our internal state */
244 dp = (unsigned *)&dl_state;
245 for (sz = sizeof(dl_state) / sizeof(unsigned); sz > 0; sz -= 1)
246 *dp++ = 0;
247
248 /* Enable _only_ BSS initialization if enabled by user */
249 if ((options & DLOAD_INITBSS) == DLOAD_INITBSS)
250 dl_state.myoptions = DLOAD_INITBSS;
251
252 /* Check that mandatory arguments are present */
253 if (!module || !syms) {
254 dload_error(&dl_state, "Required parameter is NULL");
255 } else {
256 dl_state.strm = module;
257 dl_state.mysym = syms;
258 dload_headers(&dl_state);
259 if (!dl_state.dload_errcount)
260 dload_strings(&dl_state, false);
261 if (!dl_state.dload_errcount)
262 dload_sections(&dl_state);
263
264 if (init && !dl_state.dload_errcount) {
265 if (init->connect(init)) {
266 dl_state.myio = init;
267 dl_state.myalloc = alloc;
268 /* do now, before reducing symbols */
269 allocate_sections(&dl_state);
270 } else
271 dload_error(&dl_state, iconnect);
272 }
273
274 if (!dl_state.dload_errcount) {
275 /* fix up entry point address */
276 unsigned sref = dl_state.dfile_hdr.df_entry_secn - 1;
277 if (sref < dl_state.allocated_secn_count)
278 dl_state.dfile_hdr.df_entrypt +=
279 dl_state.ldr_sections[sref].run_addr;
280
281 dload_symbols(&dl_state);
282 }
283
284 init_module_handle(&dl_state);
285
286 /* dl_state.myio is either 0 or init at this point. */
287 if (dl_state.myio) {
288 if ((!dl_state.dload_errcount) &&
289 (dl_state.dfile_hdr.df_entry_secn != DN_UNDEF) &&
290 (!init->execute(init,
291 dl_state.dfile_hdr.df_entrypt)))
292 dload_error(&dl_state, "Init->Execute Failed");
293 init->release(init);
294 }
295
296 symbol_table_free(&dl_state);
297 section_table_free(&dl_state);
298 string_table_free(&dl_state);
299
300 if (dl_state.dload_errcount) {
301 dynamic_unload_module(dl_state.myhandle, syms, alloc,
302 init);
303 dl_state.myhandle = NULL;
304 }
305 }
306
307 if (mhandle)
308 *mhandle = dl_state.myhandle; /* give back the handle */
309
310 return dl_state.dload_errcount;
311} /* DLOAD_File */
312
313/*************************************************************************
314 * Procedure dload_headers
315 *
316 * Parameters:
317 * none
318 *
319 * Effect:
320 * Loads the DOFF header and verify record. Deals with any byte-order
321 * issues and checks them for validity.
322 *********************************************************************** */
323#define COMBINED_HEADER_SIZE (sizeof(struct doff_filehdr_t)+ \
324 sizeof(struct doff_verify_rec_t))
325
326void dload_headers(struct dload_state *dlthis)
327{
328 u32 map;
329
330 /* Read the header and the verify record as one. If we don't get it
331 all, we're done */
332 if (dlthis->strm->read_buffer(dlthis->strm, &dlthis->dfile_hdr,
333 COMBINED_HEADER_SIZE) !=
334 COMBINED_HEADER_SIZE) {
335 DL_ERROR(readstrm, "File Headers");
336 return;
337 }
338 /*
339 * Verify that we have the byte order of the file correct.
340 * If not, must fix it before we can continue
341 */
342 map = REORDER_MAP(dlthis->dfile_hdr.df_byte_reshuffle);
343 if (map != REORDER_MAP(BYTE_RESHUFFLE_VALUE)) {
344 /* input is either byte-shuffled or bad */
345 if ((map & 0xFCFCFCFC) == 0) { /* no obviously bogus bits */
346 dload_reorder(&dlthis->dfile_hdr, COMBINED_HEADER_SIZE,
347 map);
348 }
349 if (dlthis->dfile_hdr.df_byte_reshuffle !=
350 BYTE_RESHUFFLE_VALUE) {
351 /* didn't fix the problem, the byte swap map is bad */
352 dload_error(dlthis,
353 "Bad byte swap map " FMT_UI32 " in header",
354 dlthis->dfile_hdr.df_byte_reshuffle);
355 return;
356 }
357 dlthis->reorder_map = map; /* keep map for future use */
358 }
359
360 /*
361 * Verify checksum of header and verify record
362 */
363 if (~dload_checksum(&dlthis->dfile_hdr,
364 sizeof(struct doff_filehdr_t)) ||
365 ~dload_checksum(&dlthis->verify,
366 sizeof(struct doff_verify_rec_t))) {
367 DL_ERROR(err_checksum, "header or verify record");
368 return;
369 }
370#if HOST_ENDIANNESS
371 dlthis->dfile_hdr.df_byte_reshuffle = map; /* put back for later */
372#endif
373
374 /* Check for valid target ID */
375 if ((dlthis->dfile_hdr.df_target_id != TARGET_ID) &&
376 -(dlthis->dfile_hdr.df_target_id != TMS470_ID)) {
377 dload_error(dlthis, "Bad target ID 0x%x and TARGET_ID 0x%x",
378 dlthis->dfile_hdr.df_target_id, TARGET_ID);
379 return;
380 }
381 /* Check for valid file format */
382 if ((dlthis->dfile_hdr.df_doff_version != DOFF0)) {
383 dload_error(dlthis, "Bad DOFF version 0x%x",
384 dlthis->dfile_hdr.df_doff_version);
385 return;
386 }
387
388 /*
389 * Apply reasonableness checks to count fields
390 */
391 if (dlthis->dfile_hdr.df_strtab_size > MAX_REASONABLE_STRINGTAB) {
392 dload_error(dlthis, "Excessive string table size " FMT_UI32,
393 dlthis->dfile_hdr.df_strtab_size);
394 return;
395 }
396 if (dlthis->dfile_hdr.df_no_scns > MAX_REASONABLE_SECTIONS) {
397 dload_error(dlthis, "Excessive section count 0x%x",
398 dlthis->dfile_hdr.df_no_scns);
399 return;
400 }
401#ifndef TARGET_ENDIANNESS
402 /*
403 * Check that endianness does not disagree with explicit specification
404 */
405 if ((dlthis->dfile_hdr.df_flags >> ALIGN_COFF_ENDIANNESS) &
406 dlthis->myoptions & ENDIANNESS_MASK) {
407 dload_error(dlthis,
408 "Input endianness disagrees with specified option");
409 return;
410 }
411 dlthis->big_e_target = dlthis->dfile_hdr.df_flags & DF_BIG;
412#endif
413
414} /* dload_headers */
415
416/* COFF Section Processing
417 *
418 * COFF sections are read in and retained intact. Each record is embedded
419 * in a new structure that records the updated load and
420 * run addresses of the section */
421
422static const char secn_errid[] = { "section" };
423
424/*************************************************************************
425 * Procedure dload_sections
426 *
427 * Parameters:
428 * none
429 *
430 * Effect:
431 * Loads the section records into an internal table.
432 *********************************************************************** */
433void dload_sections(struct dload_state *dlthis)
434{
435 s16 siz;
436 struct doff_scnhdr_t *shp;
437 unsigned nsecs = dlthis->dfile_hdr.df_no_scns;
438
439 /* allocate space for the DOFF section records */
440 siz = nsecs * sizeof(struct doff_scnhdr_t);
441 shp =
442 (struct doff_scnhdr_t *)dlthis->mysym->dload_allocate(dlthis->mysym,
443 siz);
444 if (!shp) { /* not enough storage */
445 DL_ERROR(err_alloc, siz);
446 return;
447 }
448 dlthis->sect_hdrs = shp;
449
450 /* read in the section records */
451 if (dlthis->strm->read_buffer(dlthis->strm, shp, siz) != siz) {
452 DL_ERROR(readstrm, secn_errid);
453 return;
454 }
455
456 /* if we need to fix up byte order, do it now */
457 if (dlthis->reorder_map)
458 dload_reorder(shp, siz, dlthis->reorder_map);
459
460 /* check for validity */
461 if (~dload_checksum(dlthis->sect_hdrs, siz) !=
462 dlthis->verify.dv_scn_rec_checksum) {
463 DL_ERROR(err_checksum, secn_errid);
464 return;
465 }
466
467} /* dload_sections */
468
469/*****************************************************************************
470 * Procedure allocate_sections
471 *
472 * Parameters:
473 * alloc target memory allocator class
474 *
475 * Effect:
476 * Assigns new (target) addresses for sections
477 **************************************************************************** */
478static void allocate_sections(struct dload_state *dlthis)
479{
480 u16 curr_sect, nsecs, siz;
481 struct doff_scnhdr_t *shp;
482 struct ldr_section_info *asecs;
483 struct my_handle *hndl;
484 nsecs = dlthis->dfile_hdr.df_no_scns;
485 if (!nsecs)
486 return;
487 if ((dlthis->myalloc == NULL) &&
488 (dlthis->dfile_hdr.df_target_scns > 0)) {
489 DL_ERROR("Arg 3 (alloc) required but NULL", 0);
490 return;
491 }
492 /*
493 * allocate space for the module handle, which we will keep for unload
494 * purposes include an additional section store for an auto-generated
495 * trampoline section in case we need it.
496 */
497 siz = (dlthis->dfile_hdr.df_target_scns + 1) *
498 sizeof(struct ldr_section_info) + MY_HANDLE_SIZE;
499
500 hndl =
501 (struct my_handle *)dlthis->mysym->dload_allocate(dlthis->mysym,
502 siz);
503 if (!hndl) { /* not enough storage */
504 DL_ERROR(err_alloc, siz);
505 return;
506 }
507 /* initialize the handle header */
508 hndl->dm.hnext = hndl->dm.hprev = hndl; /* circular list */
509 hndl->dm.hroot = NULL;
510 hndl->dm.dbthis = 0;
511 dlthis->myhandle = hndl; /* save away for return */
512 /* pointer to the section list of allocated sections */
513 dlthis->ldr_sections = asecs = hndl->secns;
514 /* * Insert names into all sections, make copies of
515 the sections we allocate */
516 shp = dlthis->sect_hdrs;
517 for (curr_sect = 0; curr_sect < nsecs; curr_sect++) {
518 u32 soffset = shp->ds_offset;
519#if BITS_PER_AU <= BITS_PER_BYTE
520 /* attempt to insert the name of this section */
521 if (soffset < dlthis->dfile_hdr.df_strtab_size)
522 DOFFSEC_IS_LDRSEC(shp)->name = dlthis->str_head +
523 soffset;
524 else {
525 dload_error(dlthis, "Bad name offset in section %d",
526 curr_sect);
527 DOFFSEC_IS_LDRSEC(shp)->name = NULL;
528 }
529#endif
530 /* allocate target storage for sections that require it */
531 if (DS_NEEDS_ALLOCATION(shp)) {
532 *asecs = *DOFFSEC_IS_LDRSEC(shp);
533 asecs->context = 0; /* zero the context field */
534#if BITS_PER_AU > BITS_PER_BYTE
535 asecs->name = unpack_name(dlthis, soffset);
536 dlthis->debug_string_size = soffset + dlthis->temp_len;
537#else
538 dlthis->debug_string_size = soffset;
539#endif
540 if (dlthis->myalloc != NULL) {
541 if (!dlthis->myalloc->
542 dload_allocate(dlthis->myalloc, asecs,
543 DS_ALIGNMENT(asecs->type))) {
544 dload_error(dlthis, tgtalloc,
545 asecs->name, asecs->size);
546 return;
547 }
548 }
549 /* keep address deltas in original section table */
550 shp->ds_vaddr = asecs->load_addr - shp->ds_vaddr;
551 shp->ds_paddr = asecs->run_addr - shp->ds_paddr;
552 dlthis->allocated_secn_count += 1;
553 } /* allocate target storage */
554 shp += 1;
555 asecs += 1;
556 }
557#if BITS_PER_AU <= BITS_PER_BYTE
558 dlthis->debug_string_size +=
559 strlen(dlthis->str_head + dlthis->debug_string_size) + 1;
560#endif
561} /* allocate sections */
562
563/*************************************************************************
564 * Procedure section_table_free
565 *
566 * Parameters:
567 * none
568 *
569 * Effect:
570 * Frees any state used by the symbol table.
571 *
572 * WARNING:
573 * This routine is not allowed to declare errors!
574 *********************************************************************** */
575static void section_table_free(struct dload_state *dlthis)
576{
577 struct doff_scnhdr_t *shp;
578
579 shp = dlthis->sect_hdrs;
580 if (shp)
581 dlthis->mysym->dload_deallocate(dlthis->mysym, shp);
582
583} /* section_table_free */
584
585/*************************************************************************
586 * Procedure dload_strings
587 *
588 * Parameters:
589 * sec_names_only If true only read in the "section names"
590 * portion of the string table
591 *
592 * Effect:
593 * Loads the DOFF string table into memory. DOFF keeps all strings in a
594 * big unsorted array. We just read that array into memory in bulk.
595 *********************************************************************** */
596static const char stringtbl[] = { "string table" };
597
598void dload_strings(struct dload_state *dlthis, bool sec_names_only)
599{
600 u32 ssiz;
601 char *strbuf;
602
603 if (sec_names_only) {
604 ssiz = BYTE_TO_HOST(DOFF_ALIGN
605 (dlthis->dfile_hdr.df_scn_name_size));
606 } else {
607 ssiz = BYTE_TO_HOST(DOFF_ALIGN
608 (dlthis->dfile_hdr.df_strtab_size));
609 }
610 if (ssiz == 0)
611 return;
612
613 /* get some memory for the string table */
614#if BITS_PER_AU > BITS_PER_BYTE
615 strbuf = (char *)dlthis->mysym->dload_allocate(dlthis->mysym, ssiz +
616 dlthis->dfile_hdr.
617 df_max_str_len);
618#else
619 strbuf = (char *)dlthis->mysym->dload_allocate(dlthis->mysym, ssiz);
620#endif
621 if (strbuf == NULL) {
622 DL_ERROR(err_alloc, ssiz);
623 return;
624 }
625 dlthis->str_head = strbuf;
626#if BITS_PER_AU > BITS_PER_BYTE
627 dlthis->str_temp = strbuf + ssiz;
628#endif
629 /* read in the strings and verify them */
630 if ((unsigned)(dlthis->strm->read_buffer(dlthis->strm, strbuf,
631 ssiz)) != ssiz) {
632 DL_ERROR(readstrm, stringtbl);
633 }
634 /* if we need to fix up byte order, do it now */
635#ifndef _BIG_ENDIAN
636 if (dlthis->reorder_map)
637 dload_reorder(strbuf, ssiz, dlthis->reorder_map);
638
639 if ((!sec_names_only) && (~dload_checksum(strbuf, ssiz) !=
640 dlthis->verify.dv_str_tab_checksum)) {
641 DL_ERROR(err_checksum, stringtbl);
642 }
643#else
644 if (dlthis->dfile_hdr.df_byte_reshuffle !=
645 HOST_BYTE_ORDER(REORDER_MAP(BYTE_RESHUFFLE_VALUE))) {
646 /* put strings in big-endian order, not in PC order */
647 dload_reorder(strbuf, ssiz,
648 HOST_BYTE_ORDER(dlthis->
649 dfile_hdr.df_byte_reshuffle));
650 }
651 if ((!sec_names_only) && (~dload_reverse_checksum(strbuf, ssiz) !=
652 dlthis->verify.dv_str_tab_checksum)) {
653 DL_ERROR(err_checksum, stringtbl);
654 }
655#endif
656} /* dload_strings */
657
658/*************************************************************************
659 * Procedure string_table_free
660 *
661 * Parameters:
662 * none
663 *
664 * Effect:
665 * Frees any state used by the string table.
666 *
667 * WARNING:
668 * This routine is not allowed to declare errors!
669 ************************************************************************ */
670static void string_table_free(struct dload_state *dlthis)
671{
672 if (dlthis->str_head)
673 dlthis->mysym->dload_deallocate(dlthis->mysym,
674 dlthis->str_head);
675
676} /* string_table_free */
677
678/*
679 * Symbol Table Maintenance Functions
680 *
681 * COFF symbols are read by dload_symbols(), which is called after
682 * sections have been allocated. Symbols which might be used in
683 * relocation (ie, not debug info) are retained in an internal temporary
684 * compressed table (type local_symbol). A particular symbol is recovered
685 * by index by calling dload_find_symbol(). dload_find_symbol
686 * reconstructs a more explicit representation (type SLOTVEC) which is
687 * used by reloc.c
688 */
689/* real size of debug header */
690#define DBG_HDR_SIZE (sizeof(struct dll_module) - sizeof(struct dll_sect))
691
692static const char sym_errid[] = { "symbol" };
693
694/**************************************************************************
695 * Procedure dload_symbols
696 *
697 * Parameters:
698 * none
699 *
700 * Effect:
701 * Reads in symbols and retains ones that might be needed for relocation
702 * purposes.
703 *********************************************************************** */
704/* size of symbol buffer no bigger than target data buffer, to limit stack
705 * usage */
706#define MY_SYM_BUF_SIZ (BYTE_TO_HOST(IMAGE_PACKET_SIZE)/\
707 sizeof(struct doff_syment_t))
708
709static void dload_symbols(struct dload_state *dlthis)
710{
711 u32 sym_count, siz, dsiz, symbols_left;
712 u32 checks;
713 struct local_symbol *sp;
714 struct dynload_symbol *symp;
715 struct dynload_symbol *newsym;
716
717 sym_count = dlthis->dfile_hdr.df_no_syms;
718 if (sym_count == 0)
719 return;
720
721 /*
722 * We keep a local symbol table for all of the symbols in the input.
723 * This table contains only section & value info, as we do not have
724 * to do any name processing for locals. We reuse this storage
725 * as a temporary for .dllview record construction.
726 * Allocate storage for the whole table. Add 1 to the section count
727 * in case a trampoline section is auto-generated as well as the
728 * size of the trampoline section name so DLLView doens't get lost.
729 */
730
731 siz = sym_count * sizeof(struct local_symbol);
732 dsiz = DBG_HDR_SIZE +
733 (sizeof(struct dll_sect) * dlthis->allocated_secn_count) +
734 BYTE_TO_HOST_ROUND(dlthis->debug_string_size + 1);
735 if (dsiz > siz)
736 siz = dsiz; /* larger of symbols and .dllview temp */
737 sp = (struct local_symbol *)dlthis->mysym->dload_allocate(dlthis->mysym,
738 siz);
739 if (!sp) {
740 DL_ERROR(err_alloc, siz);
741 return;
742 }
743 dlthis->local_symtab = sp;
744 /* Read the symbols in the input, store them in the table, and post any
745 * globals to the global symbol table. In the process, externals
746 become defined from the global symbol table */
747 checks = dlthis->verify.dv_sym_tab_checksum;
748 symbols_left = sym_count;
749 do { /* read all symbols */
750 char *sname;
751 u32 val;
752 s32 delta;
753 struct doff_syment_t *input_sym;
754 unsigned syms_in_buf;
755 struct doff_syment_t my_sym_buf[MY_SYM_BUF_SIZ];
756 input_sym = my_sym_buf;
757 syms_in_buf = symbols_left > MY_SYM_BUF_SIZ ?
758 MY_SYM_BUF_SIZ : symbols_left;
759 siz = syms_in_buf * sizeof(struct doff_syment_t);
760 if (dlthis->strm->read_buffer(dlthis->strm, input_sym, siz) !=
761 siz) {
762 DL_ERROR(readstrm, sym_errid);
763 return;
764 }
765 if (dlthis->reorder_map)
766 dload_reorder(input_sym, siz, dlthis->reorder_map);
767
768 checks += dload_checksum(input_sym, siz);
769 do { /* process symbols in buffer */
770 symbols_left -= 1;
771 /* attempt to derive the name of this symbol */
772 sname = NULL;
773 if (input_sym->dn_offset > 0) {
774#if BITS_PER_AU <= BITS_PER_BYTE
775 if ((u32) input_sym->dn_offset <
776 dlthis->dfile_hdr.df_strtab_size)
777 sname = dlthis->str_head +
778 BYTE_TO_HOST(input_sym->dn_offset);
779 else
780 dload_error(dlthis,
781 "Bad name offset in symbol "
782 " %d", symbols_left);
783#else
784 sname = unpack_name(dlthis,
785 input_sym->dn_offset);
786#endif
787 }
788 val = input_sym->dn_value;
789 delta = 0;
790 sp->sclass = input_sym->dn_sclass;
791 sp->secnn = input_sym->dn_scnum;
792 /* if this is an undefined symbol,
793 * define it (or fail) now */
794 if (sp->secnn == DN_UNDEF) {
795 /* pointless for static undefined */
796 if (input_sym->dn_sclass != DN_EXT)
797 goto loop_cont;
798
799 /* try to define symbol from previously
800 * loaded images */
801 symp = dlthis->mysym->find_matching_symbol
802 (dlthis->mysym, sname);
803 if (!symp) {
804 DL_ERROR
805 ("Undefined external symbol %s",
806 sname);
807 goto loop_cont;
808 }
809 val = delta = symp->value;
810#ifdef ENABLE_TRAMP_DEBUG
811 dload_syms_error(dlthis->mysym,
812 "===> ext sym [%s] at %x",
813 sname, val);
814#endif
815
816 goto loop_cont;
817 }
818 /* symbol defined by this module */
819 if (sp->secnn > 0) {
820 /* symbol references a section */
821 if ((unsigned)sp->secnn <=
822 dlthis->allocated_secn_count) {
823 /* section was allocated */
824 struct doff_scnhdr_t *srefp =
825 &dlthis->sect_hdrs[sp->secnn - 1];
826
827 if (input_sym->dn_sclass ==
828 DN_STATLAB ||
829 input_sym->dn_sclass == DN_EXTLAB) {
830 /* load */
831 delta = srefp->ds_vaddr;
832 } else {
833 /* run */
834 delta = srefp->ds_paddr;
835 }
836 val += delta;
837 }
838 goto loop_itr;
839 }
840 /* This symbol is an absolute symbol */
841 if (sp->secnn == DN_ABS && ((sp->sclass == DN_EXT) ||
842 (sp->sclass ==
843 DN_EXTLAB))) {
844 symp =
845 dlthis->mysym->find_matching_symbol(dlthis->
846 mysym,
847 sname);
848 if (!symp)
849 goto loop_itr;
850 /* This absolute symbol is already defined. */
851 if (symp->value == input_sym->dn_value) {
852 /* If symbol values are equal, continue
853 * but don't add to the global symbol
854 * table */
855 sp->value = val;
856 sp->delta = delta;
857 sp += 1;
858 input_sym += 1;
859 continue;
860 } else {
861 /* If symbol values are not equal,
862 * return with redefinition error */
863 DL_ERROR("Absolute symbol %s is "
864 "defined multiple times with "
865 "different values", sname);
866 return;
867 }
868 }
869loop_itr:
870 /* if this is a global symbol, post it to the
871 * global table */
872 if (input_sym->dn_sclass == DN_EXT ||
873 input_sym->dn_sclass == DN_EXTLAB) {
874 /* Keep this global symbol for subsequent
875 * modules. Don't complain on error, to allow
876 * symbol API to suppress global symbols */
877 if (!sname)
878 goto loop_cont;
879
880 newsym = dlthis->mysym->add_to_symbol_table
881 (dlthis->mysym, sname,
882 (unsigned)dlthis->myhandle);
883 if (newsym)
884 newsym->value = val;
885
886 } /* global */
887loop_cont:
888 sp->value = val;
889 sp->delta = delta;
890 sp += 1;
891 input_sym += 1;
892 } while ((syms_in_buf -= 1) > 0); /* process sym in buf */
893 } while (symbols_left > 0); /* read all symbols */
894 if (~checks)
895 dload_error(dlthis, "Checksum of symbols failed");
896
897} /* dload_symbols */
898
899/*****************************************************************************
900 * Procedure symbol_table_free
901 *
902 * Parameters:
903 * none
904 *
905 * Effect:
906 * Frees any state used by the symbol table.
907 *
908 * WARNING:
909 * This routine is not allowed to declare errors!
910 **************************************************************************** */
911static void symbol_table_free(struct dload_state *dlthis)
912{
913 if (dlthis->local_symtab) {
914 if (dlthis->dload_errcount) { /* blow off our symbols */
915 dlthis->mysym->purge_symbol_table(dlthis->mysym,
916 (unsigned)
917 dlthis->myhandle);
918 }
919 dlthis->mysym->dload_deallocate(dlthis->mysym,
920 dlthis->local_symtab);
921 }
922} /* symbol_table_free */
923
924/* .cinit Processing
925 *
926 * The dynamic loader does .cinit interpretation. cload_cinit()
927 * acts as a special write-to-target function, in that it takes relocated
928 * data from the normal data flow, and interprets it as .cinit actions.
929 * Because the normal data flow does not necessarily process the whole
930 * .cinit section in one buffer, cload_cinit() must be prepared to
931 * interpret the data piecemeal. A state machine is used for this
932 * purpose.
933 */
934
935/* The following are only for use by reloc.c and things it calls */
936static const struct ldr_section_info cinit_info_init = { cinitname, 0, 0,
937 (ldr_addr)-1, 0, DLOAD_BSS, 0
938};
939
940/*************************************************************************
941 * Procedure cload_cinit
942 *
943 * Parameters:
944 * ipacket Pointer to data packet to be loaded
945 *
946 * Effect:
947 * Interprets the data in the buffer as .cinit data, and performs the
948 * appropriate initializations.
949 *********************************************************************** */
950static void cload_cinit(struct dload_state *dlthis,
951 struct image_packet_t *ipacket)
952{
953#if TDATA_TO_HOST(CINIT_COUNT)*BITS_PER_AU > 16
954 s32 init_count, left;
955#else
956 s16 init_count, left;
957#endif
958 unsigned char *pktp = ipacket->img_data;
959 unsigned char *pktend = pktp + BYTE_TO_HOST_ROUND(ipacket->packet_size);
960 int temp;
961 ldr_addr atmp;
962 struct ldr_section_info cinit_info;
963
964 /* PROCESS ALL THE INITIALIZATION RECORDS IN THE BUFFER. */
965 while (true) {
966 left = pktend - pktp;
967 switch (dlthis->cinit_state) {
968 case CI_COUNT: /* count field */
969 if (left < TDATA_TO_HOST(CINIT_COUNT))
970 goto loopexit;
971 temp = dload_unpack(dlthis, (tgt_au_t *) pktp,
972 CINIT_COUNT * TDATA_AU_BITS, 0,
973 ROP_SGN);
974 pktp += TDATA_TO_HOST(CINIT_COUNT);
975 /* negative signifies BSS table, zero means done */
976 if (temp <= 0) {
977 dlthis->cinit_state = CI_DONE;
978 break;
979 }
980 dlthis->cinit_count = temp;
981 dlthis->cinit_state = CI_ADDRESS;
982 break;
983#if CINIT_ALIGN < CINIT_ADDRESS
984 case CI_PARTADDRESS:
985 pktp -= TDATA_TO_HOST(CINIT_ALIGN);
986 /* back up pointer into space courtesy of caller */
987 *(uint16_t *) pktp = dlthis->cinit_addr;
988 /* stuff in saved bits !! FALL THRU !! */
989#endif
990 case CI_ADDRESS: /* Address field for a copy packet */
991 if (left < TDATA_TO_HOST(CINIT_ADDRESS)) {
992#if CINIT_ALIGN < CINIT_ADDRESS
993 if (left == TDATA_TO_HOST(CINIT_ALIGN)) {
994 /* address broken into halves */
995 dlthis->cinit_addr = *(uint16_t *) pktp;
996 /* remember 1st half */
997 dlthis->cinit_state = CI_PARTADDRESS;
998 left = 0;
999 }
1000#endif
1001 goto loopexit;
1002 }
1003 atmp = dload_unpack(dlthis, (tgt_au_t *) pktp,
1004 CINIT_ADDRESS * TDATA_AU_BITS, 0,
1005 ROP_UNS);
1006 pktp += TDATA_TO_HOST(CINIT_ADDRESS);
1007#if CINIT_PAGE_BITS > 0
1008 dlthis->cinit_page = atmp &
1009 ((1 << CINIT_PAGE_BITS) - 1);
1010 atmp >>= CINIT_PAGE_BITS;
1011#else
1012 dlthis->cinit_page = CINIT_DEFAULT_PAGE;
1013#endif
1014 dlthis->cinit_addr = atmp;
1015 dlthis->cinit_state = CI_COPY;
1016 break;
1017 case CI_COPY: /* copy bits to the target */
1018 init_count = HOST_TO_TDATA(left);
1019 if (init_count > dlthis->cinit_count)
1020 init_count = dlthis->cinit_count;
1021 if (init_count == 0)
1022 goto loopexit; /* get more bits */
1023 cinit_info = cinit_info_init;
1024 cinit_info.page = dlthis->cinit_page;
1025 if (!dlthis->myio->writemem(dlthis->myio, pktp,
1026 TDATA_TO_TADDR
1027 (dlthis->cinit_addr),
1028 &cinit_info,
1029 TDATA_TO_HOST(init_count))) {
1030 dload_error(dlthis, initfail, "write",
1031 dlthis->cinit_addr);
1032 }
1033 dlthis->cinit_count -= init_count;
1034 if (dlthis->cinit_count <= 0) {
1035 dlthis->cinit_state = CI_COUNT;
1036 init_count = (init_count + CINIT_ALIGN - 1) &
1037 -CINIT_ALIGN;
1038 /* align to next init */
1039 }
1040 pktp += TDATA_TO_HOST(init_count);
1041 dlthis->cinit_addr += init_count;
1042 break;
1043 case CI_DONE: /* no more .cinit to do */
1044 return;
1045 } /* switch (cinit_state) */
1046 } /* while */
1047
1048loopexit:
1049 if (left > 0) {
1050 dload_error(dlthis, "%d bytes left over in cinit packet", left);
1051 dlthis->cinit_state = CI_DONE; /* left over bytes are bad */
1052 }
1053} /* cload_cinit */
1054
1055/* Functions to interface to reloc.c
1056 *
1057 * reloc.c is the relocation module borrowed from the linker, with
1058 * minimal (we hope) changes for our purposes. cload_sect_data() invokes
1059 * this module on a section to relocate and load the image data for that
1060 * section. The actual read and write actions are supplied by the global
1061 * routines below.
1062 */
1063
1064/************************************************************************
1065 * Procedure relocate_packet
1066 *
1067 * Parameters:
1068 * ipacket Pointer to an image packet to relocate
1069 *
1070 * Effect:
1071 * Performs the required relocations on the packet. Returns a checksum
1072 * of the relocation operations.
1073 *********************************************************************** */
1074#define MY_RELOC_BUF_SIZ 8
1075/* careful! exists at the same time as the image buffer */
1076static int relocate_packet(struct dload_state *dlthis,
1077 struct image_packet_t *ipacket,
1078 u32 *checks, bool *tramps_generated)
1079{
1080 u32 rnum;
1081 *tramps_generated = false;
1082
1083 rnum = ipacket->num_relocs;
1084 do { /* all relocs */
1085 unsigned rinbuf;
1086 int siz;
1087 struct reloc_record_t *rp, rrec[MY_RELOC_BUF_SIZ];
1088 rp = rrec;
1089 rinbuf = rnum > MY_RELOC_BUF_SIZ ? MY_RELOC_BUF_SIZ : rnum;
1090 siz = rinbuf * sizeof(struct reloc_record_t);
1091 if (dlthis->strm->read_buffer(dlthis->strm, rp, siz) != siz) {
1092 DL_ERROR(readstrm, "relocation");
1093 return 0;
1094 }
1095 /* reorder the bytes if need be */
1096 if (dlthis->reorder_map)
1097 dload_reorder(rp, siz, dlthis->reorder_map);
1098
1099 *checks += dload_checksum(rp, siz);
1100 do {
1101 /* perform the relocation operation */
1102 dload_relocate(dlthis, (tgt_au_t *) ipacket->img_data,
1103 rp, tramps_generated, false);
1104 rp += 1;
1105 rnum -= 1;
1106 } while ((rinbuf -= 1) > 0);
1107 } while (rnum > 0); /* all relocs */
1108 /* If trampoline(s) were generated, we need to do an update of the
1109 * trampoline copy of the packet since a 2nd phase relo will be done
1110 * later. */
1111 if (*tramps_generated == true) {
1112 dload_tramp_pkt_udpate(dlthis,
1113 (dlthis->image_secn -
1114 dlthis->ldr_sections),
1115 dlthis->image_offset, ipacket);
1116 }
1117
1118 return 1;
1119} /* dload_read_reloc */
1120
1121#define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
1122
1123/* VERY dangerous */
1124static const char imagepak[] = { "image packet" };
1125
1126/*************************************************************************
1127 * Procedure dload_data
1128 *
1129 * Parameters:
1130 * none
1131 *
1132 * Effect:
1133 * Read image data from input file, relocate it, and download it to the
1134 * target.
1135 *********************************************************************** */
1136static void dload_data(struct dload_state *dlthis)
1137{
1138 u16 curr_sect;
1139 struct doff_scnhdr_t *sptr = dlthis->sect_hdrs;
1140 struct ldr_section_info *lptr = dlthis->ldr_sections;
1141#ifdef OPT_ZERO_COPY_LOADER
1142 bool zero_copy = false;
1143#endif
1144 u8 *dest;
1145
1146 struct {
1147 struct image_packet_t ipacket;
1148 u8 bufr[BYTE_TO_HOST(IMAGE_PACKET_SIZE)];
1149 } ibuf;
1150
1151 /* Indicates whether CINIT processing has occurred */
1152 bool cinit_processed = false;
1153
1154 /* Loop through the sections and load them one at a time.
1155 */
1156 for (curr_sect = 0; curr_sect < dlthis->dfile_hdr.df_no_scns;
1157 curr_sect += 1) {
1158 if (DS_NEEDS_DOWNLOAD(sptr)) {
1159 s32 nip;
1160 ldr_addr image_offset = 0;
1161 /* set relocation info for this section */
1162 if (curr_sect < dlthis->allocated_secn_count)
1163 dlthis->delta_runaddr = sptr->ds_paddr;
1164 else {
1165 lptr = DOFFSEC_IS_LDRSEC(sptr);
1166 dlthis->delta_runaddr = 0;
1167 }
1168 dlthis->image_secn = lptr;
1169#if BITS_PER_AU > BITS_PER_BYTE
1170 lptr->name = unpack_name(dlthis, sptr->ds_offset);
1171#endif
1172 nip = sptr->ds_nipacks;
1173 while ((nip -= 1) >= 0) { /* process packets */
1174
1175 s32 ipsize;
1176 u32 checks;
1177 bool tramp_generated = false;
1178
1179 /* get the fixed header bits */
1180 if (dlthis->strm->read_buffer(dlthis->strm,
1181 &ibuf.ipacket,
1182 IPH_SIZE) !=
1183 IPH_SIZE) {
1184 DL_ERROR(readstrm, imagepak);
1185 return;
1186 }
1187 /* reorder the header if need be */
1188 if (dlthis->reorder_map) {
1189 dload_reorder(&ibuf.ipacket, IPH_SIZE,
1190 dlthis->reorder_map);
1191 }
1192 /* now read the rest of the packet */
1193 ipsize =
1194 BYTE_TO_HOST(DOFF_ALIGN
1195 (ibuf.ipacket.packet_size));
1196 if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) {
1197 DL_ERROR("Bad image packet size %d",
1198 ipsize);
1199 return;
1200 }
1201 dest = ibuf.bufr;
1202#ifdef OPT_ZERO_COPY_LOADER
1203 zero_copy = false;
1204 if (DLOAD_SECT_TYPE(sptr) != DLOAD_CINIT) {
1205 dlthis->myio->writemem(dlthis->myio,
1206 &dest,
1207 lptr->load_addr +
1208 image_offset,
1209 lptr, 0);
1210 zero_copy = (dest != ibuf.bufr);
1211 }
1212#endif
1213 /* End of determination */
1214
1215 if (dlthis->strm->read_buffer(dlthis->strm,
1216 ibuf.bufr,
1217 ipsize) !=
1218 ipsize) {
1219 DL_ERROR(readstrm, imagepak);
1220 return;
1221 }
1222 ibuf.ipacket.img_data = dest;
1223
1224 /* reorder the bytes if need be */
1225#if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
1226 if (dlthis->reorder_map) {
1227 dload_reorder(dest, ipsize,
1228 dlthis->reorder_map);
1229 }
1230 checks = dload_checksum(dest, ipsize);
1231#else
1232 if (dlthis->dfile_hdr.df_byte_reshuffle !=
1233 TARGET_ORDER(REORDER_MAP
1234 (BYTE_RESHUFFLE_VALUE))) {
1235 /* put image bytes in big-endian order,
1236 * not PC order */
1237 dload_reorder(dest, ipsize,
1238 TARGET_ORDER
1239 (dlthis->dfile_hdr.
1240 df_byte_reshuffle));
1241 }
1242#if TARGET_AU_BITS > 8
1243 checks = dload_reverse_checksum16(dest, ipsize);
1244#else
1245 checks = dload_reverse_checksum(dest, ipsize);
1246#endif
1247#endif
1248
1249 checks += dload_checksum(&ibuf.ipacket,
1250 IPH_SIZE);
1251 /* relocate the image bits as needed */
1252 if (ibuf.ipacket.num_relocs) {
1253 dlthis->image_offset = image_offset;
1254 if (!relocate_packet(dlthis,
1255 &ibuf.ipacket,
1256 &checks,
1257 &tramp_generated))
1258 return; /* serious error */
1259 }
1260 if (~checks)
1261 DL_ERROR(err_checksum, imagepak);
1262 /* Only write the result to the target if no
1263 * trampoline was generated. Otherwise it
1264 *will be done during trampoline finalize. */
1265
1266 if (tramp_generated == false) {
1267
1268 /* stuff the result into target
1269 * memory */
1270 if (DLOAD_SECT_TYPE(sptr) ==
1271 DLOAD_CINIT) {
1272 cload_cinit(dlthis,
1273 &ibuf.ipacket);
1274 cinit_processed = true;
1275 } else {
1276#ifdef OPT_ZERO_COPY_LOADER
1277 if (!zero_copy) {
1278#endif
1279 /* FIXME */
1280 if (!dlthis->myio->
1281 writemem(dlthis->
1282 myio,
1283 ibuf.bufr,
1284 lptr->
1285 load_addr +
1286 image_offset,
1287 lptr,
1288 BYTE_TO_HOST
1289 (ibuf.
1290 ipacket.
1291 packet_size))) {
1292 DL_ERROR
1293 ("Write to "
1294 FMT_UI32
1295 " failed",
1296 lptr->
1297 load_addr +
1298 image_offset);
1299 }
1300#ifdef OPT_ZERO_COPY_LOADER
1301 }
1302#endif
1303 }
1304 }
1305 image_offset +=
1306 BYTE_TO_TADDR(ibuf.ipacket.packet_size);
1307 } /* process packets */
1308 /* if this is a BSS section, we may want to fill it */
1309 if (DLOAD_SECT_TYPE(sptr) != DLOAD_BSS)
1310 goto loop_cont;
1311
1312 if (!(dlthis->myoptions & DLOAD_INITBSS))
1313 goto loop_cont;
1314
1315 if (cinit_processed) {
1316 /* Don't clear BSS after load-time
1317 * initialization */
1318 DL_ERROR
1319 ("Zero-initialization at " FMT_UI32
1320 " after " "load-time initialization!",
1321 lptr->load_addr);
1322 goto loop_cont;
1323 }
1324 /* fill the .bss area */
1325 dlthis->myio->fillmem(dlthis->myio,
1326 TADDR_TO_HOST(lptr->load_addr),
1327 lptr, TADDR_TO_HOST(lptr->size),
1328 DLOAD_FILL_BSS);
1329 goto loop_cont;
1330 }
1331 /* if DS_DOWNLOAD_MASK */
1332 /* If not loading, but BSS, zero initialize */
1333 if (DLOAD_SECT_TYPE(sptr) != DLOAD_BSS)
1334 goto loop_cont;
1335
1336 if (!(dlthis->myoptions & DLOAD_INITBSS))
1337 goto loop_cont;
1338
1339 if (curr_sect >= dlthis->allocated_secn_count)
1340 lptr = DOFFSEC_IS_LDRSEC(sptr);
1341
1342 if (cinit_processed) {
1343 /*Don't clear BSS after load-time initialization */
1344 DL_ERROR("Zero-initialization at " FMT_UI32
1345 " attempted after "
1346 "load-time initialization!", lptr->load_addr);
1347 goto loop_cont;
1348 }
1349 /* fill the .bss area */
1350 dlthis->myio->fillmem(dlthis->myio,
1351 TADDR_TO_HOST(lptr->load_addr), lptr,
1352 TADDR_TO_HOST(lptr->size),
1353 DLOAD_FILL_BSS);
1354loop_cont:
1355 sptr += 1;
1356 lptr += 1;
1357 } /* load sections */
1358
1359 /* Finalize any trampolines that were created during the load */
1360 if (dload_tramp_finalize(dlthis) == 0) {
1361 DL_ERROR("Finalization of auto-trampolines (size = " FMT_UI32
1362 ") failed", dlthis->tramp.tramp_sect_next_addr);
1363 }
1364} /* dload_data */
1365
1366/*************************************************************************
1367 * Procedure dload_reorder
1368 *
1369 * Parameters:
1370 * data 32-bit aligned pointer to data to be byte-swapped
1371 * dsiz size of the data to be reordered in sizeof() units.
1372 * map 32-bit map defining how to reorder the data. Value
1373 * must be REORDER_MAP() of some permutation
1374 * of 0x00 01 02 03
1375 *
1376 * Effect:
1377 * Re-arranges the bytes in each word according to the map specified.
1378 *
1379 *********************************************************************** */
1380/* mask for byte shift count */
1381#define SHIFT_COUNT_MASK (3 << LOG_BITS_PER_BYTE)
1382
1383void dload_reorder(void *data, int dsiz, unsigned int map)
1384{
1385 register u32 tmp, tmap, datv;
1386 u32 *dp = (u32 *) data;
1387
1388 map <<= LOG_BITS_PER_BYTE; /* align map with SHIFT_COUNT_MASK */
1389 do {
1390 tmp = 0;
1391 datv = *dp;
1392 tmap = map;
1393 do {
1394 tmp |= (datv & BYTE_MASK) << (tmap & SHIFT_COUNT_MASK);
1395 tmap >>= BITS_PER_BYTE;
1396 } while (datv >>= BITS_PER_BYTE);
1397 *dp++ = tmp;
1398 } while ((dsiz -= sizeof(u32)) > 0);
1399} /* dload_reorder */
1400
1401/*************************************************************************
1402 * Procedure dload_checksum
1403 *
1404 * Parameters:
1405 * data 32-bit aligned pointer to data to be checksummed
1406 * siz size of the data to be checksummed in sizeof() units.
1407 *
1408 * Effect:
1409 * Returns a checksum of the specified block
1410 *
1411 *********************************************************************** */
1412u32 dload_checksum(void *data, unsigned siz)
1413{
1414 u32 sum;
1415 u32 *dp;
1416 int left;
1417
1418 sum = 0;
1419 dp = (u32 *) data;
1420 for (left = siz; left > 0; left -= sizeof(u32))
1421 sum += *dp++;
1422 return sum;
1423} /* dload_checksum */
1424
1425#if HOST_ENDIANNESS
1426/*************************************************************************
1427 * Procedure dload_reverse_checksum
1428 *
1429 * Parameters:
1430 * data 32-bit aligned pointer to data to be checksummed
1431 * siz size of the data to be checksummed in sizeof() units.
1432 *
1433 * Effect:
1434 * Returns a checksum of the specified block, which is assumed to be bytes
1435 * in big-endian order.
1436 *
1437 * Notes:
1438 * In a big-endian host, things like the string table are stored as bytes
1439 * in host order. But dllcreate always checksums in little-endian order.
1440 * It is most efficient to just handle the difference a word at a time.
1441 *
1442 ********************************************************************** */
1443u32 dload_reverse_checksum(void *data, unsigned siz)
1444{
1445 u32 sum, temp;
1446 u32 *dp;
1447 int left;
1448
1449 sum = 0;
1450 dp = (u32 *) data;
1451
1452 for (left = siz; left > 0; left -= sizeof(u32)) {
1453 temp = *dp++;
1454 sum += temp << BITS_PER_BYTE * 3;
1455 sum += temp >> BITS_PER_BYTE * 3;
1456 sum += (temp >> BITS_PER_BYTE) & (BYTE_MASK << BITS_PER_BYTE);
1457 sum += (temp & (BYTE_MASK << BITS_PER_BYTE)) << BITS_PER_BYTE;
1458 }
1459
1460 return sum;
1461} /* dload_reverse_checksum */
1462
1463#if (TARGET_AU_BITS > 8) && (TARGET_AU_BITS < 32)
1464u32 dload_reverse_checksum16(void *data, unsigned siz)
1465{
1466 uint_fast32_t sum, temp;
1467 u32 *dp;
1468 int left;
1469
1470 sum = 0;
1471 dp = (u32 *) data;
1472
1473 for (left = siz; left > 0; left -= sizeof(u32)) {
1474 temp = *dp++;
1475 sum += temp << BITS_PER_BYTE * 2;
1476 sum += temp >> BITS_PER_BYTE * 2;
1477 }
1478
1479 return sum;
1480} /* dload_reverse_checksum16 */
1481#endif
1482#endif
1483
1484/*************************************************************************
1485 * Procedure swap_words
1486 *
1487 * Parameters:
1488 * data 32-bit aligned pointer to data to be swapped
1489 * siz size of the data to be swapped.
1490 * bitmap Bit map of how to swap each 32-bit word; 1 => 2 shorts,
1491 * 0 => 1 long
1492 *
1493 * Effect:
1494 * Swaps the specified data according to the specified map
1495 *
1496 *********************************************************************** */
1497static void swap_words(void *data, unsigned siz, unsigned bitmap)
1498{
1499 register int i;
1500#if TARGET_AU_BITS < 16
1501 register u16 *sp;
1502#endif
1503 register u32 *lp;
1504
1505 siz /= sizeof(u16);
1506
1507#if TARGET_AU_BITS < 16
1508 /* pass 1: do all the bytes */
1509 i = siz;
1510 sp = (u16 *) data;
1511 do {
1512 register u16 tmp;
1513 tmp = *sp;
1514 *sp++ = SWAP16BY8(tmp);
1515 } while ((i -= 1) > 0);
1516#endif
1517
1518#if TARGET_AU_BITS < 32
1519 /* pass 2: fixup the 32-bit words */
1520 i = siz >> 1;
1521 lp = (u32 *) data;
1522 do {
1523 if ((bitmap & 1) == 0) {
1524 register u32 tmp;
1525 tmp = *lp;
1526 *lp = SWAP32BY16(tmp);
1527 }
1528 lp += 1;
1529 bitmap >>= 1;
1530 } while ((i -= 1) > 0);
1531#endif
1532} /* swap_words */
1533
1534/*************************************************************************
1535 * Procedure copy_tgt_strings
1536 *
1537 * Parameters:
1538 * dstp Destination address. Assumed to be 32-bit aligned
1539 * srcp Source address. Assumed to be 32-bit aligned
1540 * charcount Number of characters to copy.
1541 *
1542 * Effect:
1543 * Copies strings from the source (which is in usual .dof file order on
1544 * the loading processor) to the destination buffer (which should be in proper
1545 * target addressable unit order). Makes sure the last string in the
1546 * buffer is NULL terminated (for safety).
1547 * Returns the first unused destination address.
1548 *********************************************************************** */
1549static char *copy_tgt_strings(void *dstp, void *srcp, unsigned charcount)
1550{
1551 register tgt_au_t *src = (tgt_au_t *) srcp;
1552 register tgt_au_t *dst = (tgt_au_t *) dstp;
1553 register int cnt = charcount;
1554 do {
1555#if TARGET_AU_BITS <= BITS_PER_AU
1556 /* byte-swapping issues may exist for strings on target */
1557 *dst++ = *src++;
1558#else
1559 *dst++ = *src++;
1560#endif
1561 } while ((cnt -= (sizeof(tgt_au_t) * BITS_PER_AU / BITS_PER_BYTE)) > 0);
1562 /*apply force to make sure that the string table has null terminator */
1563#if (BITS_PER_AU == BITS_PER_BYTE) && (TARGET_AU_BITS == BITS_PER_BYTE)
1564 dst[-1] = 0;
1565#else
1566 /* little endian */
1567 dst[-1] &= (1 << (BITS_PER_AU - BITS_PER_BYTE)) - 1;
1568#endif
1569 return (char *)dst;
1570} /* copy_tgt_strings */
1571
1572/*************************************************************************
1573 * Procedure init_module_handle
1574 *
1575 * Parameters:
1576 * none
1577 *
1578 * Effect:
1579 * Initializes the module handle we use to enable unloading, and installs
1580 * the debug information required by the target.
1581 *
1582 * Notes:
1583 * The handle returned from dynamic_load_module needs to encapsulate all the
1584 * allocations done for the module, and enable them plus the modules symbols to
1585 * be deallocated.
1586 *
1587 *********************************************************************** */
1588#ifndef _BIG_ENDIAN
1589static const struct ldr_section_info dllview_info_init = { ".dllview", 0, 0,
1590 (ldr_addr)-1, DBG_LIST_PAGE, DLOAD_DATA, 0
1591};
1592#else
1593static const struct ldr_section_info dllview_info_init = { ".dllview", 0, 0,
1594 (ldr_addr)-1, DLOAD_DATA, DBG_LIST_PAGE, 0
1595};
1596#endif
1597static void init_module_handle(struct dload_state *dlthis)
1598{
1599 struct my_handle *hndl;
1600 u16 curr_sect;
1601 struct ldr_section_info *asecs;
1602 struct dll_module *dbmod;
1603 struct dll_sect *dbsec;
1604 struct dbg_mirror_root *mlist;
1605 register char *cp;
1606 struct modules_header mhdr;
1607 struct ldr_section_info dllview_info;
1608 struct dynload_symbol *debug_mirror_sym;
1609 hndl = dlthis->myhandle;
1610 if (!hndl)
1611 return; /* must be errors detected, so forget it */
1612
1613 /* Store the section count */
1614 hndl->secn_count = dlthis->allocated_secn_count;
1615
1616 /* If a trampoline section was created, add it in */
1617 if (dlthis->tramp.tramp_sect_next_addr != 0)
1618 hndl->secn_count += 1;
1619
1620 hndl->secn_count = hndl->secn_count << 1;
1621
1622 hndl->secn_count = dlthis->allocated_secn_count << 1;
1623#ifndef TARGET_ENDIANNESS
1624 if (dlthis->big_e_target)
1625 hndl->secn_count += 1; /* flag for big-endian */
1626#endif
1627 if (dlthis->dload_errcount)
1628 return; /* abandon if errors detected */
1629 /* Locate the symbol that names the header for the CCS debug list
1630 of modules. If not found, we just don't generate the debug record.
1631 If found, we create our modules list. We make sure to create the
1632 loader_dllview_root even if there is no relocation info to record,
1633 just to try to put both symbols in the same symbol table and
1634 module. */
1635 debug_mirror_sym = dlthis->mysym->find_matching_symbol(dlthis->mysym,
1636 loader_dllview_root);
1637 if (!debug_mirror_sym) {
1638 struct dynload_symbol *dlmodsym;
1639 struct dbg_mirror_root *mlst;
1640
1641 /* our root symbol is not yet present;
1642 check if we have DLModules defined */
1643 dlmodsym = dlthis->mysym->find_matching_symbol(dlthis->mysym,
1644 LINKER_MODULES_HEADER);
1645 if (!dlmodsym)
1646 return; /* no DLModules list so no debug info */
1647 /* if we have DLModules defined, construct our header */
1648 mlst = (struct dbg_mirror_root *)
1649 dlthis->mysym->dload_allocate(dlthis->mysym,
1650 sizeof(struct
1651 dbg_mirror_root));
1652 if (!mlst) {
1653 DL_ERROR(err_alloc, sizeof(struct dbg_mirror_root));
1654 return;
1655 }
1656 mlst->hnext = NULL;
1657 mlst->changes = 0;
1658 mlst->refcount = 0;
1659 mlst->dbthis = TDATA_TO_TADDR(dlmodsym->value);
1660 /* add our root symbol */
1661 debug_mirror_sym = dlthis->mysym->add_to_symbol_table
1662 (dlthis->mysym, loader_dllview_root,
1663 (unsigned)dlthis->myhandle);
1664 if (!debug_mirror_sym) {
1665 /* failed, recover memory */
1666 dlthis->mysym->dload_deallocate(dlthis->mysym, mlst);
1667 return;
1668 }
1669 debug_mirror_sym->value = (u32) mlst;
1670 }
1671 /* First create the DLLview record and stuff it into the buffer.
1672 Then write it to the DSP. Record pertinent locations in our hndl,
1673 and add it to the per-processor list of handles with debug info. */
1674#ifndef DEBUG_HEADER_IN_LOADER
1675 mlist = (struct dbg_mirror_root *)debug_mirror_sym->value;
1676 if (!mlist)
1677 return;
1678#else
1679 mlist = (struct dbg_mirror_root *)&debug_list_header;
1680#endif
1681 hndl->dm.hroot = mlist; /* set pointer to root into our handle */
1682 if (!dlthis->allocated_secn_count)
1683 return; /* no load addresses to be recorded */
1684 /* reuse temporary symbol storage */
1685 dbmod = (struct dll_module *)dlthis->local_symtab;
1686 /* Create the DLLview record in the memory we retain for our handle */
1687 dbmod->num_sects = dlthis->allocated_secn_count;
1688 dbmod->timestamp = dlthis->verify.dv_timdat;
1689 dbmod->version = INIT_VERSION;
1690 dbmod->verification = VERIFICATION;
1691 asecs = dlthis->ldr_sections;
1692 dbsec = dbmod->sects;
1693 for (curr_sect = dlthis->allocated_secn_count;
1694 curr_sect > 0; curr_sect -= 1) {
1695 dbsec->sect_load_adr = asecs->load_addr;
1696 dbsec->sect_run_adr = asecs->run_addr;
1697 dbsec += 1;
1698 asecs += 1;
1699 }
1700
1701 /* If a trampoline section was created go ahead and add its info */
1702 if (dlthis->tramp.tramp_sect_next_addr != 0) {
1703 dbmod->num_sects++;
1704 dbsec->sect_load_adr = asecs->load_addr;
1705 dbsec->sect_run_adr = asecs->run_addr;
1706 dbsec++;
1707 asecs++;
1708 }
1709
1710 /* now cram in the names */
1711 cp = copy_tgt_strings(dbsec, dlthis->str_head,
1712 dlthis->debug_string_size);
1713
1714 /* If a trampoline section was created, add its name so DLLView
1715 * can show the user the section info. */
1716 if (dlthis->tramp.tramp_sect_next_addr != 0) {
1717 cp = copy_tgt_strings(cp,
1718 dlthis->tramp.final_string_table,
1719 strlen(dlthis->tramp.final_string_table) +
1720 1);
1721 }
1722
1723 /* round off the size of the debug record, and remember same */
1724 hndl->dm.dbsiz = HOST_TO_TDATA_ROUND(cp - (char *)dbmod);
1725 *cp = 0; /* strictly to make our test harness happy */
1726 dllview_info = dllview_info_init;
1727 dllview_info.size = TDATA_TO_TADDR(hndl->dm.dbsiz);
1728 /* Initialize memory context to default heap */
1729 dllview_info.context = 0;
1730 hndl->dm.context = 0;
1731 /* fill in next pointer and size */
1732 if (mlist->hnext) {
1733 dbmod->next_module = TADDR_TO_TDATA(mlist->hnext->dm.dbthis);
1734 dbmod->next_module_size = mlist->hnext->dm.dbsiz;
1735 } else {
1736 dbmod->next_module_size = 0;
1737 dbmod->next_module = 0;
1738 }
1739 /* allocate memory for on-DSP DLLview debug record */
1740 if (!dlthis->myalloc)
1741 return;
1742 if (!dlthis->myalloc->dload_allocate(dlthis->myalloc, &dllview_info,
1743 HOST_TO_TADDR(sizeof(u32)))) {
1744 return;
1745 }
1746 /* Store load address of .dllview section */
1747 hndl->dm.dbthis = dllview_info.load_addr;
1748 /* Store memory context (segid) in which .dllview section
1749 * was allocated */
1750 hndl->dm.context = dllview_info.context;
1751 mlist->refcount += 1;
1752 /* swap bytes in the entire debug record, but not the string table */
1753 if (TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)) {
1754 swap_words(dbmod, (char *)dbsec - (char *)dbmod,
1755 DLL_MODULE_BITMAP);
1756 }
1757 /* Update the DLLview list on the DSP write new record */
1758 if (!dlthis->myio->writemem(dlthis->myio, dbmod,
1759 dllview_info.load_addr, &dllview_info,
1760 TADDR_TO_HOST(dllview_info.size))) {
1761 return;
1762 }
1763 /* write new header */
1764 mhdr.first_module_size = hndl->dm.dbsiz;
1765 mhdr.first_module = TADDR_TO_TDATA(dllview_info.load_addr);
1766 /* swap bytes in the module header, if needed */
1767 if (TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)) {
1768 swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
1769 MODULES_HEADER_BITMAP);
1770 }
1771 dllview_info = dllview_info_init;
1772 if (!dlthis->myio->writemem(dlthis->myio, &mhdr, mlist->dbthis,
1773 &dllview_info,
1774 sizeof(struct modules_header) -
1775 sizeof(u16))) {
1776 return;
1777 }
1778 /* Add the module handle to this processor's list
1779 of handles with debug info */
1780 hndl->dm.hnext = mlist->hnext;
1781 if (hndl->dm.hnext)
1782 hndl->dm.hnext->dm.hprev = hndl;
1783 hndl->dm.hprev = (struct my_handle *)mlist;
1784 mlist->hnext = hndl; /* insert after root */
1785} /* init_module_handle */
1786
1787/*************************************************************************
1788 * Procedure dynamic_unload_module
1789 *
1790 * Parameters:
1791 * mhandle A module handle from dynamic_load_module
1792 * syms Host-side symbol table and malloc/free functions
1793 * alloc Target-side memory allocation
1794 *
1795 * Effect:
1796 * The module specified by mhandle is unloaded. Unloading causes all
1797 * target memory to be deallocated, all symbols defined by the module to
1798 * be purged, and any host-side storage used by the dynamic loader for
1799 * this module to be released.
1800 *
1801 * Returns:
1802 * Zero for success. On error, the number of errors detected is returned.
1803 * Individual errors are reported using syms->error_report().
1804 *********************************************************************** */
1805int dynamic_unload_module(void *mhandle,
1806 struct dynamic_loader_sym *syms,
1807 struct dynamic_loader_allocate *alloc,
1808 struct dynamic_loader_initialize *init)
1809{
1810 s16 curr_sect;
1811 struct ldr_section_info *asecs;
1812 struct my_handle *hndl;
1813 struct dbg_mirror_root *root;
1814 unsigned errcount = 0;
1815 struct ldr_section_info dllview_info = dllview_info_init;
1816 struct modules_header mhdr;
1817
1818 hndl = (struct my_handle *)mhandle;
1819 if (!hndl)
1820 return 0; /* if handle is null, nothing to do */
1821 /* Clear out the module symbols
1822 * Note that if this is the module that defined MODULES_HEADER
1823 (the head of the target debug list)
1824 * then this operation will blow away that symbol.
1825 It will therefore be impossible for subsequent
1826 * operations to add entries to this un-referenceable list. */
1827 if (!syms)
1828 return 1;
1829 syms->purge_symbol_table(syms, (unsigned)hndl);
1830 /* Deallocate target memory for sections
1831 * NOTE: The trampoline section, if created, gets deleted here, too */
1832
1833 asecs = hndl->secns;
1834 if (alloc)
1835 for (curr_sect = (hndl->secn_count >> 1); curr_sect > 0;
1836 curr_sect -= 1) {
1837 asecs->name = NULL;
1838 alloc->dload_deallocate(alloc, asecs++);
1839 }
1840 root = hndl->dm.hroot;
1841 if (!root) {
1842 /* there is a debug list containing this module */
1843 goto func_end;
1844 }
1845 if (!hndl->dm.dbthis) { /* target-side dllview record exists */
1846 goto loop_end;
1847 }
1848 /* Retrieve memory context in which .dllview was allocated */
1849 dllview_info.context = hndl->dm.context;
1850 if (hndl->dm.hprev == hndl)
1851 goto exitunltgt;
1852
1853 /* target-side dllview record is in list */
1854 /* dequeue this record from our GPP-side mirror list */
1855 hndl->dm.hprev->dm.hnext = hndl->dm.hnext;
1856 if (hndl->dm.hnext)
1857 hndl->dm.hnext->dm.hprev = hndl->dm.hprev;
1858 /* Update next_module of previous entry in target list
1859 * We are using mhdr here as a surrogate for either a
1860 struct modules_header or a dll_module */
1861 if (hndl->dm.hnext) {
1862 mhdr.first_module = TADDR_TO_TDATA(hndl->dm.hnext->dm.dbthis);
1863 mhdr.first_module_size = hndl->dm.hnext->dm.dbsiz;
1864 } else {
1865 mhdr.first_module = 0;
1866 mhdr.first_module_size = 0;
1867 }
1868 if (!init)
1869 goto exitunltgt;
1870
1871 if (!init->connect(init)) {
1872 dload_syms_error(syms, iconnect);
1873 errcount += 1;
1874 goto exitunltgt;
1875 }
1876 /* swap bytes in the module header, if needed */
1877 if (TARGET_ENDIANNESS_DIFFERS(hndl->secn_count & 0x1)) {
1878 swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
1879 MODULES_HEADER_BITMAP);
1880 }
1881 if (!init->writemem(init, &mhdr, hndl->dm.hprev->dm.dbthis,
1882 &dllview_info, sizeof(struct modules_header) -
1883 sizeof(mhdr.update_flag))) {
1884 dload_syms_error(syms, dlvwrite);
1885 errcount += 1;
1886 }
1887 /* update change counter */
1888 root->changes += 1;
1889 if (!init->writemem(init, &(root->changes),
1890 root->dbthis + HOST_TO_TADDR
1891 (sizeof(mhdr.first_module) +
1892 sizeof(mhdr.first_module_size)),
1893 &dllview_info, sizeof(mhdr.update_flag))) {
1894 dload_syms_error(syms, dlvwrite);
1895 errcount += 1;
1896 }
1897 init->release(init);
1898exitunltgt:
1899 /* release target storage */
1900 dllview_info.size = TDATA_TO_TADDR(hndl->dm.dbsiz);
1901 dllview_info.load_addr = hndl->dm.dbthis;
1902 if (alloc)
1903 alloc->dload_deallocate(alloc, &dllview_info);
1904 root->refcount -= 1;
1905 /* target-side dllview record exists */
1906loop_end:
1907#ifndef DEBUG_HEADER_IN_LOADER
1908 if (root->refcount <= 0) {
1909 /* if all references gone, blow off the header */
1910 /* our root symbol may be gone due to the Purge above,
1911 but if not, do not destroy the root */
1912 if (syms->find_matching_symbol
1913 (syms, loader_dllview_root) == NULL)
1914 syms->dload_deallocate(syms, root);
1915 }
1916#endif
1917func_end:
1918 /* there is a debug list containing this module */
1919 syms->dload_deallocate(syms, mhandle); /* release our storage */
1920 return errcount;
1921} /* dynamic_unload_module */
1922
1923#if BITS_PER_AU > BITS_PER_BYTE
1924/*************************************************************************
1925 * Procedure unpack_name
1926 *
1927 * Parameters:
1928 * soffset Byte offset into the string table
1929 *
1930 * Effect:
1931 * Returns a pointer to the string specified by the offset supplied, or
1932 * NULL for error.
1933 *
1934 *********************************************************************** */
1935static char *unpack_name(struct dload_state *dlthis, u32 soffset)
1936{
1937 u8 tmp, *src;
1938 char *dst;
1939
1940 if (soffset >= dlthis->dfile_hdr.df_strtab_size) {
1941 dload_error(dlthis, "Bad string table offset " FMT_UI32,
1942 soffset);
1943 return NULL;
1944 }
1945 src = (uint_least8_t *) dlthis->str_head +
1946 (soffset >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE));
1947 dst = dlthis->str_temp;
1948 if (soffset & 1)
1949 *dst++ = *src++; /* only 1 character in first word */
1950 do {
1951 tmp = *src++;
1952 *dst = (tmp >> BITS_PER_BYTE);
1953 if (!(*dst++))
1954 break;
1955 } while ((*dst++ = tmp & BYTE_MASK));
1956 dlthis->temp_len = dst - dlthis->str_temp;
1957 /* squirrel away length including terminating null */
1958 return dlthis->str_temp;
1959} /* unpack_name */
1960#endif
diff --git a/drivers/staging/tidspbridge/dynload/dload_internal.h b/drivers/staging/tidspbridge/dynload/dload_internal.h
new file mode 100644
index 00000000000..803756198bc
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/dload_internal.h
@@ -0,0 +1,351 @@
1/*
2 * dload_internal.h
3 *
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5 *
6 * Copyright (C) 2005-2006 Texas Instruments, Inc.
7 *
8 * This package is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15 */
16
17#ifndef _DLOAD_INTERNAL_
18#define _DLOAD_INTERNAL_
19
20#include <linux/types.h>
21
22/*
23 * Internal state definitions for the dynamic loader
24 */
25
26#define TRUE 1
27#define FALSE 0
28
29/* type used for relocation intermediate results */
30typedef s32 rvalue;
31
32/* unsigned version of same; must have at least as many bits */
33typedef u32 urvalue;
34
35/*
36 * Dynamic loader configuration constants
37 */
38/* error issued if input has more sections than this limit */
39#define REASONABLE_SECTION_LIMIT 100
40
41/* (Addressable unit) value used to clear BSS section */
42#define DLOAD_FILL_BSS 0
43
44/*
45 * Reorder maps explained (?)
46 *
47 * The doff file format defines a 32-bit pattern used to determine the
48 * byte order of an image being read. That value is
49 * BYTE_RESHUFFLE_VALUE == 0x00010203
50 * For purposes of the reorder routine, we would rather have the all-is-OK
51 * for 32-bits pattern be 0x03020100. This first macro makes the
52 * translation from doff file header value to MAP value: */
53#define REORDER_MAP(rawmap) ((rawmap) ^ 0x3030303)
54/* This translation is made in dload_headers. Thereafter, the all-is-OK
55 * value for the maps stored in dlthis is REORDER_MAP(BYTE_RESHUFFLE_VALUE).
56 * But sadly, not all bits of the doff file are 32-bit integers.
57 * The notable exceptions are strings and image bits.
58 * Strings obey host byte order: */
59#if defined(_BIG_ENDIAN)
60#define HOST_BYTE_ORDER(cookedmap) ((cookedmap) ^ 0x3030303)
61#else
62#define HOST_BYTE_ORDER(cookedmap) (cookedmap)
63#endif
64/* Target bits consist of target AUs (could be bytes, or 16-bits,
65 * or 32-bits) stored as an array in host order. A target order
66 * map is defined by: */
67#if !defined(_BIG_ENDIAN) || TARGET_AU_BITS > 16
68#define TARGET_ORDER(cookedmap) (cookedmap)
69#elif TARGET_AU_BITS > 8
70#define TARGET_ORDER(cookedmap) ((cookedmap) ^ 0x2020202)
71#else
72#define TARGET_ORDER(cookedmap) ((cookedmap) ^ 0x3030303)
73#endif
74
75/* forward declaration for handle returned by dynamic loader */
76struct my_handle;
77
78/*
79 * a list of module handles, which mirrors the debug list on the target
80 */
81struct dbg_mirror_root {
82 /* must be same as dbg_mirror_list; __DLModules address on target */
83 u32 dbthis;
84 struct my_handle *hnext; /* must be same as dbg_mirror_list */
85 u16 changes; /* change counter */
86 u16 refcount; /* number of modules referencing this root */
87};
88
89struct dbg_mirror_list {
90 u32 dbthis;
91 struct my_handle *hnext, *hprev;
92 struct dbg_mirror_root *hroot;
93 u16 dbsiz;
94 u32 context; /* Save context for .dllview memory allocation */
95};
96
97#define VARIABLE_SIZE 1
98/*
99 * the structure we actually return as an opaque module handle
100 */
101struct my_handle {
102 struct dbg_mirror_list dm; /* !!! must be first !!! */
103 /* sections following << 1, LSB is set for big-endian target */
104 u16 secn_count;
105 struct ldr_section_info secns[VARIABLE_SIZE];
106};
107#define MY_HANDLE_SIZE (sizeof(struct my_handle) -\
108 sizeof(struct ldr_section_info))
109/* real size of my_handle */
110
111/*
112 * reduced symbol structure used for symbols during relocation
113 */
114struct local_symbol {
115 s32 value; /* Relocated symbol value */
116 s32 delta; /* Original value in input file */
117 s16 secnn; /* section number */
118 s16 sclass; /* symbol class */
119};
120
121/*
122 * Trampoline data structures
123 */
124#define TRAMP_NO_GEN_AVAIL 65535
125#define TRAMP_SYM_PREFIX "__$dbTR__"
126#define TRAMP_SECT_NAME ".dbTR"
127/* MUST MATCH THE LENGTH ABOVE!! */
128#define TRAMP_SYM_PREFIX_LEN 9
129/* Includes NULL termination */
130#define TRAMP_SYM_HEX_ASCII_LEN 9
131
132#define GET_CONTAINER(ptr, type, field) ((type *)((unsigned long)ptr -\
133 (unsigned long)(&((type *)0)->field)))
134#ifndef FIELD_OFFSET
135#define FIELD_OFFSET(type, field) ((unsigned long)(&((type *)0)->field))
136#endif
137
138/*
139 The trampoline code for the target is located in a table called
140 "tramp_gen_info" with is indexed by looking up the index in the table
141 "tramp_map". The tramp_map index is acquired using the target
142 HASH_FUNC on the relocation type that caused the trampoline. Each
143 trampoline code table entry MUST follow this format:
144
145 |----------------------------------------------|
146 | tramp_gen_code_hdr |
147 |----------------------------------------------|
148 | Trampoline image code |
149 | (the raw instruction code for the target) |
150 |----------------------------------------------|
151 | Relocation entries for the image code |
152 |----------------------------------------------|
153
154 This is very similar to how image data is laid out in the DOFF file
155 itself.
156 */
157struct tramp_gen_code_hdr {
158 u32 tramp_code_size; /* in BYTES */
159 u32 num_relos;
160 u32 relo_offset; /* in BYTES */
161};
162
163struct tramp_img_pkt {
164 struct tramp_img_pkt *next; /* MUST BE FIRST */
165 u32 base;
166 struct tramp_gen_code_hdr hdr;
167 u8 payload[VARIABLE_SIZE];
168};
169
170struct tramp_img_dup_relo {
171 struct tramp_img_dup_relo *next;
172 struct reloc_record_t relo;
173};
174
175struct tramp_img_dup_pkt {
176 struct tramp_img_dup_pkt *next; /* MUST BE FIRST */
177 s16 secnn;
178 u32 offset;
179 struct image_packet_t img_pkt;
180 struct tramp_img_dup_relo *relo_chain;
181
182 /* PAYLOAD OF IMG PKT FOLLOWS */
183};
184
185struct tramp_sym {
186 struct tramp_sym *next; /* MUST BE FIRST */
187 u32 index;
188 u32 str_index;
189 struct local_symbol sym_info;
190};
191
192struct tramp_string {
193 struct tramp_string *next; /* MUST BE FIRST */
194 u32 index;
195 char str[VARIABLE_SIZE]; /* NULL terminated */
196};
197
198struct tramp_info {
199 u32 tramp_sect_next_addr;
200 struct ldr_section_info sect_info;
201
202 struct tramp_sym *symbol_head;
203 struct tramp_sym *symbol_tail;
204 u32 tramp_sym_next_index;
205 struct local_symbol *final_sym_table;
206
207 struct tramp_string *string_head;
208 struct tramp_string *string_tail;
209 u32 tramp_string_next_index;
210 u32 tramp_string_size;
211 char *final_string_table;
212
213 struct tramp_img_pkt *tramp_pkts;
214 struct tramp_img_dup_pkt *dup_pkts;
215};
216
217/*
218 * States of the .cinit state machine
219 */
220enum cinit_mode {
221 CI_COUNT = 0, /* expecting a count */
222 CI_ADDRESS, /* expecting an address */
223#if CINIT_ALIGN < CINIT_ADDRESS /* handle case of partial address field */
224 CI_PARTADDRESS, /* have only part of the address */
225#endif
226 CI_COPY, /* in the middle of copying data */
227 CI_DONE /* end of .cinit table */
228};
229
230/*
231 * The internal state of the dynamic loader, which is passed around as
232 * an object
233 */
234struct dload_state {
235 struct dynamic_loader_stream *strm; /* The module input stream */
236 struct dynamic_loader_sym *mysym; /* Symbols for this session */
237 /* target memory allocator */
238 struct dynamic_loader_allocate *myalloc;
239 struct dynamic_loader_initialize *myio; /* target memory initializer */
240 unsigned myoptions; /* Options parameter dynamic_load_module */
241
242 char *str_head; /* Pointer to string table */
243#if BITS_PER_AU > BITS_PER_BYTE
244 char *str_temp; /* Pointer to temporary buffer for strings */
245 /* big enough to hold longest string */
246 unsigned temp_len; /* length of last temporary string */
247 char *xstrings; /* Pointer to buffer for expanded */
248 /* strings for sec names */
249#endif
250 /* Total size of strings for DLLView section names */
251 unsigned debug_string_size;
252 /* Pointer to parallel section info for allocated sections only */
253 struct doff_scnhdr_t *sect_hdrs; /* Pointer to section table */
254 struct ldr_section_info *ldr_sections;
255#if TMS32060
256 /* The address of the start of the .bss section */
257 ldr_addr bss_run_base;
258#endif
259 struct local_symbol *local_symtab; /* Relocation symbol table */
260
261 /* pointer to DL section info for the section being relocated */
262 struct ldr_section_info *image_secn;
263 /* change in run address for current section during relocation */
264 ldr_addr delta_runaddr;
265 ldr_addr image_offset; /* offset of current packet in section */
266 enum cinit_mode cinit_state; /* current state of cload_cinit() */
267 int cinit_count; /* the current count */
268 ldr_addr cinit_addr; /* the current address */
269 s16 cinit_page; /* the current page */
270 /* Handle to be returned by dynamic_load_module */
271 struct my_handle *myhandle;
272 unsigned dload_errcount; /* Total # of errors reported so far */
273 /* Number of target sections that require allocation and relocation */
274 unsigned allocated_secn_count;
275#ifndef TARGET_ENDIANNESS
276 int big_e_target; /* Target data in big-endian format */
277#endif
278 /* map for reordering bytes, 0 if not needed */
279 u32 reorder_map;
280 struct doff_filehdr_t dfile_hdr; /* DOFF file header structure */
281 struct doff_verify_rec_t verify; /* Verify record */
282
283 struct tramp_info tramp; /* Trampoline data, if needed */
284
285 int relstkidx; /* index into relocation value stack */
286 /* relocation value stack used in relexp.c */
287 rvalue relstk[STATIC_EXPR_STK_SIZE];
288
289};
290
291#ifdef TARGET_ENDIANNESS
292#define TARGET_BIG_ENDIAN TARGET_ENDIANNESS
293#else
294#define TARGET_BIG_ENDIAN (dlthis->big_e_target)
295#endif
296
297/*
298 * Exports from cload.c to rest of the world
299 */
300extern void dload_error(struct dload_state *dlthis, const char *errtxt, ...);
301extern void dload_syms_error(struct dynamic_loader_sym *syms,
302 const char *errtxt, ...);
303extern void dload_headers(struct dload_state *dlthis);
304extern void dload_strings(struct dload_state *dlthis, bool sec_names_only);
305extern void dload_sections(struct dload_state *dlthis);
306extern void dload_reorder(void *data, int dsiz, u32 map);
307extern u32 dload_checksum(void *data, unsigned siz);
308
309#if HOST_ENDIANNESS
310extern uint32_t dload_reverse_checksum(void *data, unsigned siz);
311#if (TARGET_AU_BITS > 8) && (TARGET_AU_BITS < 32)
312extern uint32_t dload_reverse_checksum16(void *data, unsigned siz);
313#endif
314#endif
315
316#define IS_DATA_SCN(zzz) (DLOAD_SECTION_TYPE((zzz)->type) != DLOAD_TEXT)
317#define IS_DATA_SCN_NUM(zzz) \
318 (DLOAD_SECT_TYPE(&dlthis->sect_hdrs[(zzz)-1]) != DLOAD_TEXT)
319
320/*
321 * exported by reloc.c
322 */
323extern void dload_relocate(struct dload_state *dlthis, tgt_au_t * data,
324 struct reloc_record_t *rp, bool * tramps_generated,
325 bool second_pass);
326
327extern rvalue dload_unpack(struct dload_state *dlthis, tgt_au_t * data,
328 int fieldsz, int offset, unsigned sgn);
329
330extern int dload_repack(struct dload_state *dlthis, rvalue val, tgt_au_t * data,
331 int fieldsz, int offset, unsigned sgn);
332
333/*
334 * exported by tramp.c
335 */
336extern bool dload_tramp_avail(struct dload_state *dlthis,
337 struct reloc_record_t *rp);
338
339int dload_tramp_generate(struct dload_state *dlthis, s16 secnn,
340 u32 image_offset, struct image_packet_t *ipacket,
341 struct reloc_record_t *rp);
342
343extern int dload_tramp_pkt_udpate(struct dload_state *dlthis,
344 s16 secnn, u32 image_offset,
345 struct image_packet_t *ipacket);
346
347extern int dload_tramp_finalize(struct dload_state *dlthis);
348
349extern void dload_tramp_cleanup(struct dload_state *dlthis);
350
351#endif /* _DLOAD_INTERNAL_ */
diff --git a/drivers/staging/tidspbridge/dynload/doff.h b/drivers/staging/tidspbridge/dynload/doff.h
new file mode 100644
index 00000000000..5bf99240f9f
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/doff.h
@@ -0,0 +1,344 @@
1/*
2 * doff.h
3 *
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5 *
6 * Structures & definitions used for dynamically loaded modules file format.
7 * This format is a reformatted version of COFF. It optimizes the layout for
8 * the dynamic loader.
9 *
10 * .dof files, when viewed as a sequence of 32-bit integers, look the same
11 * on big-endian and little-endian machines.
12 *
13 * Copyright (C) 2005-2006 Texas Instruments, Inc.
14 *
15 * This package is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License version 2 as
17 * published by the Free Software Foundation.
18 *
19 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
21 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22 */
23
24#ifndef _DOFF_H
25#define _DOFF_H
26
27#ifndef UINT32_C
28#define UINT32_C(zzz) ((u32)zzz)
29#endif
30
31#define BYTE_RESHUFFLE_VALUE UINT32_C(0x00010203)
32
33/* DOFF file header containing fields categorizing the remainder of the file */
34struct doff_filehdr_t {
35
36 /* string table size, including filename, in bytes */
37 u32 df_strtab_size;
38
39 /* entry point if one exists */
40 u32 df_entrypt;
41
42 /* identifies byte ordering of file;
43 * always set to BYTE_RESHUFFLE_VALUE */
44 u32 df_byte_reshuffle;
45
46 /* Size of the string table up to and including the last section name */
47 /* Size includes the name of the COFF file also */
48 u32 df_scn_name_size;
49
50#ifndef _BIG_ENDIAN
51 /* number of symbols */
52 u16 df_no_syms;
53
54 /* length in bytes of the longest string, including terminating NULL */
55 /* excludes the name of the file */
56 u16 df_max_str_len;
57
58 /* total number of sections including no-load ones */
59 u16 df_no_scns;
60
61 /* number of sections containing target code allocated or downloaded */
62 u16 df_target_scns;
63
64 /* unique id for dll file format & version */
65 u16 df_doff_version;
66
67 /* identifies ISA */
68 u16 df_target_id;
69
70 /* useful file flags */
71 u16 df_flags;
72
73 /* section reference for entry point, N_UNDEF for none, */
74 /* N_ABS for absolute address */
75 s16 df_entry_secn;
76#else
77 /* length of the longest string, including terminating NULL */
78 u16 df_max_str_len;
79
80 /* number of symbols */
81 u16 df_no_syms;
82
83 /* number of sections containing target code allocated or downloaded */
84 u16 df_target_scns;
85
86 /* total number of sections including no-load ones */
87 u16 df_no_scns;
88
89 /* identifies ISA */
90 u16 df_target_id;
91
92 /* unique id for dll file format & version */
93 u16 df_doff_version;
94
95 /* section reference for entry point, N_UNDEF for none, */
96 /* N_ABS for absolute address */
97 s16 df_entry_secn;
98
99 /* useful file flags */
100 u16 df_flags;
101#endif
102 /* checksum for file header record */
103 u32 df_checksum;
104
105};
106
107/* flags in the df_flags field */
108#define DF_LITTLE 0x100
109#define DF_BIG 0x200
110#define DF_BYTE_ORDER (DF_LITTLE | DF_BIG)
111
112/* Supported processors */
113#define TMS470_ID 0x97
114#define LEAD_ID 0x98
115#define TMS32060_ID 0x99
116#define LEAD3_ID 0x9c
117
118/* Primary processor for loading */
119#if TMS32060
120#define TARGET_ID TMS32060_ID
121#endif
122
123/* Verification record containing values used to test integrity of the bits */
124struct doff_verify_rec_t {
125
126 /* time and date stamp */
127 u32 dv_timdat;
128
129 /* checksum for all section records */
130 u32 dv_scn_rec_checksum;
131
132 /* checksum for string table */
133 u32 dv_str_tab_checksum;
134
135 /* checksum for symbol table */
136 u32 dv_sym_tab_checksum;
137
138 /* checksum for verification record */
139 u32 dv_verify_rec_checksum;
140
141};
142
143/* String table is an array of null-terminated strings. The first entry is
144 * the filename, which is added by DLLcreate. No new structure definitions
145 * are required.
146 */
147
148/* Section Records including information on the corresponding image packets */
149/*
150 * !!WARNING!!
151 *
152 * This structure is expected to match in form ldr_section_info in
153 * dynamic_loader.h
154 */
155
156struct doff_scnhdr_t {
157
158 s32 ds_offset; /* offset into string table of name */
159 s32 ds_paddr; /* RUN address, in target AU */
160 s32 ds_vaddr; /* LOAD address, in target AU */
161 s32 ds_size; /* section size, in target AU */
162#ifndef _BIG_ENDIAN
163 u16 ds_page; /* memory page id */
164 u16 ds_flags; /* section flags */
165#else
166 u16 ds_flags; /* section flags */
167 u16 ds_page; /* memory page id */
168#endif
169 u32 ds_first_pkt_offset;
170 /* Absolute byte offset into the file */
171 /* where the first image record resides */
172
173 s32 ds_nipacks; /* number of image packets */
174
175};
176
177/* Symbol table entry */
178struct doff_syment_t {
179
180 s32 dn_offset; /* offset into string table of name */
181 s32 dn_value; /* value of symbol */
182#ifndef _BIG_ENDIAN
183 s16 dn_scnum; /* section number */
184 s16 dn_sclass; /* storage class */
185#else
186 s16 dn_sclass; /* storage class */
187 s16 dn_scnum; /* section number, 1-based */
188#endif
189
190};
191
192/* special values for dn_scnum */
193#define DN_UNDEF 0 /* undefined symbol */
194#define DN_ABS (-1) /* value of symbol is absolute */
195/* special values for dn_sclass */
196#define DN_EXT 2
197#define DN_STATLAB 20
198#define DN_EXTLAB 21
199
200/* Default value of image bits in packet */
201/* Configurable by user on the command line */
202#define IMAGE_PACKET_SIZE 1024
203
204/* An image packet contains a chunk of data from a section along with */
205/* information necessary for its processing. */
206struct image_packet_t {
207
208 s32 num_relocs; /* number of relocations for */
209 /* this packet */
210
211 s32 packet_size; /* number of bytes in array */
212 /* "bits" occupied by */
213 /* valid data. Could be */
214 /* < IMAGE_PACKET_SIZE to */
215 /* prevent splitting a */
216 /* relocation across packets. */
217 /* Last packet of a section */
218 /* will most likely contain */
219 /* < IMAGE_PACKET_SIZE bytes */
220 /* of valid data */
221
222 s32 img_chksum; /* Checksum for image packet */
223 /* and the corresponding */
224 /* relocation records */
225
226 u8 *img_data; /* Actual data in section */
227
228};
229
230/* The relocation structure definition matches the COFF version. Offsets */
231/* however are relative to the image packet base not the section base. */
232struct reloc_record_t {
233
234 s32 vaddr;
235
236 /* expressed in target AUs */
237
238 union {
239 struct {
240#ifndef _BIG_ENDIAN
241 u8 _offset; /* bit offset of rel fld */
242 u8 _fieldsz; /* size of rel fld */
243 u8 _wordsz; /* # bytes containing rel fld */
244 u8 _dum1;
245 u16 _dum2;
246 u16 _type;
247#else
248 unsigned _dum1:8;
249 unsigned _wordsz:8; /* # bytes containing rel fld */
250 unsigned _fieldsz:8; /* size of rel fld */
251 unsigned _offset:8; /* bit offset of rel fld */
252 u16 _type;
253 u16 _dum2;
254#endif
255 } _r_field;
256
257 struct {
258 u32 _spc; /* image packet relative PC */
259#ifndef _BIG_ENDIAN
260 u16 _dum;
261 u16 _type; /* relocation type */
262#else
263 u16 _type; /* relocation type */
264 u16 _dum;
265#endif
266 } _r_spc;
267
268 struct {
269 u32 _uval; /* constant value */
270#ifndef _BIG_ENDIAN
271 u16 _dum;
272 u16 _type; /* relocation type */
273#else
274 u16 _type; /* relocation type */
275 u16 _dum;
276#endif
277 } _r_uval;
278
279 struct {
280 s32 _symndx; /* 32-bit sym tbl index */
281#ifndef _BIG_ENDIAN
282 u16 _disp; /* extra addr encode data */
283 u16 _type; /* relocation type */
284#else
285 u16 _type; /* relocation type */
286 u16 _disp; /* extra addr encode data */
287#endif
288 } _r_sym;
289 } _u_reloc;
290
291};
292
293/* abbreviations for convenience */
294#ifndef TYPE
295#define TYPE _u_reloc._r_sym._type
296#define UVAL _u_reloc._r_uval._uval
297#define SYMNDX _u_reloc._r_sym._symndx
298#define OFFSET _u_reloc._r_field._offset
299#define FIELDSZ _u_reloc._r_field._fieldsz
300#define WORDSZ _u_reloc._r_field._wordsz
301#define R_DISP _u_reloc._r_sym._disp
302#endif
303
304/**************************************************************************** */
305/* */
306/* Important DOFF macros used for file processing */
307/* */
308/**************************************************************************** */
309
310/* DOFF Versions */
311#define DOFF0 0
312
313/* Return the address/size >= to addr that is at a 32-bit boundary */
314/* This assumes that a byte is 8 bits */
315#define DOFF_ALIGN(addr) (((addr) + 3) & ~UINT32_C(3))
316
317/**************************************************************************** */
318/* */
319/* The DOFF section header flags field is laid out as follows: */
320/* */
321/* Bits 0-3 : Section Type */
322/* Bit 4 : Set when section requires target memory to be allocated by DL */
323/* Bit 5 : Set when section requires downloading */
324/* Bits 8-11: Alignment, same as COFF */
325/* */
326/**************************************************************************** */
327
328/* Enum for DOFF section types (bits 0-3 of flag): See dynamic_loader.h */
329
330/* Macros to help processing of sections */
331#define DLOAD_SECT_TYPE(s_hdr) ((s_hdr)->ds_flags & 0xF)
332
333/* DS_ALLOCATE indicates whether a section needs space on the target */
334#define DS_ALLOCATE_MASK 0x10
335#define DS_NEEDS_ALLOCATION(s_hdr) ((s_hdr)->ds_flags & DS_ALLOCATE_MASK)
336
337/* DS_DOWNLOAD indicates that the loader needs to copy bits */
338#define DS_DOWNLOAD_MASK 0x20
339#define DS_NEEDS_DOWNLOAD(s_hdr) ((s_hdr)->ds_flags & DS_DOWNLOAD_MASK)
340
341/* Section alignment requirement in AUs */
342#define DS_ALIGNMENT(ds_flags) (1 << (((ds_flags) >> 8) & 0xF))
343
344#endif /* _DOFF_H */
diff --git a/drivers/staging/tidspbridge/dynload/getsection.c b/drivers/staging/tidspbridge/dynload/getsection.c
new file mode 100644
index 00000000000..029898fc091
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/getsection.c
@@ -0,0 +1,416 @@
1/*
2 * getsection.c
3 *
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5 *
6 * Copyright (C) 2005-2006 Texas Instruments, Inc.
7 *
8 * This package is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15 */
16
17#include <dspbridge/getsection.h>
18#include "header.h"
19
20/*
21 * Error strings
22 */
23static const char readstrm[] = { "Error reading %s from input stream" };
24static const char seek[] = { "Set file position to %d failed" };
25static const char isiz[] = { "Bad image packet size %d" };
26static const char err_checksum[] = { "Checksum failed on %s" };
27
28static const char err_reloc[] = { "dload_get_section unable to read"
29 "sections containing relocation entries"
30};
31
32#if BITS_PER_AU > BITS_PER_BYTE
33static const char err_alloc[] = { "Syms->dload_allocate( %d ) failed" };
34static const char stbl[] = { "Bad string table offset " FMT_UI32 };
35#endif
36
37/*
38 * we use the fact that DOFF section records are shaped just like
39 * ldr_section_info to reduce our section storage usage. These macros
40 * marks the places where that assumption is made
41 */
42#define DOFFSEC_IS_LDRSEC(pdoffsec) ((struct ldr_section_info *)(pdoffsec))
43#define LDRSEC_IS_DOFFSEC(ldrsec) ((struct doff_scnhdr_t *)(ldrsec))
44
45/************************************************************** */
46/********************* SUPPORT FUNCTIONS ********************** */
47/************************************************************** */
48
49#if BITS_PER_AU > BITS_PER_BYTE
50/**************************************************************************
51 * Procedure unpack_sec_name
52 *
53 * Parameters:
54 * dlthis Handle from dload_module_open for this module
55 * soffset Byte offset into the string table
56 * dst Place to store the expanded string
57 *
58 * Effect:
59 * Stores a string from the string table into the destination, expanding
60 * it in the process. Returns a pointer just past the end of the stored
61 * string on success, or NULL on failure.
62 *
63 ************************************************************************ */
64static char *unpack_sec_name(struct dload_state *dlthis, u32 soffset, char *dst)
65{
66 u8 tmp, *src;
67
68 if (soffset >= dlthis->dfile_hdr.df_scn_name_size) {
69 dload_error(dlthis, stbl, soffset);
70 return NULL;
71 }
72 src = (u8 *) dlthis->str_head +
73 (soffset >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE));
74 if (soffset & 1)
75 *dst++ = *src++; /* only 1 character in first word */
76 do {
77 tmp = *src++;
78 *dst = (tmp >> BITS_PER_BYTE)
79 if (!(*dst++))
80 break;
81 } while ((*dst++ = tmp & BYTE_MASK));
82
83 return dst;
84}
85
86/**************************************************************************
87 * Procedure expand_sec_names
88 *
89 * Parameters:
90 * dlthis Handle from dload_module_open for this module
91 *
92 * Effect:
93 * Allocates a buffer, unpacks and copies strings from string table into it.
94 * Stores a pointer to the buffer into a state variable.
95 ************************************************************************* */
96static void expand_sec_names(struct dload_state *dlthis)
97{
98 char *xstrings, *curr, *next;
99 u32 xsize;
100 u16 sec;
101 struct ldr_section_info *shp;
102 /* assume worst-case size requirement */
103 xsize = dlthis->dfile_hdr.df_max_str_len * dlthis->dfile_hdr.df_no_scns;
104 xstrings = (char *)dlthis->mysym->dload_allocate(dlthis->mysym, xsize);
105 if (xstrings == NULL) {
106 dload_error(dlthis, err_alloc, xsize);
107 return;
108 }
109 dlthis->xstrings = xstrings;
110 /* For each sec, copy and expand its name */
111 curr = xstrings;
112 for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
113 shp = DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
114 next = unpack_sec_name(dlthis, *(u32 *) &shp->name, curr);
115 if (next == NULL)
116 break; /* error */
117 shp->name = curr;
118 curr = next;
119 }
120}
121
122#endif
123
124/************************************************************** */
125/********************* EXPORTED FUNCTIONS ********************* */
126/************************************************************** */
127
128/**************************************************************************
129 * Procedure dload_module_open
130 *
131 * Parameters:
132 * module The input stream that supplies the module image
133 * syms Host-side malloc/free and error reporting functions.
134 * Other methods are unused.
135 *
136 * Effect:
137 * Reads header information from a dynamic loader module using the
138 specified
139 * stream object, and returns a handle for the module information. This
140 * handle may be used in subsequent query calls to obtain information
141 * contained in the module.
142 *
143 * Returns:
144 * NULL if an error is encountered, otherwise a module handle for use
145 * in subsequent operations.
146 ************************************************************************* */
147void *dload_module_open(struct dynamic_loader_stream *module,
148 struct dynamic_loader_sym *syms)
149{
150 struct dload_state *dlthis; /* internal state for this call */
151 unsigned *dp, sz;
152 u32 sec_start;
153#if BITS_PER_AU <= BITS_PER_BYTE
154 u16 sec;
155#endif
156
157 /* Check that mandatory arguments are present */
158 if (!module || !syms) {
159 if (syms != NULL)
160 dload_syms_error(syms, "Required parameter is NULL");
161
162 return NULL;
163 }
164
165 dlthis = (struct dload_state *)
166 syms->dload_allocate(syms, sizeof(struct dload_state));
167 if (!dlthis) {
168 /* not enough storage */
169 dload_syms_error(syms, "Can't allocate module info");
170 return NULL;
171 }
172
173 /* clear our internal state */
174 dp = (unsigned *)dlthis;
175 for (sz = sizeof(struct dload_state) / sizeof(unsigned);
176 sz > 0; sz -= 1)
177 *dp++ = 0;
178
179 dlthis->strm = module;
180 dlthis->mysym = syms;
181
182 /* read in the doff image and store in our state variable */
183 dload_headers(dlthis);
184
185 if (!dlthis->dload_errcount)
186 dload_strings(dlthis, true);
187
188 /* skip ahead past the unread portion of the string table */
189 sec_start = sizeof(struct doff_filehdr_t) +
190 sizeof(struct doff_verify_rec_t) +
191 BYTE_TO_HOST(DOFF_ALIGN(dlthis->dfile_hdr.df_strtab_size));
192
193 if (dlthis->strm->set_file_posn(dlthis->strm, sec_start) != 0) {
194 dload_error(dlthis, seek, sec_start);
195 return NULL;
196 }
197
198 if (!dlthis->dload_errcount)
199 dload_sections(dlthis);
200
201 if (dlthis->dload_errcount) {
202 dload_module_close(dlthis); /* errors, blow off our state */
203 dlthis = NULL;
204 return NULL;
205 }
206#if BITS_PER_AU > BITS_PER_BYTE
207 /* Expand all section names from the string table into the */
208 /* state variable, and convert section names from a relative */
209 /* string table offset to a pointers to the expanded string. */
210 expand_sec_names(dlthis);
211#else
212 /* Convert section names from a relative string table offset */
213 /* to a pointer into the string table. */
214 for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
215 struct ldr_section_info *shp =
216 DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
217 shp->name = dlthis->str_head + *(u32 *) &shp->name;
218 }
219#endif
220
221 return dlthis;
222}
223
224/***************************************************************************
225 * Procedure dload_get_section_info
226 *
227 * Parameters:
228 * minfo Handle from dload_module_open for this module
229 * sectionName Pointer to the string name of the section desired
230 * sectionInfo Address of a section info structure pointer to be
231 * initialized
232 *
233 * Effect:
234 * Finds the specified section in the module information, and initializes
235 * the provided struct ldr_section_info pointer.
236 *
237 * Returns:
238 * true for success, false for section not found
239 ************************************************************************* */
240int dload_get_section_info(void *minfo, const char *sectionName,
241 const struct ldr_section_info **const sectionInfo)
242{
243 struct dload_state *dlthis;
244 struct ldr_section_info *shp;
245 u16 sec;
246
247 dlthis = (struct dload_state *)minfo;
248 if (!dlthis)
249 return false;
250
251 for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
252 shp = DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
253 if (strcmp(sectionName, shp->name) == 0) {
254 *sectionInfo = shp;
255 return true;
256 }
257 }
258
259 return false;
260}
261
262#define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
263#define REVERSE_REORDER_MAP(rawmap) ((rawmap) ^ 0x3030303)
264
265/**************************************************************************
266 * Procedure dload_get_section
267 *
268 * Parameters:
269 * minfo Handle from dload_module_open for this module
270 * sectionInfo Pointer to a section info structure for the desired
271 * section
272 * sectionData Buffer to contain the section initialized data
273 *
274 * Effect:
275 * Copies the initialized data for the specified section into the
276 * supplied buffer.
277 *
278 * Returns:
279 * true for success, false for section not found
280 ************************************************************************* */
281int dload_get_section(void *minfo,
282 const struct ldr_section_info *sectionInfo,
283 void *sectionData)
284{
285 struct dload_state *dlthis;
286 u32 pos;
287 struct doff_scnhdr_t *sptr = NULL;
288 s32 nip;
289 struct image_packet_t ipacket;
290 s32 ipsize;
291 u32 checks;
292 s8 *dest = (s8 *) sectionData;
293
294 dlthis = (struct dload_state *)minfo;
295 if (!dlthis)
296 return false;
297 sptr = LDRSEC_IS_DOFFSEC(sectionInfo);
298 if (sptr == NULL)
299 return false;
300
301 /* skip ahead to the start of the first packet */
302 pos = BYTE_TO_HOST(DOFF_ALIGN((u32) sptr->ds_first_pkt_offset));
303 if (dlthis->strm->set_file_posn(dlthis->strm, pos) != 0) {
304 dload_error(dlthis, seek, pos);
305 return false;
306 }
307
308 nip = sptr->ds_nipacks;
309 while ((nip -= 1) >= 0) { /* for each packet */
310 /* get the fixed header bits */
311 if (dlthis->strm->read_buffer(dlthis->strm, &ipacket,
312 IPH_SIZE) != IPH_SIZE) {
313 dload_error(dlthis, readstrm, "image packet");
314 return false;
315 }
316 /* reorder the header if need be */
317 if (dlthis->reorder_map)
318 dload_reorder(&ipacket, IPH_SIZE, dlthis->reorder_map);
319
320 /* Now read the packet image bits. Note: round the size up to
321 * the next multiple of 4 bytes; this is what checksum
322 * routines want. */
323 ipsize = BYTE_TO_HOST(DOFF_ALIGN(ipacket.packet_size));
324 if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) {
325 dload_error(dlthis, isiz, ipsize);
326 return false;
327 }
328 if (dlthis->strm->read_buffer
329 (dlthis->strm, dest, ipsize) != ipsize) {
330 dload_error(dlthis, readstrm, "image packet");
331 return false;
332 }
333 /* reorder the bytes if need be */
334#if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
335 if (dlthis->reorder_map)
336 dload_reorder(dest, ipsize, dlthis->reorder_map);
337
338 checks = dload_checksum(dest, ipsize);
339#else
340 if (dlthis->dfile_hdr.df_byte_reshuffle !=
341 TARGET_ORDER(REORDER_MAP(BYTE_RESHUFFLE_VALUE))) {
342 /* put image bytes in big-endian order, not PC order */
343 dload_reorder(dest, ipsize,
344 TARGET_ORDER(dlthis->
345 dfile_hdr.df_byte_reshuffle));
346 }
347#if TARGET_AU_BITS > 8
348 checks = dload_reverse_checksum16(dest, ipsize);
349#else
350 checks = dload_reverse_checksum(dest, ipsize);
351#endif
352#endif
353 checks += dload_checksum(&ipacket, IPH_SIZE);
354
355 /* NYI: unable to handle relocation entries here. Reloc
356 * entries referring to fields that span the packet boundaries
357 * may result in packets of sizes that are not multiple of
358 * 4 bytes. Our checksum implementation works on 32-bit words
359 * only. */
360 if (ipacket.num_relocs != 0) {
361 dload_error(dlthis, err_reloc, ipsize);
362 return false;
363 }
364
365 if (~checks) {
366 dload_error(dlthis, err_checksum, "image packet");
367 return false;
368 }
369
370 /*Advance destination ptr by the size of the just-read packet */
371 dest += ipsize;
372 }
373
374 return true;
375}
376
377/***************************************************************************
378 * Procedure dload_module_close
379 *
380 * Parameters:
381 * minfo Handle from dload_module_open for this module
382 *
383 * Effect:
384 * Releases any storage associated with the module handle. On return,
385 * the module handle is invalid.
386 *
387 * Returns:
388 * Zero for success. On error, the number of errors detected is returned.
389 * Individual errors are reported using syms->error_report(), where syms was
390 * an argument to dload_module_open
391 ************************************************************************* */
392void dload_module_close(void *minfo)
393{
394 struct dload_state *dlthis;
395
396 dlthis = (struct dload_state *)minfo;
397 if (!dlthis)
398 return;
399
400 if (dlthis->str_head)
401 dlthis->mysym->dload_deallocate(dlthis->mysym,
402 dlthis->str_head);
403
404 if (dlthis->sect_hdrs)
405 dlthis->mysym->dload_deallocate(dlthis->mysym,
406 dlthis->sect_hdrs);
407
408#if BITS_PER_AU > BITS_PER_BYTE
409 if (dlthis->xstrings)
410 dlthis->mysym->dload_deallocate(dlthis->mysym,
411 dlthis->xstrings);
412
413#endif
414
415 dlthis->mysym->dload_deallocate(dlthis->mysym, dlthis);
416}
diff --git a/drivers/staging/tidspbridge/dynload/header.h b/drivers/staging/tidspbridge/dynload/header.h
new file mode 100644
index 00000000000..5cef3600157
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/header.h
@@ -0,0 +1,55 @@
1/*
2 * header.h
3 *
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5 *
6 * Copyright (C) 2005-2006 Texas Instruments, Inc.
7 *
8 * This package is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15 */
16
17#define TRUE 1
18#define FALSE 0
19#ifndef NULL
20#define NULL 0
21#endif
22
23#include <linux/string.h>
24#define DL_STRCMP strcmp
25
26/* maximum parenthesis nesting in relocation stack expressions */
27#define STATIC_EXPR_STK_SIZE 10
28
29#include <linux/types.h>
30
31#include "doff.h"
32#include <dspbridge/dynamic_loader.h>
33#include "params.h"
34#include "dload_internal.h"
35#include "reloc_table.h"
36
37/*
38 * Plausibility limits
39 *
40 * These limits are imposed upon the input DOFF file as a check for validity.
41 * They are hard limits, in that the load will fail if they are exceeded.
42 * The numbers selected are arbitrary, in that the loader implementation does
43 * not require these limits.
44 */
45
46/* maximum number of bytes in string table */
47#define MAX_REASONABLE_STRINGTAB (0x100000)
48/* maximum number of code,data,etc. sections */
49#define MAX_REASONABLE_SECTIONS (200)
50/* maximum number of linker symbols */
51#define MAX_REASONABLE_SYMBOLS (100000)
52
53/* shift count to align F_BIG with DLOAD_LITTLE */
54#define ALIGN_COFF_ENDIANNESS 7
55#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 00000000000..a216bb131a4
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/module_list.h
@@ -0,0 +1,159 @@
1/*
2 * dspbridge/mpu_driver/src/dynload/module_list.h
3 *
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5 *
6 * Copyright (C) 2008 Texas Instruments, Inc.
7 *
8 * This package is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15 */
16
17/*
18 * This C header file gives the layout of the data structure created by the
19 * dynamic loader to describe the set of modules loaded into the DSP.
20 *
21 * Linked List Structure:
22 * ----------------------
23 * The data structure defined here is a singly-linked list. The list
24 * represents the set of modules which are currently loaded in the DSP memory.
25 * The first entry in the list is a header record which contains a flag
26 * representing the state of the list. The rest of the entries in the list
27 * are module records.
28 *
29 * Global symbol _DLModules designates the first record in the list (i.e. the
30 * header record). This symbol must be defined in any program that wishes to
31 * use DLLview plug-in.
32 *
33 * String Representation:
34 * ----------------------
35 * The string names of the module and its sections are stored in a block of
36 * memory which follows the module record itself. The strings are ordered:
37 * module name first, followed by section names in order from the first
38 * section to the last. String names are tightly packed arrays of 8-bit
39 * characters (two characters per 16-bit word on the C55x). Strings are
40 * zero-byte-terminated.
41 *
42 * Creating and updating the list:
43 * -------------------------------
44 * Upon loading a new module into the DSP memory the dynamic loader inserts a
45 * new module record as the first module record in the list. The fields of
46 * this module record are initialized to reflect the properties of the module.
47 * The dynamic loader does NOT increment the flag/counter in the list's header
48 * record.
49 *
50 * Upon unloading a module from the DSP memory the dynamic loader removes the
51 * module's record from this list. The dynamic loader also increments the
52 * flag/counter in the list's header record to indicate that the list has been
53 * changed.
54 */
55
56#ifndef _MODULE_LIST_H_
57#define _MODULE_LIST_H_
58
59#include <linux/types.h>
60
61/* Global pointer to the modules_header structure */
62#define MODULES_HEADER "_DLModules"
63#define MODULES_HEADER_NO_UNDERSCORE "DLModules"
64
65/* Initial version number */
66#define INIT_VERSION 1
67
68/* Verification number -- to be recorded in each module record */
69#define VERIFICATION 0x79
70
71/* forward declarations */
72struct dll_module;
73struct dll_sect;
74
75/* the first entry in the list is the modules_header record;
76 * its address is contained in the global _DLModules pointer */
77struct modules_header {
78
79 /*
80 * Address of the first dll_module record in the list or NULL.
81 * Note: for C55x this is a word address (C55x data is
82 * word-addressable)
83 */
84 u32 first_module;
85
86 /* Combined storage size (in target addressable units) of the
87 * dll_module record which follows this header record, or zero
88 * if the list is empty. This size includes the module's string table.
89 * Note: for C55x the unit is a 16-bit word */
90 u16 first_module_size;
91
92 /* Counter is incremented whenever a module record is removed from
93 * the list */
94 u16 update_flag;
95
96};
97
98/* for each 32-bits in above structure, a bitmap, LSB first, whose bits are:
99 * 0 => a 32-bit value, 1 => 2 16-bit values */
100/* swapping bitmap for type modules_header */
101#define MODULES_HEADER_BITMAP 0x2
102
103/* information recorded about each section in a module */
104struct dll_sect {
105
106 /* Load-time address of the section.
107 * Note: for C55x this is a byte address for program sections, and
108 * a word address for data sections. C55x program memory is
109 * byte-addressable, while data memory is word-addressable. */
110 u32 sect_load_adr;
111
112 /* Run-time address of the section.
113 * Note 1: for C55x this is a byte address for program sections, and
114 * a word address for data sections.
115 * Note 2: for C55x two most significant bits of this field indicate
116 * the section type: '00' for a code section, '11' for a data section
117 * (C55 addresses are really only 24-bits wide). */
118 u32 sect_run_adr;
119
120};
121
122/* the rest of the entries in the list are module records */
123struct dll_module {
124
125 /* Address of the next dll_module record in the list, or 0 if this is
126 * the last record in the list.
127 * Note: for C55x this is a word address (C55x data is
128 * word-addressable) */
129 u32 next_module;
130
131 /* Combined storage size (in target addressable units) of the
132 * dll_module record which follows this one, or zero if this is the
133 * last record in the list. This size includes the module's string
134 * table.
135 * Note: for C55x the unit is a 16-bit word. */
136 u16 next_module_size;
137
138 /* version number of the tooling; set to INIT_VERSION for Phase 1 */
139 u16 version;
140
141 /* the verification word; set to VERIFICATION */
142 u16 verification;
143
144 /* Number of sections in the sects array */
145 u16 num_sects;
146
147 /* Module's "unique" id; copy of the timestamp from the host
148 * COFF file */
149 u32 timestamp;
150
151 /* Array of num_sects elements of the module's section records */
152 struct dll_sect sects[1];
153};
154
155/* for each 32 bits in above structure, a bitmap, LSB first, whose bits are:
156 * 0 => a 32-bit value, 1 => 2 16-bit values */
157#define DLL_MODULE_BITMAP 0x6 /* swapping bitmap for type dll_module */
158
159#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 00000000000..d797fcd3b66
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/params.h
@@ -0,0 +1,226 @@
1/*
2 * params.h
3 *
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5 *
6 * This file defines host and target properties for all machines
7 * supported by the dynamic loader. To be tedious...
8 *
9 * host: the machine on which the dynamic loader runs
10 * target: the machine that the dynamic loader is loading
11 *
12 * Host and target may or may not be the same, depending upon the particular
13 * use.
14 *
15 * Copyright (C) 2005-2006 Texas Instruments, Inc.
16 *
17 * This package is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License version 2 as
19 * published by the Free Software Foundation.
20 *
21 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
23 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
24 */
25
26/******************************************************************************
27 *
28 * Host Properties
29 *
30 **************************************************************************** */
31
32#define BITS_PER_BYTE 8 /* bits in the standard PC/SUN byte */
33#define LOG_BITS_PER_BYTE 3 /* log base 2 of same */
34#define BYTE_MASK ((1U<<BITS_PER_BYTE)-1)
35
36#if defined(__TMS320C55X__) || defined(_TMS320C5XX)
37#define BITS_PER_AU 16
38#define LOG_BITS_PER_AU 4
39 /* use this print string in error messages for uint32_t */
40#define FMT_UI32 "0x%lx"
41#define FMT8_UI32 "%08lx" /* same but no 0x, fixed width field */
42#else
43/* bits in the smallest addressable data storage unit */
44#define BITS_PER_AU 8
45/* log base 2 of the same; useful for shift counts */
46#define LOG_BITS_PER_AU 3
47#define FMT_UI32 "0x%x"
48#define FMT8_UI32 "%08x"
49#endif
50
51/* generic fastest method for swapping bytes and shorts */
52#define SWAP32BY16(zz) (((zz) << 16) | ((zz) >> 16))
53#define SWAP16BY8(zz) (((zz) << 8) | ((zz) >> 8))
54
55/* !! don't be tempted to insert type definitions here; use <stdint.h> !! */
56
57/******************************************************************************
58 *
59 * Target Properties
60 *
61 **************************************************************************** */
62
63/*-------------------------------------------------------------------------- */
64/* TMS320C6x Target Specific Parameters (byte-addressable) */
65/*-------------------------------------------------------------------------- */
66#if TMS32060
67#define MEMORG 0x0L /* Size of configured memory */
68#define MEMSIZE 0x0L /* (full address space) */
69
70#define CINIT_ALIGN 8 /* alignment of cinit record in TDATA AUs */
71#define CINIT_COUNT 4 /* width of count field in TDATA AUs */
72#define CINIT_ADDRESS 4 /* width of address field in TDATA AUs */
73#define CINIT_PAGE_BITS 0 /* Number of LSBs of address that
74 * are page number */
75
76#define LENIENT_SIGNED_RELEXPS 0 /* DOES SIGNED ALLOW MAX UNSIGNED */
77
78#undef TARGET_ENDIANNESS /* may be big or little endian */
79
80/* align a target address to a word boundary */
81#define TARGET_WORD_ALIGN(zz) (((zz) + 0x3) & -0x4)
82#endif
83
84/*--------------------------------------------------------------------------
85 *
86 * DEFAULT SETTINGS and DERIVED PROPERTIES
87 *
88 * This section establishes defaults for values not specified above
89 *-------------------------------------------------------------------------- */
90#ifndef TARGET_AU_BITS
91#define TARGET_AU_BITS 8 /* width of the target addressable unit */
92#define LOG_TARGET_AU_BITS 3 /* log2 of same */
93#endif
94
95#ifndef CINIT_DEFAULT_PAGE
96#define CINIT_DEFAULT_PAGE 0 /* default .cinit page number */
97#endif
98
99#ifndef DATA_RUN2LOAD
100#define DATA_RUN2LOAD(zz) (zz) /* translate data run address to load address */
101#endif
102
103#ifndef DBG_LIST_PAGE
104#define DBG_LIST_PAGE 0 /* page number for .dllview section */
105#endif
106
107#ifndef TARGET_WORD_ALIGN
108/* align a target address to a word boundary */
109#define TARGET_WORD_ALIGN(zz) (zz)
110#endif
111
112#ifndef TDATA_TO_TADDR
113#define TDATA_TO_TADDR(zz) (zz) /* target data address to target AU address */
114#define TADDR_TO_TDATA(zz) (zz) /* target AU address to target data address */
115#define TDATA_AU_BITS TARGET_AU_BITS /* bits per data AU */
116#define LOG_TDATA_AU_BITS LOG_TARGET_AU_BITS
117#endif
118
119/*
120 *
121 * Useful properties and conversions derived from the above
122 *
123 */
124
125/*
126 * Conversions between host and target addresses
127 */
128#if LOG_BITS_PER_AU == LOG_TARGET_AU_BITS
129/* translate target addressable unit to host address */
130#define TADDR_TO_HOST(x) (x)
131/* translate host address to target addressable unit */
132#define HOST_TO_TADDR(x) (x)
133#elif LOG_BITS_PER_AU > LOG_TARGET_AU_BITS
134#define TADDR_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU-LOG_TARGET_AU_BITS))
135#define HOST_TO_TADDR(x) ((x) << (LOG_BITS_PER_AU-LOG_TARGET_AU_BITS))
136#else
137#define TADDR_TO_HOST(x) ((x) << (LOG_TARGET_AU_BITS-LOG_BITS_PER_AU))
138#define HOST_TO_TADDR(x) ((x) >> (LOG_TARGET_AU_BITS-LOG_BITS_PER_AU))
139#endif
140
141#if LOG_BITS_PER_AU == LOG_TDATA_AU_BITS
142/* translate target addressable unit to host address */
143#define TDATA_TO_HOST(x) (x)
144/* translate host address to target addressable unit */
145#define HOST_TO_TDATA(x) (x)
146/* translate host address to target addressable unit, round up */
147#define HOST_TO_TDATA_ROUND(x) (x)
148/* byte offset to host offset, rounded up for TDATA size */
149#define BYTE_TO_HOST_TDATA_ROUND(x) BYTE_TO_HOST_ROUND(x)
150#elif LOG_BITS_PER_AU > LOG_TDATA_AU_BITS
151#define TDATA_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
152#define HOST_TO_TDATA(x) ((x) << (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
153#define HOST_TO_TDATA_ROUND(x) ((x) << (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
154#define BYTE_TO_HOST_TDATA_ROUND(x) BYTE_TO_HOST_ROUND(x)
155#else
156#define TDATA_TO_HOST(x) ((x) << (LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
157#define HOST_TO_TDATA(x) ((x) >> (LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
158#define HOST_TO_TDATA_ROUND(x) (((x) +\
159 (1<<(LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))-1) >>\
160 (LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
161#define BYTE_TO_HOST_TDATA_ROUND(x) (BYTE_TO_HOST((x) +\
162 (1<<(LOG_TDATA_AU_BITS-LOG_BITS_PER_BYTE))-1) &\
163 -(TDATA_AU_BITS/BITS_PER_AU))
164#endif
165
166/*
167 * Input in DOFF format is always expresed in bytes, regardless of loading host
168 * so we wind up converting from bytes to target and host units even when the
169 * host is not a byte machine.
170 */
171#if LOG_BITS_PER_AU == LOG_BITS_PER_BYTE
172#define BYTE_TO_HOST(x) (x)
173#define BYTE_TO_HOST_ROUND(x) (x)
174#define HOST_TO_BYTE(x) (x)
175#elif LOG_BITS_PER_AU >= LOG_BITS_PER_BYTE
176#define BYTE_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
177#define BYTE_TO_HOST_ROUND(x) ((x + (BITS_PER_AU/BITS_PER_BYTE-1)) >>\
178 (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
179#define HOST_TO_BYTE(x) ((x) << (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
180#else
181/* lets not try to deal with sub-8-bit byte machines */
182#endif
183
184#if LOG_TARGET_AU_BITS == LOG_BITS_PER_BYTE
185/* translate target addressable unit to byte address */
186#define TADDR_TO_BYTE(x) (x)
187/* translate byte address to target addressable unit */
188#define BYTE_TO_TADDR(x) (x)
189#elif LOG_TARGET_AU_BITS > LOG_BITS_PER_BYTE
190#define TADDR_TO_BYTE(x) ((x) << (LOG_TARGET_AU_BITS-LOG_BITS_PER_BYTE))
191#define BYTE_TO_TADDR(x) ((x) >> (LOG_TARGET_AU_BITS-LOG_BITS_PER_BYTE))
192#else
193/* lets not try to deal with sub-8-bit byte machines */
194#endif
195
196#ifdef _BIG_ENDIAN
197#define HOST_ENDIANNESS 1
198#else
199#define HOST_ENDIANNESS 0
200#endif
201
202#ifdef TARGET_ENDIANNESS
203#define TARGET_ENDIANNESS_DIFFERS(rtend) (HOST_ENDIANNESS^TARGET_ENDIANNESS)
204#elif HOST_ENDIANNESS
205#define TARGET_ENDIANNESS_DIFFERS(rtend) (!(rtend))
206#else
207#define TARGET_ENDIANNESS_DIFFERS(rtend) (rtend)
208#endif
209
210/* the unit in which we process target image data */
211#if TARGET_AU_BITS <= 8
212typedef u8 tgt_au_t;
213#elif TARGET_AU_BITS <= 16
214typedef u16 tgt_au_t;
215#else
216typedef u32 tgt_au_t;
217#endif
218
219/* size of that unit */
220#if TARGET_AU_BITS < BITS_PER_AU
221#define TGTAU_BITS BITS_PER_AU
222#define LOG_TGTAU_BITS LOG_BITS_PER_AU
223#else
224#define TGTAU_BITS TARGET_AU_BITS
225#define LOG_TGTAU_BITS LOG_TARGET_AU_BITS
226#endif
diff --git a/drivers/staging/tidspbridge/dynload/reloc.c b/drivers/staging/tidspbridge/dynload/reloc.c
new file mode 100644
index 00000000000..316a38c2a1f
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/reloc.c
@@ -0,0 +1,484 @@
1/*
2 * reloc.c
3 *
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5 *
6 * Copyright (C) 2005-2006 Texas Instruments, Inc.
7 *
8 * This package is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15 */
16
17#include "header.h"
18
19#if TMS32060
20/* the magic symbol for the start of BSS */
21static const char bsssymbol[] = { ".bss" };
22#endif
23
24#if TMS32060
25#include "reloc_table_c6000.c"
26#endif
27
28#if TMS32060
29/* From coff.h - ignore these relocation operations */
30#define R_C60ALIGN 0x76 /* C60: Alignment info for compressor */
31#define R_C60FPHEAD 0x77 /* C60: Explicit assembly directive */
32#define R_C60NOCMP 0x100 /* C60: Don't compress this code scn */
33#endif
34
35/**************************************************************************
36 * Procedure dload_unpack
37 *
38 * Parameters:
39 * data pointer to storage unit containing lowest host address of
40 * image data
41 * fieldsz Size of bit field, 0 < fieldsz <= sizeof(rvalue)*BITS_PER_AU
42 * offset Offset from LSB, 0 <= offset < BITS_PER_AU
43 * sgn Signedness of the field (ROP_SGN, ROP_UNS, ROP_MAX, ROP_ANY)
44 *
45 * Effect:
46 * Extracts the specified field and returns it.
47 ************************************************************************* */
48rvalue dload_unpack(struct dload_state *dlthis, tgt_au_t * data, int fieldsz,
49 int offset, unsigned sgn)
50{
51 register rvalue objval;
52 register int shift, direction;
53 register tgt_au_t *dp = data;
54
55 fieldsz -= 1; /* avoid nastiness with 32-bit shift of 32-bit value */
56 /* * collect up enough bits to contain the desired field */
57 if (TARGET_BIG_ENDIAN) {
58 dp += (fieldsz + offset) >> LOG_TGTAU_BITS;
59 direction = -1;
60 } else
61 direction = 1;
62 objval = *dp >> offset;
63 shift = TGTAU_BITS - offset;
64 while (shift <= fieldsz) {
65 dp += direction;
66 objval += (rvalue) *dp << shift;
67 shift += TGTAU_BITS;
68 }
69
70 /* * sign or zero extend the value appropriately */
71 if (sgn == ROP_UNS)
72 objval &= (2 << fieldsz) - 1;
73 else {
74 shift = sizeof(rvalue) * BITS_PER_AU - 1 - fieldsz;
75 objval = (objval << shift) >> shift;
76 }
77
78 return objval;
79
80} /* dload_unpack */
81
82/**************************************************************************
83 * Procedure dload_repack
84 *
85 * Parameters:
86 * val Value to insert
87 * data Pointer to storage unit containing lowest host address of
88 * image data
89 * fieldsz Size of bit field, 0 < fieldsz <= sizeof(rvalue)*BITS_PER_AU
90 * offset Offset from LSB, 0 <= offset < BITS_PER_AU
91 * sgn Signedness of the field (ROP_SGN, ROP_UNS, ROP_MAX, ROP_ANY)
92 *
93 * Effect:
94 * Stuffs the specified value in the specified field. Returns 0 for
95 * success
96 * or 1 if the value will not fit in the specified field according to the
97 * specified signedness rule.
98 ************************************************************************* */
99static const unsigned char ovf_limit[] = { 1, 2, 2 };
100
101int dload_repack(struct dload_state *dlthis, rvalue val, tgt_au_t * data,
102 int fieldsz, int offset, unsigned sgn)
103{
104 register urvalue objval, mask;
105 register int shift, direction;
106 register tgt_au_t *dp = data;
107
108 fieldsz -= 1; /* avoid nastiness with 32-bit shift of 32-bit value */
109 /* clip the bits */
110 mask = ((UINT32_C(2) << fieldsz) - 1);
111 objval = (val & mask);
112 /* * store the bits through the specified mask */
113 if (TARGET_BIG_ENDIAN) {
114 dp += (fieldsz + offset) >> LOG_TGTAU_BITS;
115 direction = -1;
116 } else
117 direction = 1;
118
119 /* insert LSBs */
120 *dp = (*dp & ~(mask << offset)) + (objval << offset);
121 shift = TGTAU_BITS - offset;
122 /* align mask and objval with AU boundary */
123 objval >>= shift;
124 mask >>= shift;
125
126 while (mask) {
127 dp += direction;
128 *dp = (*dp & ~mask) + objval;
129 objval >>= TGTAU_BITS;
130 mask >>= TGTAU_BITS;
131 }
132
133 /*
134 * check for overflow
135 */
136 if (sgn) {
137 unsigned tmp = (val >> fieldsz) + (sgn & 0x1);
138 if (tmp > ovf_limit[sgn - 1])
139 return 1;
140 }
141 return 0;
142
143} /* dload_repack */
144
145/* lookup table for the scaling amount in a C6x instruction */
146#if TMS32060
147#define SCALE_BITS 4 /* there are 4 bits in the scale field */
148#define SCALE_MASK 0x7 /* we really only use the bottom 3 bits */
149static const u8 c60_scale[SCALE_MASK + 1] = {
150 1, 0, 0, 0, 1, 1, 2, 2
151};
152#endif
153
154/**************************************************************************
155 * Procedure dload_relocate
156 *
157 * Parameters:
158 * data Pointer to base of image data
159 * rp Pointer to relocation operation
160 *
161 * Effect:
162 * Performs the specified relocation operation
163 ************************************************************************* */
164void dload_relocate(struct dload_state *dlthis, tgt_au_t * data,
165 struct reloc_record_t *rp, bool * tramps_genereted,
166 bool second_pass)
167{
168 rvalue val, reloc_amt, orig_val = 0;
169 unsigned int fieldsz = 0;
170 unsigned int offset = 0;
171 unsigned int reloc_info = 0;
172 unsigned int reloc_action = 0;
173 register int rx = 0;
174 rvalue *stackp = NULL;
175 int top;
176 struct local_symbol *svp = NULL;
177#ifdef RFV_SCALE
178 unsigned int scale = 0;
179#endif
180 struct image_packet_t *img_pkt = NULL;
181
182 /* The image packet data struct is only used during first pass
183 * relocation in the event that a trampoline is needed. 2nd pass
184 * relocation doesn't guarantee that data is coming from an
185 * image_packet_t structure. See cload.c, dload_data for how img_data is
186 * set. If that changes this needs to be updated!!! */
187 if (second_pass == false)
188 img_pkt = (struct image_packet_t *)((u8 *) data -
189 sizeof(struct
190 image_packet_t));
191
192 rx = HASH_FUNC(rp->TYPE);
193 while (rop_map1[rx] != rp->TYPE) {
194 rx = HASH_L(rop_map2[rx]);
195 if (rx < 0) {
196#if TMS32060
197 switch (rp->TYPE) {
198 case R_C60ALIGN:
199 case R_C60NOCMP:
200 case R_C60FPHEAD:
201 /* Ignore these reloc types and return */
202 break;
203 default:
204 /* Unknown reloc type, print error and return */
205 dload_error(dlthis, "Bad coff operator 0x%x",
206 rp->TYPE);
207 }
208#else
209 dload_error(dlthis, "Bad coff operator 0x%x", rp->TYPE);
210#endif
211 return;
212 }
213 }
214 rx = HASH_I(rop_map2[rx]);
215 if ((rx < (sizeof(rop_action) / sizeof(u16)))
216 && (rx < (sizeof(rop_info) / sizeof(u16))) && (rx > 0)) {
217 reloc_action = rop_action[rx];
218 reloc_info = rop_info[rx];
219 } else {
220 dload_error(dlthis, "Buffer Overflow - Array Index Out "
221 "of Bounds");
222 }
223
224 /* Compute the relocation amount for the referenced symbol, if any */
225 reloc_amt = rp->UVAL;
226 if (RFV_SYM(reloc_info)) { /* relocation uses a symbol reference */
227 /* If this is first pass, use the module local symbol table,
228 * else use the trampoline symbol table. */
229 if (second_pass == false) {
230 if ((u32) rp->SYMNDX < dlthis->dfile_hdr.df_no_syms) {
231 /* real symbol reference */
232 svp = &dlthis->local_symtab[rp->SYMNDX];
233 reloc_amt = (RFV_SYM(reloc_info) == ROP_SYMD) ?
234 svp->delta : svp->value;
235 }
236 /* reloc references current section */
237 else if (rp->SYMNDX == -1) {
238 reloc_amt = (RFV_SYM(reloc_info) == ROP_SYMD) ?
239 dlthis->delta_runaddr :
240 dlthis->image_secn->run_addr;
241 }
242 }
243 }
244 /* relocation uses a symbol reference */
245 /* Handle stack adjustment */
246 val = 0;
247 top = RFV_STK(reloc_info);
248 if (top) {
249 top += dlthis->relstkidx - RSTK_UOP;
250 if (top >= STATIC_EXPR_STK_SIZE) {
251 dload_error(dlthis,
252 "Expression stack overflow in %s at offset "
253 FMT_UI32, dlthis->image_secn->name,
254 rp->vaddr + dlthis->image_offset);
255 return;
256 }
257 val = dlthis->relstk[dlthis->relstkidx];
258 dlthis->relstkidx = top;
259 stackp = &dlthis->relstk[top];
260 }
261 /* Derive field position and size, if we need them */
262 if (reloc_info & ROP_RW) { /* read or write action in our future */
263 fieldsz = RFV_WIDTH(reloc_action);
264 if (fieldsz) { /* field info from table */
265 offset = RFV_POSN(reloc_action);
266 if (TARGET_BIG_ENDIAN)
267 /* make sure vaddr is the lowest target
268 * address containing bits */
269 rp->vaddr += RFV_BIGOFF(reloc_info);
270 } else { /* field info from relocation op */
271 fieldsz = rp->FIELDSZ;
272 offset = rp->OFFSET;
273 if (TARGET_BIG_ENDIAN)
274 /* make sure vaddr is the lowest target
275 address containing bits */
276 rp->vaddr += (rp->WORDSZ - offset - fieldsz)
277 >> LOG_TARGET_AU_BITS;
278 }
279 data = (tgt_au_t *) ((char *)data + TADDR_TO_HOST(rp->vaddr));
280 /* compute lowest host location of referenced data */
281#if BITS_PER_AU > TARGET_AU_BITS
282 /* conversion from target address to host address may lose
283 address bits; add loss to offset */
284 if (TARGET_BIG_ENDIAN) {
285 offset += -((rp->vaddr << LOG_TARGET_AU_BITS) +
286 offset + fieldsz) &
287 (BITS_PER_AU - TARGET_AU_BITS);
288 } else {
289 offset += (rp->vaddr << LOG_TARGET_AU_BITS) &
290 (BITS_PER_AU - 1);
291 }
292#endif
293#ifdef RFV_SCALE
294 scale = RFV_SCALE(reloc_info);
295#endif
296 }
297 /* read the object value from the current image, if so ordered */
298 if (reloc_info & ROP_R) {
299 /* relocation reads current image value */
300 val = dload_unpack(dlthis, data, fieldsz, offset,
301 RFV_SIGN(reloc_info));
302 /* Save off the original value in case the relo overflows and
303 * we can trampoline it. */
304 orig_val = val;
305
306#ifdef RFV_SCALE
307 val <<= scale;
308#endif
309 }
310 /* perform the necessary arithmetic */
311 switch (RFV_ACTION(reloc_action)) { /* relocation actions */
312 case RACT_VAL:
313 break;
314 case RACT_ASGN:
315 val = reloc_amt;
316 break;
317 case RACT_ADD:
318 val += reloc_amt;
319 break;
320 case RACT_PCR:
321 /*-----------------------------------------------------------
322 * Handle special cases of jumping from absolute sections
323 * (special reloc type) or to absolute destination
324 * (symndx == -1). In either case, set the appropriate
325 * relocation amount to 0.
326 *----------------------------------------------------------- */
327 if (rp->SYMNDX == -1)
328 reloc_amt = 0;
329 val += reloc_amt - dlthis->delta_runaddr;
330 break;
331 case RACT_ADDISP:
332 val += rp->R_DISP + reloc_amt;
333 break;
334 case RACT_ASGPC:
335 val = dlthis->image_secn->run_addr + reloc_amt;
336 break;
337 case RACT_PLUS:
338 if (stackp != NULL)
339 val += *stackp;
340 break;
341 case RACT_SUB:
342 if (stackp != NULL)
343 val = *stackp - val;
344 break;
345 case RACT_NEG:
346 val = -val;
347 break;
348 case RACT_MPY:
349 if (stackp != NULL)
350 val *= *stackp;
351 break;
352 case RACT_DIV:
353 if (stackp != NULL)
354 val = *stackp / val;
355 break;
356 case RACT_MOD:
357 if (stackp != NULL)
358 val = *stackp % val;
359 break;
360 case RACT_SR:
361 if (val >= sizeof(rvalue) * BITS_PER_AU)
362 val = 0;
363 else if (stackp != NULL)
364 val = (urvalue) *stackp >> val;
365 break;
366 case RACT_ASR:
367 if (val >= sizeof(rvalue) * BITS_PER_AU)
368 val = sizeof(rvalue) * BITS_PER_AU - 1;
369 else if (stackp != NULL)
370 val = *stackp >> val;
371 break;
372 case RACT_SL:
373 if (val >= sizeof(rvalue) * BITS_PER_AU)
374 val = 0;
375 else if (stackp != NULL)
376 val = *stackp << val;
377 break;
378 case RACT_AND:
379 if (stackp != NULL)
380 val &= *stackp;
381 break;
382 case RACT_OR:
383 if (stackp != NULL)
384 val |= *stackp;
385 break;
386 case RACT_XOR:
387 if (stackp != NULL)
388 val ^= *stackp;
389 break;
390 case RACT_NOT:
391 val = ~val;
392 break;
393#if TMS32060
394 case RACT_C6SECT:
395 /* actually needed address of secn containing symbol */
396 if (svp != NULL) {
397 if (rp->SYMNDX >= 0)
398 if (svp->secnn > 0)
399 reloc_amt = dlthis->ldr_sections
400 [svp->secnn - 1].run_addr;
401 }
402 /* !!! FALL THRU !!! */
403 case RACT_C6BASE:
404 if (dlthis->bss_run_base == 0) {
405 struct dynload_symbol *symp;
406 symp = dlthis->mysym->find_matching_symbol
407 (dlthis->mysym, bsssymbol);
408 /* lookup value of global BSS base */
409 if (symp)
410 dlthis->bss_run_base = symp->value;
411 else
412 dload_error(dlthis,
413 "Global BSS base referenced in %s "
414 "offset" FMT_UI32 " but not "
415 "defined",
416 dlthis->image_secn->name,
417 rp->vaddr + dlthis->image_offset);
418 }
419 reloc_amt -= dlthis->bss_run_base;
420 /* !!! FALL THRU !!! */
421 case RACT_C6DSPL:
422 /* scale factor determined by 3 LSBs of field */
423 scale = c60_scale[val & SCALE_MASK];
424 offset += SCALE_BITS;
425 fieldsz -= SCALE_BITS;
426 val >>= SCALE_BITS; /* ignore the scale field hereafter */
427 val <<= scale;
428 val += reloc_amt; /* do the usual relocation */
429 if (((1 << scale) - 1) & val)
430 dload_error(dlthis,
431 "Unaligned reference in %s offset "
432 FMT_UI32, dlthis->image_secn->name,
433 rp->vaddr + dlthis->image_offset);
434 break;
435#endif
436 } /* relocation actions */
437 /* * Put back result as required */
438 if (reloc_info & ROP_W) { /* relocation writes image value */
439#ifdef RFV_SCALE
440 val >>= scale;
441#endif
442 if (dload_repack(dlthis, val, data, fieldsz, offset,
443 RFV_SIGN(reloc_info))) {
444 /* Check to see if this relo can be trampolined,
445 * but only in first phase relocation. 2nd phase
446 * relocation cannot trampoline. */
447 if ((second_pass == false) &&
448 (dload_tramp_avail(dlthis, rp) == true)) {
449
450 /* Before generating the trampoline, restore
451 * the value to its original so the 2nd pass
452 * relo will work. */
453 dload_repack(dlthis, orig_val, data, fieldsz,
454 offset, RFV_SIGN(reloc_info));
455 if (!dload_tramp_generate(dlthis,
456 (dlthis->image_secn -
457 dlthis->ldr_sections),
458 dlthis->image_offset,
459 img_pkt, rp)) {
460 dload_error(dlthis,
461 "Failed to "
462 "generate trampoline for "
463 "bit overflow");
464 dload_error(dlthis,
465 "Relocation val " FMT_UI32
466 " overflows %d bits in %s "
467 "offset " FMT_UI32, val,
468 fieldsz,
469 dlthis->image_secn->name,
470 dlthis->image_offset +
471 rp->vaddr);
472 } else
473 *tramps_genereted = true;
474 } else {
475 dload_error(dlthis, "Relocation value "
476 FMT_UI32 " overflows %d bits in %s"
477 " offset " FMT_UI32, val, fieldsz,
478 dlthis->image_secn->name,
479 dlthis->image_offset + rp->vaddr);
480 }
481 }
482 } else if (top)
483 *stackp = val;
484} /* 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 00000000000..6aab03d4668
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/reloc_table.h
@@ -0,0 +1,102 @@
1/*
2 * reloc_table.h
3 *
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5 *
6 * Copyright (C) 2005-2006 Texas Instruments, Inc.
7 *
8 * This package is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15 */
16
17#ifndef _RELOC_TABLE_H_
18#define _RELOC_TABLE_H_
19/*
20 * Table of relocation operator properties
21 */
22#include <linux/types.h>
23
24/* How does this relocation operation access the program image? */
25#define ROP_N 0 /* does not access image */
26#define ROP_R 1 /* read from image */
27#define ROP_W 2 /* write to image */
28#define ROP_RW 3 /* read from and write to image */
29
30/* For program image access, what are the overflow rules for the bit field? */
31/* Beware! Procedure repack depends on this encoding */
32#define ROP_ANY 0 /* no overflow ever, just truncate the value */
33#define ROP_SGN 1 /* signed field */
34#define ROP_UNS 2 /* unsigned field */
35#define ROP_MAX 3 /* allow maximum range of either signed or unsigned */
36
37/* How does the relocation operation use the symbol reference */
38#define ROP_IGN 0 /* no symbol is referenced */
39#define ROP_LIT 0 /* use rp->UVAL literal field */
40#define ROP_SYM 1 /* symbol value is used in relocation */
41#define ROP_SYMD 2 /* delta value vs last link is used */
42
43/* How does the reloc op use the stack? */
44#define RSTK_N 0 /* Does not use */
45#define RSTK_POP 1 /* Does a POP */
46#define RSTK_UOP 2 /* Unary op, stack position unaffected */
47#define RSTK_PSH 3 /* Does a push */
48
49/*
50 * Computational actions performed by the dynamic loader
51 */
52enum dload_actions {
53 /* don't alter the current val (from stack or mem fetch) */
54 RACT_VAL,
55 /* set value to reference amount (from symbol reference) */
56 RACT_ASGN,
57 RACT_ADD, /* add reference to value */
58 RACT_PCR, /* add reference minus PC delta to value */
59 RACT_ADDISP, /* add reference plus R_DISP */
60 RACT_ASGPC, /* set value to section addr plus reference */
61
62 RACT_PLUS, /* stack + */
63 RACT_SUB, /* stack - */
64 RACT_NEG, /* stack unary - */
65
66 RACT_MPY, /* stack * */
67 RACT_DIV, /* stack / */
68 RACT_MOD, /* stack % */
69
70 RACT_SR, /* stack unsigned >> */
71 RACT_ASR, /* stack signed >> */
72 RACT_SL, /* stack << */
73 RACT_AND, /* stack & */
74 RACT_OR, /* stack | */
75 RACT_XOR, /* stack ^ */
76 RACT_NOT, /* stack ~ */
77 RACT_C6SECT, /* for C60 R_SECT op */
78 RACT_C6BASE, /* for C60 R_BASE op */
79 RACT_C6DSPL, /* for C60 scaled 15-bit displacement */
80 RACT_PCR23T /* for ARM Thumb long branch */
81};
82
83/*
84 * macros used to extract values
85 */
86#define RFV_POSN(aaa) ((aaa) & 0xF)
87#define RFV_WIDTH(aaa) (((aaa) >> 4) & 0x3F)
88#define RFV_ACTION(aaa) ((aaa) >> 10)
89
90#define RFV_SIGN(iii) (((iii) >> 2) & 0x3)
91#define RFV_SYM(iii) (((iii) >> 4) & 0x3)
92#define RFV_STK(iii) (((iii) >> 6) & 0x3)
93#define RFV_ACCS(iii) ((iii) & 0x3)
94
95#if (TMS32060)
96#define RFV_SCALE(iii) ((iii) >> 11)
97#define RFV_BIGOFF(iii) (((iii) >> 8) & 0x7)
98#else
99#define RFV_BIGOFF(iii) ((iii) >> 8)
100#endif
101
102#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 00000000000..8ae3b38f398
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/reloc_table_c6000.c
@@ -0,0 +1,257 @@
1/*
2 * reloc_table_c6000.c
3 *
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5 *
6 * Copyright (C) 2005-2006 Texas Instruments, Inc.
7 *
8 * This package is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15 */
16
17/* Tables generated for c6000 */
18
19#define HASH_FUNC(zz) (((((zz) + 1) * UINT32_C(1845)) >> 11) & 63)
20#define HASH_L(zz) ((zz) >> 8)
21#define HASH_I(zz) ((zz) & 0xFF)
22
23static const u16 rop_map1[] = {
24 0,
25 1,
26 2,
27 20,
28 4,
29 5,
30 6,
31 15,
32 80,
33 81,
34 82,
35 83,
36 84,
37 85,
38 86,
39 87,
40 17,
41 18,
42 19,
43 21,
44 16,
45 16394,
46 16404,
47 65535,
48 65535,
49 65535,
50 65535,
51 65535,
52 65535,
53 32,
54 65535,
55 65535,
56 65535,
57 65535,
58 65535,
59 65535,
60 40,
61 112,
62 113,
63 65535,
64 16384,
65 16385,
66 16386,
67 16387,
68 16388,
69 16389,
70 16390,
71 16391,
72 16392,
73 16393,
74 16395,
75 16396,
76 16397,
77 16398,
78 16399,
79 16400,
80 16401,
81 16402,
82 16403,
83 16405,
84 16406,
85 65535,
86 65535,
87 65535
88};
89
90static const s16 rop_map2[] = {
91 -256,
92 -255,
93 -254,
94 -245,
95 -253,
96 -252,
97 -251,
98 -250,
99 -241,
100 -240,
101 -239,
102 -238,
103 -237,
104 -236,
105 1813,
106 5142,
107 -248,
108 -247,
109 778,
110 -244,
111 -249,
112 -221,
113 -211,
114 -1,
115 -1,
116 -1,
117 -1,
118 -1,
119 -1,
120 -243,
121 -1,
122 -1,
123 -1,
124 -1,
125 -1,
126 -1,
127 -242,
128 -233,
129 -232,
130 -1,
131 -231,
132 -230,
133 -229,
134 -228,
135 -227,
136 -226,
137 -225,
138 -224,
139 -223,
140 5410,
141 -220,
142 -219,
143 -218,
144 -217,
145 -216,
146 -215,
147 -214,
148 -213,
149 5676,
150 -210,
151 -209,
152 -1,
153 -1,
154 -1
155};
156
157static const u16 rop_action[] = {
158 2560,
159 2304,
160 2304,
161 2432,
162 2432,
163 2560,
164 2176,
165 2304,
166 2560,
167 3200,
168 3328,
169 3584,
170 3456,
171 2304,
172 4208,
173 20788,
174 21812,
175 3415,
176 3245,
177 2311,
178 4359,
179 19764,
180 2311,
181 3191,
182 3280,
183 6656,
184 7680,
185 8704,
186 9728,
187 10752,
188 11776,
189 12800,
190 13824,
191 14848,
192 15872,
193 16896,
194 17920,
195 18944,
196 0,
197 0,
198 0,
199 0,
200 1536,
201 1536,
202 1536,
203 5632,
204 512,
205 0
206};
207
208static const u16 rop_info[] = {
209 0,
210 35,
211 35,
212 35,
213 35,
214 35,
215 35,
216 35,
217 35,
218 39,
219 39,
220 39,
221 39,
222 35,
223 34,
224 283,
225 299,
226 4135,
227 4391,
228 291,
229 33059,
230 283,
231 295,
232 4647,
233 4135,
234 64,
235 64,
236 128,
237 64,
238 64,
239 64,
240 64,
241 64,
242 64,
243 64,
244 64,
245 64,
246 128,
247 201,
248 197,
249 74,
250 70,
251 208,
252 196,
253 200,
254 192,
255 192,
256 66
257};
diff --git a/drivers/staging/tidspbridge/dynload/tramp.c b/drivers/staging/tidspbridge/dynload/tramp.c
new file mode 100644
index 00000000000..7b593fc2b69
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/tramp.c
@@ -0,0 +1,1143 @@
1/*
2 * tramp.c
3 *
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5 *
6 * Copyright (C) 2009 Texas Instruments, Inc.
7 *
8 * This package is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15 */
16
17#include "header.h"
18
19#if TMS32060
20#include "tramp_table_c6000.c"
21#endif
22
23#define MAX_RELOS_PER_PASS 4
24
25/*
26 * Function: priv_tramp_sect_tgt_alloc
27 * Description: Allocate target memory for the trampoline section. The
28 * target mem size is easily obtained as the next available address.
29 */
30static int priv_tramp_sect_tgt_alloc(struct dload_state *dlthis)
31{
32 int ret_val = 0;
33 struct ldr_section_info *sect_info;
34
35 /* Populate the trampoline loader section and allocate it on the
36 * target. The section name is ALWAYS the first string in the final
37 * string table for trampolines. The trampoline section is always
38 * 1 beyond the total number of allocated sections. */
39 sect_info = &dlthis->ldr_sections[dlthis->allocated_secn_count];
40
41 sect_info->name = dlthis->tramp.final_string_table;
42 sect_info->size = dlthis->tramp.tramp_sect_next_addr;
43 sect_info->context = 0;
44 sect_info->type =
45 (4 << 8) | DLOAD_TEXT | DS_ALLOCATE_MASK | DS_DOWNLOAD_MASK;
46 sect_info->page = 0;
47 sect_info->run_addr = 0;
48 sect_info->load_addr = 0;
49 ret_val = dlthis->myalloc->dload_allocate(dlthis->myalloc,
50 sect_info,
51 DS_ALIGNMENT
52 (sect_info->type));
53
54 if (ret_val == 0)
55 dload_error(dlthis, "Failed to allocate target memory for"
56 " trampoline");
57
58 return ret_val;
59}
60
61/*
62 * Function: priv_h2a
63 * Description: Helper function to convert a hex value to its ASCII
64 * representation. Used for trampoline symbol name generation.
65 */
66static u8 priv_h2a(u8 value)
67{
68 if (value > 0xF)
69 return 0xFF;
70
71 if (value <= 9)
72 value += 0x30;
73 else
74 value += 0x37;
75
76 return value;
77}
78
79/*
80 * Function: priv_tramp_sym_gen_name
81 * Description: Generate a trampoline symbol name (ASCII) using the value
82 * of the symbol. This places the new name into the user buffer.
83 * The name is fixed in length and of the form: __$dbTR__xxxxxxxx
84 * (where "xxxxxxxx" is the hex value.
85 */
86static void priv_tramp_sym_gen_name(u32 value, char *dst)
87{
88 u32 i;
89 volatile char *prefix = TRAMP_SYM_PREFIX;
90 volatile char *dst_local = dst;
91 u8 tmp;
92
93 /* Clear out the destination, including the ending NULL */
94 for (i = 0; i < (TRAMP_SYM_PREFIX_LEN + TRAMP_SYM_HEX_ASCII_LEN); i++)
95 *(dst_local + i) = 0;
96
97 /* Copy the prefix to start */
98 for (i = 0; i < strlen(TRAMP_SYM_PREFIX); i++) {
99 *dst_local = *(prefix + i);
100 dst_local++;
101 }
102
103 /* Now convert the value passed in to a string equiv of the hex */
104 for (i = 0; i < sizeof(value); i++) {
105#ifndef _BIG_ENDIAN
106 tmp = *(((u8 *) &value) + (sizeof(value) - 1) - i);
107 *dst_local = priv_h2a((tmp & 0xF0) >> 4);
108 dst_local++;
109 *dst_local = priv_h2a(tmp & 0x0F);
110 dst_local++;
111#else
112 tmp = *(((u8 *) &value) + i);
113 *dst_local = priv_h2a((tmp & 0xF0) >> 4);
114 dst_local++;
115 *dst_local = priv_h2a(tmp & 0x0F);
116 dst_local++;
117#endif
118 }
119
120 /* NULL terminate */
121 *dst_local = 0;
122}
123
124/*
125 * Function: priv_tramp_string_create
126 * Description: Create a new string specific to the trampoline loading and add
127 * it to the trampoline string list. This list contains the
128 * trampoline section name and trampoline point symbols.
129 */
130static struct tramp_string *priv_tramp_string_create(struct dload_state *dlthis,
131 u32 str_len, char *str)
132{
133 struct tramp_string *new_string = NULL;
134 u32 i;
135
136 /* Create a new string object with the specified size. */
137 new_string =
138 (struct tramp_string *)dlthis->mysym->dload_allocate(dlthis->mysym,
139 (sizeof
140 (struct
141 tramp_string)
142 + str_len +
143 1));
144 if (new_string != NULL) {
145 /* Clear the string first. This ensures the ending NULL is
146 * present and the optimizer won't touch it. */
147 for (i = 0; i < (sizeof(struct tramp_string) + str_len + 1);
148 i++)
149 *((u8 *) new_string + i) = 0;
150
151 /* Add this string to our virtual table by assigning it the
152 * next index and pushing it to the tail of the list. */
153 new_string->index = dlthis->tramp.tramp_string_next_index;
154 dlthis->tramp.tramp_string_next_index++;
155 dlthis->tramp.tramp_string_size += str_len + 1;
156
157 new_string->next = NULL;
158 if (dlthis->tramp.string_head == NULL)
159 dlthis->tramp.string_head = new_string;
160 else
161 dlthis->tramp.string_tail->next = new_string;
162
163 dlthis->tramp.string_tail = new_string;
164
165 /* Copy the string over to the new object */
166 for (i = 0; i < str_len; i++)
167 new_string->str[i] = str[i];
168 }
169
170 return new_string;
171}
172
173/*
174 * Function: priv_tramp_string_find
175 * Description: Walk the trampoline string list and find a match for the
176 * provided string. If not match is found, NULL is returned.
177 */
178static struct tramp_string *priv_tramp_string_find(struct dload_state *dlthis,
179 char *str)
180{
181 struct tramp_string *cur_str = NULL;
182 struct tramp_string *ret_val = NULL;
183 u32 i;
184 u32 str_len = strlen(str);
185
186 for (cur_str = dlthis->tramp.string_head;
187 (ret_val == NULL) && (cur_str != NULL); cur_str = cur_str->next) {
188 /* If the string lengths aren't equal, don't bother
189 * comparing */
190 if (str_len != strlen(cur_str->str))
191 continue;
192
193 /* Walk the strings until one of them ends */
194 for (i = 0; i < str_len; i++) {
195 /* If they don't match in the current position then
196 * break out now, no sense in continuing to look at
197 * this string. */
198 if (str[i] != cur_str->str[i])
199 break;
200 }
201
202 if (i == str_len)
203 ret_val = cur_str;
204 }
205
206 return ret_val;
207}
208
209/*
210 * Function: priv_string_tbl_finalize
211 * Description: Flatten the trampoline string list into a table of NULL
212 * terminated strings. This is the same format of string table
213 * as used by the COFF/DOFF file.
214 */
215static int priv_string_tbl_finalize(struct dload_state *dlthis)
216{
217 int ret_val = 0;
218 struct tramp_string *cur_string;
219 char *cur_loc;
220 char *tmp;
221
222 /* Allocate enough space for all strings that have been created. The
223 * table is simply all strings concatenated together will NULL
224 * endings. */
225 dlthis->tramp.final_string_table =
226 (char *)dlthis->mysym->dload_allocate(dlthis->mysym,
227 dlthis->tramp.
228 tramp_string_size);
229 if (dlthis->tramp.final_string_table != NULL) {
230 /* We got our buffer, walk the list and release the nodes as*
231 * we go */
232 cur_loc = dlthis->tramp.final_string_table;
233 cur_string = dlthis->tramp.string_head;
234 while (cur_string != NULL) {
235 /* Move the head/tail pointers */
236 dlthis->tramp.string_head = cur_string->next;
237 if (dlthis->tramp.string_tail == cur_string)
238 dlthis->tramp.string_tail = NULL;
239
240 /* Copy the string contents */
241 for (tmp = cur_string->str;
242 *tmp != '\0'; tmp++, cur_loc++)
243 *cur_loc = *tmp;
244
245 /* Pick up the NULL termination since it was missed by
246 * breaking using it to end the above loop. */
247 *cur_loc = '\0';
248 cur_loc++;
249
250 /* Free the string node, we don't need it any more. */
251 dlthis->mysym->dload_deallocate(dlthis->mysym,
252 cur_string);
253
254 /* Move our pointer to the next one */
255 cur_string = dlthis->tramp.string_head;
256 }
257
258 /* Update our return value to success */
259 ret_val = 1;
260 } else
261 dload_error(dlthis, "Failed to allocate trampoline "
262 "string table");
263
264 return ret_val;
265}
266
267/*
268 * Function: priv_tramp_sect_alloc
269 * Description: Virtually allocate space from the trampoline section. This
270 * function returns the next offset within the trampoline section
271 * that is available and moved the next available offset by the
272 * requested size. NO TARGET ALLOCATION IS DONE AT THIS TIME.
273 */
274static u32 priv_tramp_sect_alloc(struct dload_state *dlthis, u32 tramp_size)
275{
276 u32 ret_val;
277
278 /* If the next available address is 0, this is our first allocation.
279 * Create a section name string to go into the string table . */
280 if (dlthis->tramp.tramp_sect_next_addr == 0) {
281 dload_syms_error(dlthis->mysym, "*** WARNING *** created "
282 "dynamic TRAMPOLINE section for module %s",
283 dlthis->str_head);
284 }
285
286 /* Reserve space for the new trampoline */
287 ret_val = dlthis->tramp.tramp_sect_next_addr;
288 dlthis->tramp.tramp_sect_next_addr += tramp_size;
289 return ret_val;
290}
291
292/*
293 * Function: priv_tramp_sym_create
294 * Description: Allocate and create a new trampoline specific symbol and add
295 * it to the trampoline symbol list. These symbols will include
296 * trampoline points as well as the external symbols they
297 * reference.
298 */
299static struct tramp_sym *priv_tramp_sym_create(struct dload_state *dlthis,
300 u32 str_index,
301 struct local_symbol *tmp_sym)
302{
303 struct tramp_sym *new_sym = NULL;
304 u32 i;
305
306 /* Allocate new space for the symbol in the symbol table. */
307 new_sym =
308 (struct tramp_sym *)dlthis->mysym->dload_allocate(dlthis->mysym,
309 sizeof(struct tramp_sym));
310 if (new_sym != NULL) {
311 for (i = 0; i != sizeof(struct tramp_sym); i++)
312 *((char *)new_sym + i) = 0;
313
314 /* Assign this symbol the next symbol index for easier
315 * reference later during relocation. */
316 new_sym->index = dlthis->tramp.tramp_sym_next_index;
317 dlthis->tramp.tramp_sym_next_index++;
318
319 /* Populate the symbol information. At this point any
320 * trampoline symbols will be the offset location, not the
321 * final. Copy over the symbol info to start, then be sure to
322 * get the string index from the trampoline string table. */
323 new_sym->sym_info = *tmp_sym;
324 new_sym->str_index = str_index;
325
326 /* Push the new symbol to the tail of the symbol table list */
327 new_sym->next = NULL;
328 if (dlthis->tramp.symbol_head == NULL)
329 dlthis->tramp.symbol_head = new_sym;
330 else
331 dlthis->tramp.symbol_tail->next = new_sym;
332
333 dlthis->tramp.symbol_tail = new_sym;
334 }
335
336 return new_sym;
337}
338
339/*
340 * Function: priv_tramp_sym_get
341 * Description: Search for the symbol with the matching string index (from
342 * the trampoline string table) and return the trampoline
343 * symbol object, if found. Otherwise return NULL.
344 */
345static struct tramp_sym *priv_tramp_sym_get(struct dload_state *dlthis,
346 u32 string_index)
347{
348 struct tramp_sym *sym_found = NULL;
349
350 /* Walk the symbol table list and search vs. the string index */
351 for (sym_found = dlthis->tramp.symbol_head;
352 sym_found != NULL; sym_found = sym_found->next) {
353 if (sym_found->str_index == string_index)
354 break;
355 }
356
357 return sym_found;
358}
359
360/*
361 * Function: priv_tramp_sym_find
362 * Description: Search for a trampoline symbol based on the string name of
363 * the symbol. Return the symbol object, if found, otherwise
364 * return NULL.
365 */
366static struct tramp_sym *priv_tramp_sym_find(struct dload_state *dlthis,
367 char *string)
368{
369 struct tramp_sym *sym_found = NULL;
370 struct tramp_string *str_found = NULL;
371
372 /* First, search for the string, then search for the sym based on the
373 string index. */
374 str_found = priv_tramp_string_find(dlthis, string);
375 if (str_found != NULL)
376 sym_found = priv_tramp_sym_get(dlthis, str_found->index);
377
378 return sym_found;
379}
380
381/*
382 * Function: priv_tramp_sym_finalize
383 * Description: Allocate a flat symbol table for the trampoline section,
384 * put each trampoline symbol into the table, adjust the
385 * symbol value based on the section address on the target and
386 * free the trampoline symbol list nodes.
387 */
388static int priv_tramp_sym_finalize(struct dload_state *dlthis)
389{
390 int ret_val = 0;
391 struct tramp_sym *cur_sym;
392 struct ldr_section_info *tramp_sect =
393 &dlthis->ldr_sections[dlthis->allocated_secn_count];
394 struct local_symbol *new_sym;
395
396 /* Allocate a table to hold a flattened version of all symbols
397 * created. */
398 dlthis->tramp.final_sym_table =
399 (struct local_symbol *)dlthis->mysym->dload_allocate(dlthis->mysym,
400 (sizeof(struct local_symbol) * dlthis->tramp.
401 tramp_sym_next_index));
402 if (dlthis->tramp.final_sym_table != NULL) {
403 /* Walk the list of all symbols, copy it over to the flattened
404 * table. After it has been copied, the node can be freed as
405 * it is no longer needed. */
406 new_sym = dlthis->tramp.final_sym_table;
407 cur_sym = dlthis->tramp.symbol_head;
408 while (cur_sym != NULL) {
409 /* Pop it off the list */
410 dlthis->tramp.symbol_head = cur_sym->next;
411 if (cur_sym == dlthis->tramp.symbol_tail)
412 dlthis->tramp.symbol_tail = NULL;
413
414 /* Copy the symbol contents into the flat table */
415 *new_sym = cur_sym->sym_info;
416
417 /* Now finaize the symbol. If it is in the tramp
418 * section, we need to adjust for the section start.
419 * If it is external then we don't need to adjust at
420 * all.
421 * NOTE: THIS CODE ASSUMES THAT THE TRAMPOLINE IS
422 * REFERENCED LIKE A CALL TO AN EXTERNAL SO VALUE AND
423 * DELTA ARE THE SAME. SEE THE FUNCTION dload_symbols
424 * WHERE DN_UNDEF IS HANDLED FOR MORE REFERENCE. */
425 if (new_sym->secnn < 0) {
426 new_sym->value += tramp_sect->load_addr;
427 new_sym->delta = new_sym->value;
428 }
429
430 /* Let go of the symbol node */
431 dlthis->mysym->dload_deallocate(dlthis->mysym, cur_sym);
432
433 /* Move to the next node */
434 cur_sym = dlthis->tramp.symbol_head;
435 new_sym++;
436 }
437
438 ret_val = 1;
439 } else
440 dload_error(dlthis, "Failed to alloc trampoline sym table");
441
442 return ret_val;
443}
444
445/*
446 * Function: priv_tgt_img_gen
447 * Description: Allocate storage for and copy the target specific image data
448 * and fix up its relocations for the new external symbol. If
449 * a trampoline image packet was successfully created it is added
450 * to the trampoline list.
451 */
452static int priv_tgt_img_gen(struct dload_state *dlthis, u32 base,
453 u32 gen_index, struct tramp_sym *new_ext_sym)
454{
455 struct tramp_img_pkt *new_img_pkt = NULL;
456 u32 i;
457 u32 pkt_size = tramp_img_pkt_size_get();
458 u8 *gen_tbl_entry;
459 u8 *pkt_data;
460 struct reloc_record_t *cur_relo;
461 int ret_val = 0;
462
463 /* Allocate a new image packet and set it up. */
464 new_img_pkt =
465 (struct tramp_img_pkt *)dlthis->mysym->dload_allocate(dlthis->mysym,
466 pkt_size);
467 if (new_img_pkt != NULL) {
468 /* Save the base, this is where it goes in the section */
469 new_img_pkt->base = base;
470
471 /* Copy over the image data and relos from the target table */
472 pkt_data = (u8 *) &new_img_pkt->hdr;
473 gen_tbl_entry = (u8 *) &tramp_gen_info[gen_index];
474 for (i = 0; i < pkt_size; i++) {
475 *pkt_data = *gen_tbl_entry;
476 pkt_data++;
477 gen_tbl_entry++;
478 }
479
480 /* Update the relocations to point to the external symbol */
481 cur_relo =
482 (struct reloc_record_t *)((u8 *) &new_img_pkt->hdr +
483 new_img_pkt->hdr.relo_offset);
484 for (i = 0; i < new_img_pkt->hdr.num_relos; i++)
485 cur_relo[i].SYMNDX = new_ext_sym->index;
486
487 /* Add it to the trampoline list. */
488 new_img_pkt->next = dlthis->tramp.tramp_pkts;
489 dlthis->tramp.tramp_pkts = new_img_pkt;
490
491 ret_val = 1;
492 }
493
494 return ret_val;
495}
496
497/*
498 * Function: priv_pkt_relo
499 * Description: Take the provided image data and the collection of relocations
500 * for it and perform the relocations. Note that all relocations
501 * at this stage are considered SECOND PASS since the original
502 * image has already been processed in the first pass. This means
503 * TRAMPOLINES ARE TREATED AS 2ND PASS even though this is really
504 * the first (and only) relocation that will be performed on them.
505 */
506static int priv_pkt_relo(struct dload_state *dlthis, tgt_au_t * data,
507 struct reloc_record_t *rp[], u32 relo_count)
508{
509 int ret_val = 1;
510 u32 i;
511 bool tmp;
512
513 /* Walk through all of the relos and process them. This function is
514 * the equivalent of relocate_packet() from cload.c, but specialized
515 * for trampolines and 2nd phase relocations. */
516 for (i = 0; i < relo_count; i++)
517 dload_relocate(dlthis, data, rp[i], &tmp, true);
518
519 return ret_val;
520}
521
522/*
523 * Function: priv_tramp_pkt_finalize
524 * Description: Walk the list of all trampoline packets and finalize them.
525 * Each trampoline image packet will be relocated now that the
526 * trampoline section has been allocated on the target. Once
527 * all of the relocations are done the trampoline image data
528 * is written into target memory and the trampoline packet
529 * is freed: it is no longer needed after this point.
530 */
531static int priv_tramp_pkt_finalize(struct dload_state *dlthis)
532{
533 int ret_val = 1;
534 struct tramp_img_pkt *cur_pkt = NULL;
535 struct reloc_record_t *relos[MAX_RELOS_PER_PASS];
536 u32 relos_done;
537 u32 i;
538 struct reloc_record_t *cur_relo;
539 struct ldr_section_info *sect_info =
540 &dlthis->ldr_sections[dlthis->allocated_secn_count];
541
542 /* Walk the list of trampoline packets and relocate each packet. This
543 * function is the trampoline equivalent of dload_data() from
544 * cload.c. */
545 cur_pkt = dlthis->tramp.tramp_pkts;
546 while ((ret_val != 0) && (cur_pkt != NULL)) {
547 /* Remove the pkt from the list */
548 dlthis->tramp.tramp_pkts = cur_pkt->next;
549
550 /* Setup section and image offset information for the relo */
551 dlthis->image_secn = sect_info;
552 dlthis->image_offset = cur_pkt->base;
553 dlthis->delta_runaddr = sect_info->run_addr;
554
555 /* Walk through all relos for the packet */
556 relos_done = 0;
557 cur_relo = (struct reloc_record_t *)((u8 *) &cur_pkt->hdr +
558 cur_pkt->hdr.relo_offset);
559 while (relos_done < cur_pkt->hdr.num_relos) {
560#ifdef ENABLE_TRAMP_DEBUG
561 dload_syms_error(dlthis->mysym,
562 "===> Trampoline %x branches to %x",
563 sect_info->run_addr +
564 dlthis->image_offset,
565 dlthis->
566 tramp.final_sym_table[cur_relo->
567 SYMNDX].value);
568#endif
569
570 for (i = 0;
571 ((i < MAX_RELOS_PER_PASS) &&
572 ((i + relos_done) < cur_pkt->hdr.num_relos)); i++)
573 relos[i] = cur_relo + i;
574
575 /* Do the actual relo */
576 ret_val = priv_pkt_relo(dlthis,
577 (tgt_au_t *) &cur_pkt->payload,
578 relos, i);
579 if (ret_val == 0) {
580 dload_error(dlthis,
581 "Relocation of trampoline pkt at %x"
582 " failed", cur_pkt->base +
583 sect_info->run_addr);
584 break;
585 }
586
587 relos_done += i;
588 cur_relo += i;
589 }
590
591 /* Make sure we didn't hit a problem */
592 if (ret_val != 0) {
593 /* Relos are done for the packet, write it to the
594 * target */
595 ret_val = dlthis->myio->writemem(dlthis->myio,
596 &cur_pkt->payload,
597 sect_info->load_addr +
598 cur_pkt->base,
599 sect_info,
600 BYTE_TO_HOST
601 (cur_pkt->hdr.
602 tramp_code_size));
603 if (ret_val == 0) {
604 dload_error(dlthis,
605 "Write to " FMT_UI32 " failed",
606 sect_info->load_addr +
607 cur_pkt->base);
608 }
609
610 /* Done with the pkt, let it go */
611 dlthis->mysym->dload_deallocate(dlthis->mysym, cur_pkt);
612
613 /* Get the next packet to process */
614 cur_pkt = dlthis->tramp.tramp_pkts;
615 }
616 }
617
618 return ret_val;
619}
620
621/*
622 * Function: priv_dup_pkt_finalize
623 * Description: Walk the list of duplicate image packets and finalize them.
624 * Each duplicate packet will be relocated again for the
625 * relocations that previously failed and have been adjusted
626 * to point at a trampoline. Once all relocations for a packet
627 * have been done, write the packet into target memory. The
628 * duplicate packet and its relocation chain are all freed
629 * after use here as they are no longer needed after this.
630 */
631static int priv_dup_pkt_finalize(struct dload_state *dlthis)
632{
633 int ret_val = 1;
634 struct tramp_img_dup_pkt *cur_pkt;
635 struct tramp_img_dup_relo *cur_relo;
636 struct reloc_record_t *relos[MAX_RELOS_PER_PASS];
637 struct doff_scnhdr_t *sect_hdr = NULL;
638 s32 i;
639
640 /* Similar to the trampoline pkt finalize, this function walks each dup
641 * pkt that was generated and performs all relocations that were
642 * deferred to a 2nd pass. This is the equivalent of dload_data() from
643 * cload.c, but does not need the additional reorder and checksum
644 * processing as it has already been done. */
645 cur_pkt = dlthis->tramp.dup_pkts;
646 while ((ret_val != 0) && (cur_pkt != NULL)) {
647 /* Remove the node from the list, we'll be freeing it
648 * shortly */
649 dlthis->tramp.dup_pkts = cur_pkt->next;
650
651 /* Setup the section and image offset for relocation */
652 dlthis->image_secn = &dlthis->ldr_sections[cur_pkt->secnn];
653 dlthis->image_offset = cur_pkt->offset;
654
655 /* In order to get the delta run address, we need to reference
656 * the original section header. It's a bit ugly, but needed
657 * for relo. */
658 i = (s32) (dlthis->image_secn - dlthis->ldr_sections);
659 sect_hdr = dlthis->sect_hdrs + i;
660 dlthis->delta_runaddr = sect_hdr->ds_paddr;
661
662 /* Walk all relos in the chain and process each. */
663 cur_relo = cur_pkt->relo_chain;
664 while (cur_relo != NULL) {
665 /* Process them a chunk at a time to be efficient */
666 for (i = 0; (i < MAX_RELOS_PER_PASS)
667 && (cur_relo != NULL);
668 i++, cur_relo = cur_relo->next) {
669 relos[i] = &cur_relo->relo;
670 cur_pkt->relo_chain = cur_relo->next;
671 }
672
673 /* Do the actual relo */
674 ret_val = priv_pkt_relo(dlthis,
675 cur_pkt->img_pkt.img_data,
676 relos, i);
677 if (ret_val == 0) {
678 dload_error(dlthis,
679 "Relocation of dup pkt at %x"
680 " failed", cur_pkt->offset +
681 dlthis->image_secn->run_addr);
682 break;
683 }
684
685 /* Release all of these relos, we're done with them */
686 while (i > 0) {
687 dlthis->mysym->dload_deallocate(dlthis->mysym,
688 GET_CONTAINER
689 (relos[i - 1],
690 struct tramp_img_dup_relo,
691 relo));
692 i--;
693 }
694
695 /* DO NOT ADVANCE cur_relo, IT IS ALREADY READY TO
696 * GO! */
697 }
698
699 /* Done with all relos. Make sure we didn't have a problem and
700 * write it out to the target */
701 if (ret_val != 0) {
702 ret_val = dlthis->myio->writemem(dlthis->myio,
703 cur_pkt->img_pkt.
704 img_data,
705 dlthis->image_secn->
706 load_addr +
707 cur_pkt->offset,
708 dlthis->image_secn,
709 BYTE_TO_HOST
710 (cur_pkt->img_pkt.
711 packet_size));
712 if (ret_val == 0) {
713 dload_error(dlthis,
714 "Write to " FMT_UI32 " failed",
715 dlthis->image_secn->load_addr +
716 cur_pkt->offset);
717 }
718
719 dlthis->mysym->dload_deallocate(dlthis->mysym, cur_pkt);
720
721 /* Advance to the next packet */
722 cur_pkt = dlthis->tramp.dup_pkts;
723 }
724 }
725
726 return ret_val;
727}
728
729/*
730 * Function: priv_dup_find
731 * Description: Walk the list of existing duplicate packets and find a
732 * match based on the section number and image offset. Return
733 * the duplicate packet if found, otherwise NULL.
734 */
735static struct tramp_img_dup_pkt *priv_dup_find(struct dload_state *dlthis,
736 s16 secnn, u32 image_offset)
737{
738 struct tramp_img_dup_pkt *cur_pkt = NULL;
739
740 for (cur_pkt = dlthis->tramp.dup_pkts;
741 cur_pkt != NULL; cur_pkt = cur_pkt->next) {
742 if ((cur_pkt->secnn == secnn) &&
743 (cur_pkt->offset == image_offset)) {
744 /* Found a match, break out */
745 break;
746 }
747 }
748
749 return cur_pkt;
750}
751
752/*
753 * Function: priv_img_pkt_dup
754 * Description: Duplicate the original image packet. If this is the first
755 * time this image packet has been seen (based on section number
756 * and image offset), create a new duplicate packet and add it
757 * to the dup packet list. If not, just get the existing one and
758 * update it with the current packet contents (since relocation
759 * on the packet is still ongoing in first pass.) Create a
760 * duplicate of the provided relocation, but update it to point
761 * to the new trampoline symbol. Add the new relocation dup to
762 * the dup packet's relo chain for 2nd pass relocation later.
763 */
764static int priv_img_pkt_dup(struct dload_state *dlthis,
765 s16 secnn, u32 image_offset,
766 struct image_packet_t *ipacket,
767 struct reloc_record_t *rp,
768 struct tramp_sym *new_tramp_sym)
769{
770 struct tramp_img_dup_pkt *dup_pkt = NULL;
771 u32 new_dup_size;
772 s32 i;
773 int ret_val = 0;
774 struct tramp_img_dup_relo *dup_relo = NULL;
775
776 /* Determinne if this image packet is already being tracked in the
777 dup list for other trampolines. */
778 dup_pkt = priv_dup_find(dlthis, secnn, image_offset);
779
780 if (dup_pkt == NULL) {
781 /* This image packet does not exist in our tracking, so create
782 * a new one and add it to the head of the list. */
783 new_dup_size = sizeof(struct tramp_img_dup_pkt) +
784 ipacket->packet_size;
785
786 dup_pkt = (struct tramp_img_dup_pkt *)
787 dlthis->mysym->dload_allocate(dlthis->mysym, new_dup_size);
788 if (dup_pkt != NULL) {
789 /* Save off the section and offset information */
790 dup_pkt->secnn = secnn;
791 dup_pkt->offset = image_offset;
792 dup_pkt->relo_chain = NULL;
793
794 /* Copy the original packet content */
795 dup_pkt->img_pkt = *ipacket;
796 dup_pkt->img_pkt.img_data = (u8 *) (dup_pkt + 1);
797 for (i = 0; i < ipacket->packet_size; i++)
798 *(dup_pkt->img_pkt.img_data + i) =
799 *(ipacket->img_data + i);
800
801 /* Add the packet to the dup list */
802 dup_pkt->next = dlthis->tramp.dup_pkts;
803 dlthis->tramp.dup_pkts = dup_pkt;
804 } else
805 dload_error(dlthis, "Failed to create dup packet!");
806 } else {
807 /* The image packet contents could have changed since
808 * trampoline detection happens during relocation of the image
809 * packets. So, we need to update the image packet contents
810 * before adding relo information. */
811 for (i = 0; i < dup_pkt->img_pkt.packet_size; i++)
812 *(dup_pkt->img_pkt.img_data + i) =
813 *(ipacket->img_data + i);
814 }
815
816 /* Since the previous code may have allocated a new dup packet for us,
817 double check that we actually have one. */
818 if (dup_pkt != NULL) {
819 /* Allocate a new node for the relo chain. Each image packet
820 * can potentially have multiple relocations that cause a
821 * trampoline to be generated. So, we keep them in a chain,
822 * order is not important. */
823 dup_relo = dlthis->mysym->dload_allocate(dlthis->mysym,
824 sizeof(struct tramp_img_dup_relo));
825 if (dup_relo != NULL) {
826 /* Copy the relo contents, adjust for the new
827 * trampoline and add it to the list. */
828 dup_relo->relo = *rp;
829 dup_relo->relo.SYMNDX = new_tramp_sym->index;
830
831 dup_relo->next = dup_pkt->relo_chain;
832 dup_pkt->relo_chain = dup_relo;
833
834 /* That's it, we're done. Make sure we update our
835 * return value to be success since everything finished
836 * ok */
837 ret_val = 1;
838 } else
839 dload_error(dlthis, "Unable to alloc dup relo");
840 }
841
842 return ret_val;
843}
844
845/*
846 * Function: dload_tramp_avail
847 * Description: Check to see if the target supports a trampoline for this type
848 * of relocation. Return true if it does, otherwise false.
849 */
850bool dload_tramp_avail(struct dload_state *dlthis, struct reloc_record_t *rp)
851{
852 bool ret_val = false;
853 u16 map_index;
854 u16 gen_index;
855
856 /* Check type hash vs. target tramp table */
857 map_index = HASH_FUNC(rp->TYPE);
858 gen_index = tramp_map[map_index];
859 if (gen_index != TRAMP_NO_GEN_AVAIL)
860 ret_val = true;
861
862 return ret_val;
863}
864
865/*
866 * Function: dload_tramp_generate
867 * Description: Create a new trampoline for the provided image packet and
868 * relocation causing problems. This will create the trampoline
869 * as well as duplicate/update the image packet and relocation
870 * causing the problem, which will be relo'd again during
871 * finalization.
872 */
873int dload_tramp_generate(struct dload_state *dlthis, s16 secnn,
874 u32 image_offset, struct image_packet_t *ipacket,
875 struct reloc_record_t *rp)
876{
877 u16 map_index;
878 u16 gen_index;
879 int ret_val = 1;
880 char tramp_sym_str[TRAMP_SYM_PREFIX_LEN + TRAMP_SYM_HEX_ASCII_LEN];
881 struct local_symbol *ref_sym;
882 struct tramp_sym *new_tramp_sym;
883 struct tramp_sym *new_ext_sym;
884 struct tramp_string *new_tramp_str;
885 u32 new_tramp_base;
886 struct local_symbol tmp_sym;
887 struct local_symbol ext_tmp_sym;
888
889 /* Hash the relo type to get our generator information */
890 map_index = HASH_FUNC(rp->TYPE);
891 gen_index = tramp_map[map_index];
892 if (gen_index != TRAMP_NO_GEN_AVAIL) {
893 /* If this is the first trampoline, create the section name in
894 * our string table for debug help later. */
895 if (dlthis->tramp.string_head == NULL) {
896 priv_tramp_string_create(dlthis,
897 strlen(TRAMP_SECT_NAME),
898 TRAMP_SECT_NAME);
899 }
900#ifdef ENABLE_TRAMP_DEBUG
901 dload_syms_error(dlthis->mysym,
902 "Trampoline at img loc %x, references %x",
903 dlthis->ldr_sections[secnn].run_addr +
904 image_offset + rp->vaddr,
905 dlthis->local_symtab[rp->SYMNDX].value);
906#endif
907
908 /* Generate the trampoline string, check if already defined.
909 * If the relo symbol index is -1, it means we need the section
910 * info for relo later. To do this we'll dummy up a symbol
911 * with the section delta and run addresses. */
912 if (rp->SYMNDX == -1) {
913 ext_tmp_sym.value =
914 dlthis->ldr_sections[secnn].run_addr;
915 ext_tmp_sym.delta = dlthis->sect_hdrs[secnn].ds_paddr;
916 ref_sym = &ext_tmp_sym;
917 } else
918 ref_sym = &(dlthis->local_symtab[rp->SYMNDX]);
919
920 priv_tramp_sym_gen_name(ref_sym->value, tramp_sym_str);
921 new_tramp_sym = priv_tramp_sym_find(dlthis, tramp_sym_str);
922 if (new_tramp_sym == NULL) {
923 /* If tramp string not defined, create it and a new
924 * string, and symbol for it as well as the original
925 * symbol which caused the trampoline. */
926 new_tramp_str = priv_tramp_string_create(dlthis,
927 strlen
928 (tramp_sym_str),
929 tramp_sym_str);
930 if (new_tramp_str == NULL) {
931 dload_error(dlthis, "Failed to create new "
932 "trampoline string\n");
933 ret_val = 0;
934 } else {
935 /* Allocate tramp section space for the new
936 * tramp from the target */
937 new_tramp_base = priv_tramp_sect_alloc(dlthis,
938 tramp_size_get());
939
940 /* We have a string, create the new symbol and
941 * duplicate the external. */
942 tmp_sym.value = new_tramp_base;
943 tmp_sym.delta = 0;
944 tmp_sym.secnn = -1;
945 tmp_sym.sclass = 0;
946 new_tramp_sym = priv_tramp_sym_create(dlthis,
947 new_tramp_str->
948 index,
949 &tmp_sym);
950
951 new_ext_sym = priv_tramp_sym_create(dlthis, -1,
952 ref_sym);
953
954 if ((new_tramp_sym != NULL) &&
955 (new_ext_sym != NULL)) {
956 /* Call the image generator to get the
957 * new image data and fix up its
958 * relocations for the external
959 * symbol. */
960 ret_val = priv_tgt_img_gen(dlthis,
961 new_tramp_base,
962 gen_index,
963 new_ext_sym);
964
965 /* Add generated image data to tramp
966 * image list */
967 if (ret_val != 1) {
968 dload_error(dlthis, "Failed to "
969 "create img pkt for"
970 " trampoline\n");
971 }
972 } else {
973 dload_error(dlthis, "Failed to create "
974 "new tramp syms "
975 "(%8.8X, %8.8X)\n",
976 new_tramp_sym, new_ext_sym);
977 ret_val = 0;
978 }
979 }
980 }
981
982 /* Duplicate the image data and relo record that caused the
983 * tramp, including update the relo data to point to the tramp
984 * symbol. */
985 if (ret_val == 1) {
986 ret_val = priv_img_pkt_dup(dlthis, secnn, image_offset,
987 ipacket, rp, new_tramp_sym);
988 if (ret_val != 1) {
989 dload_error(dlthis, "Failed to create dup of "
990 "original img pkt\n");
991 }
992 }
993 }
994
995 return ret_val;
996}
997
998/*
999 * Function: dload_tramp_pkt_update
1000 * Description: Update the duplicate copy of this image packet, which the
1001 * trampoline layer is already tracking. This is call is critical
1002 * to make if trampolines were generated anywhere within the
1003 * packet and first pass relo continued on the remainder. The
1004 * trampoline layer needs the updates image data so when 2nd
1005 * pass relo is done during finalize the image packet can be
1006 * written to the target since all relo is done.
1007 */
1008int dload_tramp_pkt_udpate(struct dload_state *dlthis, s16 secnn,
1009 u32 image_offset, struct image_packet_t *ipacket)
1010{
1011 struct tramp_img_dup_pkt *dup_pkt = NULL;
1012 s32 i;
1013 int ret_val = 0;
1014
1015 /* Find the image packet in question, the caller needs us to update it
1016 since a trampoline was previously generated. */
1017 dup_pkt = priv_dup_find(dlthis, secnn, image_offset);
1018 if (dup_pkt != NULL) {
1019 for (i = 0; i < dup_pkt->img_pkt.packet_size; i++)
1020 *(dup_pkt->img_pkt.img_data + i) =
1021 *(ipacket->img_data + i);
1022
1023 ret_val = 1;
1024 } else {
1025 dload_error(dlthis,
1026 "Unable to find existing DUP pkt for %x, offset %x",
1027 secnn, image_offset);
1028
1029 }
1030
1031 return ret_val;
1032}
1033
1034/*
1035 * Function: dload_tramp_finalize
1036 * Description: If any trampolines were created, finalize everything on the
1037 * target by allocating the trampoline section on the target,
1038 * finalizing the trampoline symbols, finalizing the trampoline
1039 * packets (write the new section to target memory) and finalize
1040 * the duplicate packets by doing 2nd pass relo over them.
1041 */
1042int dload_tramp_finalize(struct dload_state *dlthis)
1043{
1044 int ret_val = 1;
1045
1046 if (dlthis->tramp.tramp_sect_next_addr != 0) {
1047 /* Finalize strings into a flat table. This is needed so it
1048 * can be added to the debug string table later. */
1049 ret_val = priv_string_tbl_finalize(dlthis);
1050
1051 /* Do target allocation for section BEFORE finalizing
1052 * symbols. */
1053 if (ret_val != 0)
1054 ret_val = priv_tramp_sect_tgt_alloc(dlthis);
1055
1056 /* Finalize symbols with their correct target information and
1057 * flatten */
1058 if (ret_val != 0)
1059 ret_val = priv_tramp_sym_finalize(dlthis);
1060
1061 /* Finalize all trampoline packets. This performs the
1062 * relocation on the packets as well as writing them to target
1063 * memory. */
1064 if (ret_val != 0)
1065 ret_val = priv_tramp_pkt_finalize(dlthis);
1066
1067 /* Perform a 2nd pass relocation on the dup list. */
1068 if (ret_val != 0)
1069 ret_val = priv_dup_pkt_finalize(dlthis);
1070 }
1071
1072 return ret_val;
1073}
1074
1075/*
1076 * Function: dload_tramp_cleanup
1077 * Description: Release all temporary resources used in the trampoline layer.
1078 * Note that the target memory which may have been allocated and
1079 * written to store the trampolines is NOT RELEASED HERE since it
1080 * is potentially still in use. It is automatically released
1081 * when the module is unloaded.
1082 */
1083void dload_tramp_cleanup(struct dload_state *dlthis)
1084{
1085 struct tramp_info *tramp = &dlthis->tramp;
1086 struct tramp_sym *cur_sym;
1087 struct tramp_string *cur_string;
1088 struct tramp_img_pkt *cur_tramp_pkt;
1089 struct tramp_img_dup_pkt *cur_dup_pkt;
1090 struct tramp_img_dup_relo *cur_dup_relo;
1091
1092 /* If there were no tramps generated, just return */
1093 if (tramp->tramp_sect_next_addr == 0)
1094 return;
1095
1096 /* Destroy all tramp information */
1097 for (cur_sym = tramp->symbol_head;
1098 cur_sym != NULL; cur_sym = tramp->symbol_head) {
1099 tramp->symbol_head = cur_sym->next;
1100 if (tramp->symbol_tail == cur_sym)
1101 tramp->symbol_tail = NULL;
1102
1103 dlthis->mysym->dload_deallocate(dlthis->mysym, cur_sym);
1104 }
1105
1106 if (tramp->final_sym_table != NULL)
1107 dlthis->mysym->dload_deallocate(dlthis->mysym,
1108 tramp->final_sym_table);
1109
1110 for (cur_string = tramp->string_head;
1111 cur_string != NULL; cur_string = tramp->string_head) {
1112 tramp->string_head = cur_string->next;
1113 if (tramp->string_tail == cur_string)
1114 tramp->string_tail = NULL;
1115
1116 dlthis->mysym->dload_deallocate(dlthis->mysym, cur_string);
1117 }
1118
1119 if (tramp->final_string_table != NULL)
1120 dlthis->mysym->dload_deallocate(dlthis->mysym,
1121 tramp->final_string_table);
1122
1123 for (cur_tramp_pkt = tramp->tramp_pkts;
1124 cur_tramp_pkt != NULL; cur_tramp_pkt = tramp->tramp_pkts) {
1125 tramp->tramp_pkts = cur_tramp_pkt->next;
1126 dlthis->mysym->dload_deallocate(dlthis->mysym, cur_tramp_pkt);
1127 }
1128
1129 for (cur_dup_pkt = tramp->dup_pkts;
1130 cur_dup_pkt != NULL; cur_dup_pkt = tramp->dup_pkts) {
1131 tramp->dup_pkts = cur_dup_pkt->next;
1132
1133 for (cur_dup_relo = cur_dup_pkt->relo_chain;
1134 cur_dup_relo != NULL;
1135 cur_dup_relo = cur_dup_pkt->relo_chain) {
1136 cur_dup_pkt->relo_chain = cur_dup_relo->next;
1137 dlthis->mysym->dload_deallocate(dlthis->mysym,
1138 cur_dup_relo);
1139 }
1140
1141 dlthis->mysym->dload_deallocate(dlthis->mysym, cur_dup_pkt);
1142 }
1143}
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 00000000000..e38d631b321
--- /dev/null
+++ b/drivers/staging/tidspbridge/dynload/tramp_table_c6000.c
@@ -0,0 +1,164 @@
1/*
2 * tramp_table_c6000.c
3 *
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5 *
6 * Copyright (C) 2005-2006 Texas Instruments, Inc.
7 *
8 * This package is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15 */
16
17#include "dload_internal.h"
18
19/* These are defined in coff.h, but may not be available on all platforms
20 so we'll go ahead and define them here. */
21#ifndef R_C60LO16
22#define R_C60LO16 0x54 /* C60: MVK Low Half Register */
23#define R_C60HI16 0x55 /* C60: MVKH/MVKLH High Half Register */
24#endif
25
26#define C6X_TRAMP_WORD_COUNT 8
27#define C6X_TRAMP_MAX_RELOS 8
28
29/* THIS HASH FUNCTION MUST MATCH THE ONE IN reloc_table_c6000.c */
30#define HASH_FUNC(zz) (((((zz) + 1) * UINT32_C(1845)) >> 11) & 63)
31
32/* THIS MUST MATCH reloc_record_t FOR A SYMBOL BASED RELO */
33struct c6000_relo_record {
34 s32 vaddr;
35 s32 symndx;
36#ifndef _BIG_ENDIAN
37 u16 disp;
38 u16 type;
39#else
40 u16 type;
41 u16 disp;
42#endif
43};
44
45struct c6000_gen_code {
46 struct tramp_gen_code_hdr hdr;
47 u32 tramp_instrs[C6X_TRAMP_WORD_COUNT];
48 struct c6000_relo_record relos[C6X_TRAMP_MAX_RELOS];
49};
50
51/* Hash mapping for relos that can cause trampolines. */
52static const u16 tramp_map[] = {
53 65535,
54 65535,
55 65535,
56 65535,
57 65535,
58 65535,
59 65535,
60 65535,
61 65535,
62 65535,
63 0,
64 65535,
65 65535,
66 65535,
67 65535,
68 65535,
69 65535,
70 65535,
71 65535,
72 65535,
73 65535,
74 65535,
75 65535,
76 65535,
77 65535,
78 65535,
79 65535,
80 65535,
81 65535,
82 65535,
83 65535,
84 65535,
85 65535,
86 65535,
87 65535,
88 65535,
89 65535,
90 65535,
91 65535,
92 65535,
93 65535,
94 65535,
95 65535,
96 65535,
97 65535,
98 65535,
99 65535,
100 65535,
101 65535,
102 65535,
103 65535,
104 65535,
105 65535,
106 65535,
107 65535,
108 65535,
109 65535,
110 65535,
111 65535,
112 65535,
113 65535,
114 65535,
115 65535,
116 65535
117};
118
119static const struct c6000_gen_code tramp_gen_info[] = {
120 /* Tramp caused by R_C60PCR21 */
121 {
122 /* Header - 8 instructions, 2 relos */
123 {
124 sizeof(u32) * C6X_TRAMP_WORD_COUNT,
125 2,
126 FIELD_OFFSET(struct c6000_gen_code, relos)
127 },
128
129 /* Trampoline instructions */
130 {
131 0x053C54F7, /* STW.D2T2 B10, *sp--[2] */
132 0x0500002A, /* || MVK.S2 <blank>, B10 */
133 0x0500006A, /* MVKH.S2 <blank>, B10 */
134 0x00280362, /* B.S2 B10 */
135 0x053C52E6, /* LDW.D2T2 *++sp[2], B10 */
136 0x00006000, /* NOP 4 */
137 0x00000000, /* NOP */
138 0x00000000 /* NOP */
139 },
140
141 /* Relocations */
142 {
143 {4, 0, 0, R_C60LO16},
144 {8, 0, 0, R_C60HI16},
145 {0, 0, 0, 0x0000},
146 {0, 0, 0, 0x0000},
147 {0, 0, 0, 0x0000},
148 {0, 0, 0, 0x0000},
149 {0, 0, 0, 0x0000},
150 {0, 0, 0, 0x0000}
151 }
152 }
153};
154
155/* TARGET SPECIFIC FUNCTIONS THAT MUST BE DEFINED */
156static u32 tramp_size_get(void)
157{
158 return sizeof(u32) * C6X_TRAMP_WORD_COUNT;
159}
160
161static u32 tramp_img_pkt_size_get(void)
162{
163 return sizeof(struct c6000_gen_code);
164}