mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-26 22:24:09 +08:00
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>
This commit is contained in:
parent
6a88a4fe09
commit
26f8db7d2e
1960
drivers/staging/tidspbridge/dynload/cload.c
Normal file
1960
drivers/staging/tidspbridge/dynload/cload.c
Normal file
File diff suppressed because it is too large
Load Diff
351
drivers/staging/tidspbridge/dynload/dload_internal.h
Normal file
351
drivers/staging/tidspbridge/dynload/dload_internal.h
Normal file
@ -0,0 +1,351 @@
|
||||
/*
|
||||
* dload_internal.h
|
||||
*
|
||||
* DSP-BIOS Bridge driver support functions for TI OMAP processors.
|
||||
*
|
||||
* Copyright (C) 2005-2006 Texas Instruments, Inc.
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef _DLOAD_INTERNAL_
|
||||
#define _DLOAD_INTERNAL_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* Internal state definitions for the dynamic loader
|
||||
*/
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
/* type used for relocation intermediate results */
|
||||
typedef s32 rvalue;
|
||||
|
||||
/* unsigned version of same; must have at least as many bits */
|
||||
typedef u32 urvalue;
|
||||
|
||||
/*
|
||||
* Dynamic loader configuration constants
|
||||
*/
|
||||
/* error issued if input has more sections than this limit */
|
||||
#define REASONABLE_SECTION_LIMIT 100
|
||||
|
||||
/* (Addressable unit) value used to clear BSS section */
|
||||
#define DLOAD_FILL_BSS 0
|
||||
|
||||
/*
|
||||
* Reorder maps explained (?)
|
||||
*
|
||||
* The doff file format defines a 32-bit pattern used to determine the
|
||||
* byte order of an image being read. That value is
|
||||
* BYTE_RESHUFFLE_VALUE == 0x00010203
|
||||
* For purposes of the reorder routine, we would rather have the all-is-OK
|
||||
* for 32-bits pattern be 0x03020100. This first macro makes the
|
||||
* translation from doff file header value to MAP value: */
|
||||
#define REORDER_MAP(rawmap) ((rawmap) ^ 0x3030303)
|
||||
/* This translation is made in dload_headers. Thereafter, the all-is-OK
|
||||
* value for the maps stored in dlthis is REORDER_MAP(BYTE_RESHUFFLE_VALUE).
|
||||
* But sadly, not all bits of the doff file are 32-bit integers.
|
||||
* The notable exceptions are strings and image bits.
|
||||
* Strings obey host byte order: */
|
||||
#if defined(_BIG_ENDIAN)
|
||||
#define HOST_BYTE_ORDER(cookedmap) ((cookedmap) ^ 0x3030303)
|
||||
#else
|
||||
#define HOST_BYTE_ORDER(cookedmap) (cookedmap)
|
||||
#endif
|
||||
/* Target bits consist of target AUs (could be bytes, or 16-bits,
|
||||
* or 32-bits) stored as an array in host order. A target order
|
||||
* map is defined by: */
|
||||
#if !defined(_BIG_ENDIAN) || TARGET_AU_BITS > 16
|
||||
#define TARGET_ORDER(cookedmap) (cookedmap)
|
||||
#elif TARGET_AU_BITS > 8
|
||||
#define TARGET_ORDER(cookedmap) ((cookedmap) ^ 0x2020202)
|
||||
#else
|
||||
#define TARGET_ORDER(cookedmap) ((cookedmap) ^ 0x3030303)
|
||||
#endif
|
||||
|
||||
/* forward declaration for handle returned by dynamic loader */
|
||||
struct my_handle;
|
||||
|
||||
/*
|
||||
* a list of module handles, which mirrors the debug list on the target
|
||||
*/
|
||||
struct dbg_mirror_root {
|
||||
/* must be same as dbg_mirror_list; __DLModules address on target */
|
||||
u32 dbthis;
|
||||
struct my_handle *hnext; /* must be same as dbg_mirror_list */
|
||||
u16 changes; /* change counter */
|
||||
u16 refcount; /* number of modules referencing this root */
|
||||
};
|
||||
|
||||
struct dbg_mirror_list {
|
||||
u32 dbthis;
|
||||
struct my_handle *hnext, *hprev;
|
||||
struct dbg_mirror_root *hroot;
|
||||
u16 dbsiz;
|
||||
u32 context; /* Save context for .dllview memory allocation */
|
||||
};
|
||||
|
||||
#define VARIABLE_SIZE 1
|
||||
/*
|
||||
* the structure we actually return as an opaque module handle
|
||||
*/
|
||||
struct my_handle {
|
||||
struct dbg_mirror_list dm; /* !!! must be first !!! */
|
||||
/* sections following << 1, LSB is set for big-endian target */
|
||||
u16 secn_count;
|
||||
struct ldr_section_info secns[VARIABLE_SIZE];
|
||||
};
|
||||
#define MY_HANDLE_SIZE (sizeof(struct my_handle) -\
|
||||
sizeof(struct ldr_section_info))
|
||||
/* real size of my_handle */
|
||||
|
||||
/*
|
||||
* reduced symbol structure used for symbols during relocation
|
||||
*/
|
||||
struct local_symbol {
|
||||
s32 value; /* Relocated symbol value */
|
||||
s32 delta; /* Original value in input file */
|
||||
s16 secnn; /* section number */
|
||||
s16 sclass; /* symbol class */
|
||||
};
|
||||
|
||||
/*
|
||||
* Trampoline data structures
|
||||
*/
|
||||
#define TRAMP_NO_GEN_AVAIL 65535
|
||||
#define TRAMP_SYM_PREFIX "__$dbTR__"
|
||||
#define TRAMP_SECT_NAME ".dbTR"
|
||||
/* MUST MATCH THE LENGTH ABOVE!! */
|
||||
#define TRAMP_SYM_PREFIX_LEN 9
|
||||
/* Includes NULL termination */
|
||||
#define TRAMP_SYM_HEX_ASCII_LEN 9
|
||||
|
||||
#define GET_CONTAINER(ptr, type, field) ((type *)((unsigned long)ptr -\
|
||||
(unsigned long)(&((type *)0)->field)))
|
||||
#ifndef FIELD_OFFSET
|
||||
#define FIELD_OFFSET(type, field) ((unsigned long)(&((type *)0)->field))
|
||||
#endif
|
||||
|
||||
/*
|
||||
The trampoline code for the target is located in a table called
|
||||
"tramp_gen_info" with is indexed by looking up the index in the table
|
||||
"tramp_map". The tramp_map index is acquired using the target
|
||||
HASH_FUNC on the relocation type that caused the trampoline. Each
|
||||
trampoline code table entry MUST follow this format:
|
||||
|
||||
|----------------------------------------------|
|
||||
| tramp_gen_code_hdr |
|
||||
|----------------------------------------------|
|
||||
| Trampoline image code |
|
||||
| (the raw instruction code for the target) |
|
||||
|----------------------------------------------|
|
||||
| Relocation entries for the image code |
|
||||
|----------------------------------------------|
|
||||
|
||||
This is very similar to how image data is laid out in the DOFF file
|
||||
itself.
|
||||
*/
|
||||
struct tramp_gen_code_hdr {
|
||||
u32 tramp_code_size; /* in BYTES */
|
||||
u32 num_relos;
|
||||
u32 relo_offset; /* in BYTES */
|
||||
};
|
||||
|
||||
struct tramp_img_pkt {
|
||||
struct tramp_img_pkt *next; /* MUST BE FIRST */
|
||||
u32 base;
|
||||
struct tramp_gen_code_hdr hdr;
|
||||
u8 payload[VARIABLE_SIZE];
|
||||
};
|
||||
|
||||
struct tramp_img_dup_relo {
|
||||
struct tramp_img_dup_relo *next;
|
||||
struct reloc_record_t relo;
|
||||
};
|
||||
|
||||
struct tramp_img_dup_pkt {
|
||||
struct tramp_img_dup_pkt *next; /* MUST BE FIRST */
|
||||
s16 secnn;
|
||||
u32 offset;
|
||||
struct image_packet_t img_pkt;
|
||||
struct tramp_img_dup_relo *relo_chain;
|
||||
|
||||
/* PAYLOAD OF IMG PKT FOLLOWS */
|
||||
};
|
||||
|
||||
struct tramp_sym {
|
||||
struct tramp_sym *next; /* MUST BE FIRST */
|
||||
u32 index;
|
||||
u32 str_index;
|
||||
struct local_symbol sym_info;
|
||||
};
|
||||
|
||||
struct tramp_string {
|
||||
struct tramp_string *next; /* MUST BE FIRST */
|
||||
u32 index;
|
||||
char str[VARIABLE_SIZE]; /* NULL terminated */
|
||||
};
|
||||
|
||||
struct tramp_info {
|
||||
u32 tramp_sect_next_addr;
|
||||
struct ldr_section_info sect_info;
|
||||
|
||||
struct tramp_sym *symbol_head;
|
||||
struct tramp_sym *symbol_tail;
|
||||
u32 tramp_sym_next_index;
|
||||
struct local_symbol *final_sym_table;
|
||||
|
||||
struct tramp_string *string_head;
|
||||
struct tramp_string *string_tail;
|
||||
u32 tramp_string_next_index;
|
||||
u32 tramp_string_size;
|
||||
char *final_string_table;
|
||||
|
||||
struct tramp_img_pkt *tramp_pkts;
|
||||
struct tramp_img_dup_pkt *dup_pkts;
|
||||
};
|
||||
|
||||
/*
|
||||
* States of the .cinit state machine
|
||||
*/
|
||||
enum cinit_mode {
|
||||
CI_COUNT = 0, /* expecting a count */
|
||||
CI_ADDRESS, /* expecting an address */
|
||||
#if CINIT_ALIGN < CINIT_ADDRESS /* handle case of partial address field */
|
||||
CI_PARTADDRESS, /* have only part of the address */
|
||||
#endif
|
||||
CI_COPY, /* in the middle of copying data */
|
||||
CI_DONE /* end of .cinit table */
|
||||
};
|
||||
|
||||
/*
|
||||
* The internal state of the dynamic loader, which is passed around as
|
||||
* an object
|
||||
*/
|
||||
struct dload_state {
|
||||
struct dynamic_loader_stream *strm; /* The module input stream */
|
||||
struct dynamic_loader_sym *mysym; /* Symbols for this session */
|
||||
/* target memory allocator */
|
||||
struct dynamic_loader_allocate *myalloc;
|
||||
struct dynamic_loader_initialize *myio; /* target memory initializer */
|
||||
unsigned myoptions; /* Options parameter dynamic_load_module */
|
||||
|
||||
char *str_head; /* Pointer to string table */
|
||||
#if BITS_PER_AU > BITS_PER_BYTE
|
||||
char *str_temp; /* Pointer to temporary buffer for strings */
|
||||
/* big enough to hold longest string */
|
||||
unsigned temp_len; /* length of last temporary string */
|
||||
char *xstrings; /* Pointer to buffer for expanded */
|
||||
/* strings for sec names */
|
||||
#endif
|
||||
/* Total size of strings for DLLView section names */
|
||||
unsigned debug_string_size;
|
||||
/* Pointer to parallel section info for allocated sections only */
|
||||
struct doff_scnhdr_t *sect_hdrs; /* Pointer to section table */
|
||||
struct ldr_section_info *ldr_sections;
|
||||
#if TMS32060
|
||||
/* The address of the start of the .bss section */
|
||||
ldr_addr bss_run_base;
|
||||
#endif
|
||||
struct local_symbol *local_symtab; /* Relocation symbol table */
|
||||
|
||||
/* pointer to DL section info for the section being relocated */
|
||||
struct ldr_section_info *image_secn;
|
||||
/* change in run address for current section during relocation */
|
||||
ldr_addr delta_runaddr;
|
||||
ldr_addr image_offset; /* offset of current packet in section */
|
||||
enum cinit_mode cinit_state; /* current state of cload_cinit() */
|
||||
int cinit_count; /* the current count */
|
||||
ldr_addr cinit_addr; /* the current address */
|
||||
s16 cinit_page; /* the current page */
|
||||
/* Handle to be returned by dynamic_load_module */
|
||||
struct my_handle *myhandle;
|
||||
unsigned dload_errcount; /* Total # of errors reported so far */
|
||||
/* Number of target sections that require allocation and relocation */
|
||||
unsigned allocated_secn_count;
|
||||
#ifndef TARGET_ENDIANNESS
|
||||
int big_e_target; /* Target data in big-endian format */
|
||||
#endif
|
||||
/* map for reordering bytes, 0 if not needed */
|
||||
u32 reorder_map;
|
||||
struct doff_filehdr_t dfile_hdr; /* DOFF file header structure */
|
||||
struct doff_verify_rec_t verify; /* Verify record */
|
||||
|
||||
struct tramp_info tramp; /* Trampoline data, if needed */
|
||||
|
||||
int relstkidx; /* index into relocation value stack */
|
||||
/* relocation value stack used in relexp.c */
|
||||
rvalue relstk[STATIC_EXPR_STK_SIZE];
|
||||
|
||||
};
|
||||
|
||||
#ifdef TARGET_ENDIANNESS
|
||||
#define TARGET_BIG_ENDIAN TARGET_ENDIANNESS
|
||||
#else
|
||||
#define TARGET_BIG_ENDIAN (dlthis->big_e_target)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Exports from cload.c to rest of the world
|
||||
*/
|
||||
extern void dload_error(struct dload_state *dlthis, const char *errtxt, ...);
|
||||
extern void dload_syms_error(struct dynamic_loader_sym *syms,
|
||||
const char *errtxt, ...);
|
||||
extern void dload_headers(struct dload_state *dlthis);
|
||||
extern void dload_strings(struct dload_state *dlthis, bool sec_names_only);
|
||||
extern void dload_sections(struct dload_state *dlthis);
|
||||
extern void dload_reorder(void *data, int dsiz, u32 map);
|
||||
extern u32 dload_checksum(void *data, unsigned siz);
|
||||
|
||||
#if HOST_ENDIANNESS
|
||||
extern uint32_t dload_reverse_checksum(void *data, unsigned siz);
|
||||
#if (TARGET_AU_BITS > 8) && (TARGET_AU_BITS < 32)
|
||||
extern uint32_t dload_reverse_checksum16(void *data, unsigned siz);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define IS_DATA_SCN(zzz) (DLOAD_SECTION_TYPE((zzz)->type) != DLOAD_TEXT)
|
||||
#define IS_DATA_SCN_NUM(zzz) \
|
||||
(DLOAD_SECT_TYPE(&dlthis->sect_hdrs[(zzz)-1]) != DLOAD_TEXT)
|
||||
|
||||
/*
|
||||
* exported by reloc.c
|
||||
*/
|
||||
extern void dload_relocate(struct dload_state *dlthis, tgt_au_t * data,
|
||||
struct reloc_record_t *rp, bool * tramps_generated,
|
||||
bool second_pass);
|
||||
|
||||
extern rvalue dload_unpack(struct dload_state *dlthis, tgt_au_t * data,
|
||||
int fieldsz, int offset, unsigned sgn);
|
||||
|
||||
extern int dload_repack(struct dload_state *dlthis, rvalue val, tgt_au_t * data,
|
||||
int fieldsz, int offset, unsigned sgn);
|
||||
|
||||
/*
|
||||
* exported by tramp.c
|
||||
*/
|
||||
extern bool dload_tramp_avail(struct dload_state *dlthis,
|
||||
struct reloc_record_t *rp);
|
||||
|
||||
int dload_tramp_generate(struct dload_state *dlthis, s16 secnn,
|
||||
u32 image_offset, struct image_packet_t *ipacket,
|
||||
struct reloc_record_t *rp);
|
||||
|
||||
extern int dload_tramp_pkt_udpate(struct dload_state *dlthis,
|
||||
s16 secnn, u32 image_offset,
|
||||
struct image_packet_t *ipacket);
|
||||
|
||||
extern int dload_tramp_finalize(struct dload_state *dlthis);
|
||||
|
||||
extern void dload_tramp_cleanup(struct dload_state *dlthis);
|
||||
|
||||
#endif /* _DLOAD_INTERNAL_ */
|
344
drivers/staging/tidspbridge/dynload/doff.h
Normal file
344
drivers/staging/tidspbridge/dynload/doff.h
Normal file
@ -0,0 +1,344 @@
|
||||
/*
|
||||
* doff.h
|
||||
*
|
||||
* DSP-BIOS Bridge driver support functions for TI OMAP processors.
|
||||
*
|
||||
* Structures & definitions used for dynamically loaded modules file format.
|
||||
* This format is a reformatted version of COFF. It optimizes the layout for
|
||||
* the dynamic loader.
|
||||
*
|
||||
* .dof files, when viewed as a sequence of 32-bit integers, look the same
|
||||
* on big-endian and little-endian machines.
|
||||
*
|
||||
* Copyright (C) 2005-2006 Texas Instruments, Inc.
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef _DOFF_H
|
||||
#define _DOFF_H
|
||||
|
||||
#ifndef UINT32_C
|
||||
#define UINT32_C(zzz) ((u32)zzz)
|
||||
#endif
|
||||
|
||||
#define BYTE_RESHUFFLE_VALUE UINT32_C(0x00010203)
|
||||
|
||||
/* DOFF file header containing fields categorizing the remainder of the file */
|
||||
struct doff_filehdr_t {
|
||||
|
||||
/* string table size, including filename, in bytes */
|
||||
u32 df_strtab_size;
|
||||
|
||||
/* entry point if one exists */
|
||||
u32 df_entrypt;
|
||||
|
||||
/* identifies byte ordering of file;
|
||||
* always set to BYTE_RESHUFFLE_VALUE */
|
||||
u32 df_byte_reshuffle;
|
||||
|
||||
/* Size of the string table up to and including the last section name */
|
||||
/* Size includes the name of the COFF file also */
|
||||
u32 df_scn_name_size;
|
||||
|
||||
#ifndef _BIG_ENDIAN
|
||||
/* number of symbols */
|
||||
u16 df_no_syms;
|
||||
|
||||
/* length in bytes of the longest string, including terminating NULL */
|
||||
/* excludes the name of the file */
|
||||
u16 df_max_str_len;
|
||||
|
||||
/* total number of sections including no-load ones */
|
||||
u16 df_no_scns;
|
||||
|
||||
/* number of sections containing target code allocated or downloaded */
|
||||
u16 df_target_scns;
|
||||
|
||||
/* unique id for dll file format & version */
|
||||
u16 df_doff_version;
|
||||
|
||||
/* identifies ISA */
|
||||
u16 df_target_id;
|
||||
|
||||
/* useful file flags */
|
||||
u16 df_flags;
|
||||
|
||||
/* section reference for entry point, N_UNDEF for none, */
|
||||
/* N_ABS for absolute address */
|
||||
s16 df_entry_secn;
|
||||
#else
|
||||
/* length of the longest string, including terminating NULL */
|
||||
u16 df_max_str_len;
|
||||
|
||||
/* number of symbols */
|
||||
u16 df_no_syms;
|
||||
|
||||
/* number of sections containing target code allocated or downloaded */
|
||||
u16 df_target_scns;
|
||||
|
||||
/* total number of sections including no-load ones */
|
||||
u16 df_no_scns;
|
||||
|
||||
/* identifies ISA */
|
||||
u16 df_target_id;
|
||||
|
||||
/* unique id for dll file format & version */
|
||||
u16 df_doff_version;
|
||||
|
||||
/* section reference for entry point, N_UNDEF for none, */
|
||||
/* N_ABS for absolute address */
|
||||
s16 df_entry_secn;
|
||||
|
||||
/* useful file flags */
|
||||
u16 df_flags;
|
||||
#endif
|
||||
/* checksum for file header record */
|
||||
u32 df_checksum;
|
||||
|
||||
};
|
||||
|
||||
/* flags in the df_flags field */
|
||||
#define DF_LITTLE 0x100
|
||||
#define DF_BIG 0x200
|
||||
#define DF_BYTE_ORDER (DF_LITTLE | DF_BIG)
|
||||
|
||||
/* Supported processors */
|
||||
#define TMS470_ID 0x97
|
||||
#define LEAD_ID 0x98
|
||||
#define TMS32060_ID 0x99
|
||||
#define LEAD3_ID 0x9c
|
||||
|
||||
/* Primary processor for loading */
|
||||
#if TMS32060
|
||||
#define TARGET_ID TMS32060_ID
|
||||
#endif
|
||||
|
||||
/* Verification record containing values used to test integrity of the bits */
|
||||
struct doff_verify_rec_t {
|
||||
|
||||
/* time and date stamp */
|
||||
u32 dv_timdat;
|
||||
|
||||
/* checksum for all section records */
|
||||
u32 dv_scn_rec_checksum;
|
||||
|
||||
/* checksum for string table */
|
||||
u32 dv_str_tab_checksum;
|
||||
|
||||
/* checksum for symbol table */
|
||||
u32 dv_sym_tab_checksum;
|
||||
|
||||
/* checksum for verification record */
|
||||
u32 dv_verify_rec_checksum;
|
||||
|
||||
};
|
||||
|
||||
/* String table is an array of null-terminated strings. The first entry is
|
||||
* the filename, which is added by DLLcreate. No new structure definitions
|
||||
* are required.
|
||||
*/
|
||||
|
||||
/* Section Records including information on the corresponding image packets */
|
||||
/*
|
||||
* !!WARNING!!
|
||||
*
|
||||
* This structure is expected to match in form ldr_section_info in
|
||||
* dynamic_loader.h
|
||||
*/
|
||||
|
||||
struct doff_scnhdr_t {
|
||||
|
||||
s32 ds_offset; /* offset into string table of name */
|
||||
s32 ds_paddr; /* RUN address, in target AU */
|
||||
s32 ds_vaddr; /* LOAD address, in target AU */
|
||||
s32 ds_size; /* section size, in target AU */
|
||||
#ifndef _BIG_ENDIAN
|
||||
u16 ds_page; /* memory page id */
|
||||
u16 ds_flags; /* section flags */
|
||||
#else
|
||||
u16 ds_flags; /* section flags */
|
||||
u16 ds_page; /* memory page id */
|
||||
#endif
|
||||
u32 ds_first_pkt_offset;
|
||||
/* Absolute byte offset into the file */
|
||||
/* where the first image record resides */
|
||||
|
||||
s32 ds_nipacks; /* number of image packets */
|
||||
|
||||
};
|
||||
|
||||
/* Symbol table entry */
|
||||
struct doff_syment_t {
|
||||
|
||||
s32 dn_offset; /* offset into string table of name */
|
||||
s32 dn_value; /* value of symbol */
|
||||
#ifndef _BIG_ENDIAN
|
||||
s16 dn_scnum; /* section number */
|
||||
s16 dn_sclass; /* storage class */
|
||||
#else
|
||||
s16 dn_sclass; /* storage class */
|
||||
s16 dn_scnum; /* section number, 1-based */
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
/* special values for dn_scnum */
|
||||
#define DN_UNDEF 0 /* undefined symbol */
|
||||
#define DN_ABS (-1) /* value of symbol is absolute */
|
||||
/* special values for dn_sclass */
|
||||
#define DN_EXT 2
|
||||
#define DN_STATLAB 20
|
||||
#define DN_EXTLAB 21
|
||||
|
||||
/* Default value of image bits in packet */
|
||||
/* Configurable by user on the command line */
|
||||
#define IMAGE_PACKET_SIZE 1024
|
||||
|
||||
/* An image packet contains a chunk of data from a section along with */
|
||||
/* information necessary for its processing. */
|
||||
struct image_packet_t {
|
||||
|
||||
s32 num_relocs; /* number of relocations for */
|
||||
/* this packet */
|
||||
|
||||
s32 packet_size; /* number of bytes in array */
|
||||
/* "bits" occupied by */
|
||||
/* valid data. Could be */
|
||||
/* < IMAGE_PACKET_SIZE to */
|
||||
/* prevent splitting a */
|
||||
/* relocation across packets. */
|
||||
/* Last packet of a section */
|
||||
/* will most likely contain */
|
||||
/* < IMAGE_PACKET_SIZE bytes */
|
||||
/* of valid data */
|
||||
|
||||
s32 img_chksum; /* Checksum for image packet */
|
||||
/* and the corresponding */
|
||||
/* relocation records */
|
||||
|
||||
u8 *img_data; /* Actual data in section */
|
||||
|
||||
};
|
||||
|
||||
/* The relocation structure definition matches the COFF version. Offsets */
|
||||
/* however are relative to the image packet base not the section base. */
|
||||
struct reloc_record_t {
|
||||
|
||||
s32 vaddr;
|
||||
|
||||
/* expressed in target AUs */
|
||||
|
||||
union {
|
||||
struct {
|
||||
#ifndef _BIG_ENDIAN
|
||||
u8 _offset; /* bit offset of rel fld */
|
||||
u8 _fieldsz; /* size of rel fld */
|
||||
u8 _wordsz; /* # bytes containing rel fld */
|
||||
u8 _dum1;
|
||||
u16 _dum2;
|
||||
u16 _type;
|
||||
#else
|
||||
unsigned _dum1:8;
|
||||
unsigned _wordsz:8; /* # bytes containing rel fld */
|
||||
unsigned _fieldsz:8; /* size of rel fld */
|
||||
unsigned _offset:8; /* bit offset of rel fld */
|
||||
u16 _type;
|
||||
u16 _dum2;
|
||||
#endif
|
||||
} _r_field;
|
||||
|
||||
struct {
|
||||
u32 _spc; /* image packet relative PC */
|
||||
#ifndef _BIG_ENDIAN
|
||||
u16 _dum;
|
||||
u16 _type; /* relocation type */
|
||||
#else
|
||||
u16 _type; /* relocation type */
|
||||
u16 _dum;
|
||||
#endif
|
||||
} _r_spc;
|
||||
|
||||
struct {
|
||||
u32 _uval; /* constant value */
|
||||
#ifndef _BIG_ENDIAN
|
||||
u16 _dum;
|
||||
u16 _type; /* relocation type */
|
||||
#else
|
||||
u16 _type; /* relocation type */
|
||||
u16 _dum;
|
||||
#endif
|
||||
} _r_uval;
|
||||
|
||||
struct {
|
||||
s32 _symndx; /* 32-bit sym tbl index */
|
||||
#ifndef _BIG_ENDIAN
|
||||
u16 _disp; /* extra addr encode data */
|
||||
u16 _type; /* relocation type */
|
||||
#else
|
||||
u16 _type; /* relocation type */
|
||||
u16 _disp; /* extra addr encode data */
|
||||
#endif
|
||||
} _r_sym;
|
||||
} _u_reloc;
|
||||
|
||||
};
|
||||
|
||||
/* abbreviations for convenience */
|
||||
#ifndef TYPE
|
||||
#define TYPE _u_reloc._r_sym._type
|
||||
#define UVAL _u_reloc._r_uval._uval
|
||||
#define SYMNDX _u_reloc._r_sym._symndx
|
||||
#define OFFSET _u_reloc._r_field._offset
|
||||
#define FIELDSZ _u_reloc._r_field._fieldsz
|
||||
#define WORDSZ _u_reloc._r_field._wordsz
|
||||
#define R_DISP _u_reloc._r_sym._disp
|
||||
#endif
|
||||
|
||||
/**************************************************************************** */
|
||||
/* */
|
||||
/* Important DOFF macros used for file processing */
|
||||
/* */
|
||||
/**************************************************************************** */
|
||||
|
||||
/* DOFF Versions */
|
||||
#define DOFF0 0
|
||||
|
||||
/* Return the address/size >= to addr that is at a 32-bit boundary */
|
||||
/* This assumes that a byte is 8 bits */
|
||||
#define DOFF_ALIGN(addr) (((addr) + 3) & ~UINT32_C(3))
|
||||
|
||||
/**************************************************************************** */
|
||||
/* */
|
||||
/* The DOFF section header flags field is laid out as follows: */
|
||||
/* */
|
||||
/* Bits 0-3 : Section Type */
|
||||
/* Bit 4 : Set when section requires target memory to be allocated by DL */
|
||||
/* Bit 5 : Set when section requires downloading */
|
||||
/* Bits 8-11: Alignment, same as COFF */
|
||||
/* */
|
||||
/**************************************************************************** */
|
||||
|
||||
/* Enum for DOFF section types (bits 0-3 of flag): See dynamic_loader.h */
|
||||
|
||||
/* Macros to help processing of sections */
|
||||
#define DLOAD_SECT_TYPE(s_hdr) ((s_hdr)->ds_flags & 0xF)
|
||||
|
||||
/* DS_ALLOCATE indicates whether a section needs space on the target */
|
||||
#define DS_ALLOCATE_MASK 0x10
|
||||
#define DS_NEEDS_ALLOCATION(s_hdr) ((s_hdr)->ds_flags & DS_ALLOCATE_MASK)
|
||||
|
||||
/* DS_DOWNLOAD indicates that the loader needs to copy bits */
|
||||
#define DS_DOWNLOAD_MASK 0x20
|
||||
#define DS_NEEDS_DOWNLOAD(s_hdr) ((s_hdr)->ds_flags & DS_DOWNLOAD_MASK)
|
||||
|
||||
/* Section alignment requirement in AUs */
|
||||
#define DS_ALIGNMENT(ds_flags) (1 << (((ds_flags) >> 8) & 0xF))
|
||||
|
||||
#endif /* _DOFF_H */
|
416
drivers/staging/tidspbridge/dynload/getsection.c
Normal file
416
drivers/staging/tidspbridge/dynload/getsection.c
Normal file
@ -0,0 +1,416 @@
|
||||
/*
|
||||
* getsection.c
|
||||
*
|
||||
* DSP-BIOS Bridge driver support functions for TI OMAP processors.
|
||||
*
|
||||
* Copyright (C) 2005-2006 Texas Instruments, Inc.
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#include <dspbridge/getsection.h>
|
||||
#include "header.h"
|
||||
|
||||
/*
|
||||
* Error strings
|
||||
*/
|
||||
static const char readstrm[] = { "Error reading %s from input stream" };
|
||||
static const char seek[] = { "Set file position to %d failed" };
|
||||
static const char isiz[] = { "Bad image packet size %d" };
|
||||
static const char err_checksum[] = { "Checksum failed on %s" };
|
||||
|
||||
static const char err_reloc[] = { "dload_get_section unable to read"
|
||||
"sections containing relocation entries"
|
||||
};
|
||||
|
||||
#if BITS_PER_AU > BITS_PER_BYTE
|
||||
static const char err_alloc[] = { "Syms->dload_allocate( %d ) failed" };
|
||||
static const char stbl[] = { "Bad string table offset " FMT_UI32 };
|
||||
#endif
|
||||
|
||||
/*
|
||||
* we use the fact that DOFF section records are shaped just like
|
||||
* ldr_section_info to reduce our section storage usage. These macros
|
||||
* marks the places where that assumption is made
|
||||
*/
|
||||
#define DOFFSEC_IS_LDRSEC(pdoffsec) ((struct ldr_section_info *)(pdoffsec))
|
||||
#define LDRSEC_IS_DOFFSEC(ldrsec) ((struct doff_scnhdr_t *)(ldrsec))
|
||||
|
||||
/************************************************************** */
|
||||
/********************* SUPPORT FUNCTIONS ********************** */
|
||||
/************************************************************** */
|
||||
|
||||
#if BITS_PER_AU > BITS_PER_BYTE
|
||||
/**************************************************************************
|
||||
* Procedure unpack_sec_name
|
||||
*
|
||||
* Parameters:
|
||||
* dlthis Handle from dload_module_open for this module
|
||||
* soffset Byte offset into the string table
|
||||
* dst Place to store the expanded string
|
||||
*
|
||||
* Effect:
|
||||
* Stores a string from the string table into the destination, expanding
|
||||
* it in the process. Returns a pointer just past the end of the stored
|
||||
* string on success, or NULL on failure.
|
||||
*
|
||||
************************************************************************ */
|
||||
static char *unpack_sec_name(struct dload_state *dlthis, u32 soffset, char *dst)
|
||||
{
|
||||
u8 tmp, *src;
|
||||
|
||||
if (soffset >= dlthis->dfile_hdr.df_scn_name_size) {
|
||||
dload_error(dlthis, stbl, soffset);
|
||||
return NULL;
|
||||
}
|
||||
src = (u8 *) dlthis->str_head +
|
||||
(soffset >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE));
|
||||
if (soffset & 1)
|
||||
*dst++ = *src++; /* only 1 character in first word */
|
||||
do {
|
||||
tmp = *src++;
|
||||
*dst = (tmp >> BITS_PER_BYTE)
|
||||
if (!(*dst++))
|
||||
break;
|
||||
} while ((*dst++ = tmp & BYTE_MASK));
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Procedure expand_sec_names
|
||||
*
|
||||
* Parameters:
|
||||
* dlthis Handle from dload_module_open for this module
|
||||
*
|
||||
* Effect:
|
||||
* Allocates a buffer, unpacks and copies strings from string table into it.
|
||||
* Stores a pointer to the buffer into a state variable.
|
||||
************************************************************************* */
|
||||
static void expand_sec_names(struct dload_state *dlthis)
|
||||
{
|
||||
char *xstrings, *curr, *next;
|
||||
u32 xsize;
|
||||
u16 sec;
|
||||
struct ldr_section_info *shp;
|
||||
/* assume worst-case size requirement */
|
||||
xsize = dlthis->dfile_hdr.df_max_str_len * dlthis->dfile_hdr.df_no_scns;
|
||||
xstrings = (char *)dlthis->mysym->dload_allocate(dlthis->mysym, xsize);
|
||||
if (xstrings == NULL) {
|
||||
dload_error(dlthis, err_alloc, xsize);
|
||||
return;
|
||||
}
|
||||
dlthis->xstrings = xstrings;
|
||||
/* For each sec, copy and expand its name */
|
||||
curr = xstrings;
|
||||
for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
|
||||
shp = DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
|
||||
next = unpack_sec_name(dlthis, *(u32 *) &shp->name, curr);
|
||||
if (next == NULL)
|
||||
break; /* error */
|
||||
shp->name = curr;
|
||||
curr = next;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/************************************************************** */
|
||||
/********************* EXPORTED FUNCTIONS ********************* */
|
||||
/************************************************************** */
|
||||
|
||||
/**************************************************************************
|
||||
* Procedure dload_module_open
|
||||
*
|
||||
* Parameters:
|
||||
* module The input stream that supplies the module image
|
||||
* syms Host-side malloc/free and error reporting functions.
|
||||
* Other methods are unused.
|
||||
*
|
||||
* Effect:
|
||||
* Reads header information from a dynamic loader module using the
|
||||
specified
|
||||
* stream object, and returns a handle for the module information. This
|
||||
* handle may be used in subsequent query calls to obtain information
|
||||
* contained in the module.
|
||||
*
|
||||
* Returns:
|
||||
* NULL if an error is encountered, otherwise a module handle for use
|
||||
* in subsequent operations.
|
||||
************************************************************************* */
|
||||
void *dload_module_open(struct dynamic_loader_stream *module,
|
||||
struct dynamic_loader_sym *syms)
|
||||
{
|
||||
struct dload_state *dlthis; /* internal state for this call */
|
||||
unsigned *dp, sz;
|
||||
u32 sec_start;
|
||||
#if BITS_PER_AU <= BITS_PER_BYTE
|
||||
u16 sec;
|
||||
#endif
|
||||
|
||||
/* Check that mandatory arguments are present */
|
||||
if (!module || !syms) {
|
||||
if (syms != NULL)
|
||||
dload_syms_error(syms, "Required parameter is NULL");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dlthis = (struct dload_state *)
|
||||
syms->dload_allocate(syms, sizeof(struct dload_state));
|
||||
if (!dlthis) {
|
||||
/* not enough storage */
|
||||
dload_syms_error(syms, "Can't allocate module info");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* clear our internal state */
|
||||
dp = (unsigned *)dlthis;
|
||||
for (sz = sizeof(struct dload_state) / sizeof(unsigned);
|
||||
sz > 0; sz -= 1)
|
||||
*dp++ = 0;
|
||||
|
||||
dlthis->strm = module;
|
||||
dlthis->mysym = syms;
|
||||
|
||||
/* read in the doff image and store in our state variable */
|
||||
dload_headers(dlthis);
|
||||
|
||||
if (!dlthis->dload_errcount)
|
||||
dload_strings(dlthis, true);
|
||||
|
||||
/* skip ahead past the unread portion of the string table */
|
||||
sec_start = sizeof(struct doff_filehdr_t) +
|
||||
sizeof(struct doff_verify_rec_t) +
|
||||
BYTE_TO_HOST(DOFF_ALIGN(dlthis->dfile_hdr.df_strtab_size));
|
||||
|
||||
if (dlthis->strm->set_file_posn(dlthis->strm, sec_start) != 0) {
|
||||
dload_error(dlthis, seek, sec_start);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!dlthis->dload_errcount)
|
||||
dload_sections(dlthis);
|
||||
|
||||
if (dlthis->dload_errcount) {
|
||||
dload_module_close(dlthis); /* errors, blow off our state */
|
||||
dlthis = NULL;
|
||||
return NULL;
|
||||
}
|
||||
#if BITS_PER_AU > BITS_PER_BYTE
|
||||
/* Expand all section names from the string table into the */
|
||||
/* state variable, and convert section names from a relative */
|
||||
/* string table offset to a pointers to the expanded string. */
|
||||
expand_sec_names(dlthis);
|
||||
#else
|
||||
/* Convert section names from a relative string table offset */
|
||||
/* to a pointer into the string table. */
|
||||
for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
|
||||
struct ldr_section_info *shp =
|
||||
DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
|
||||
shp->name = dlthis->str_head + *(u32 *) &shp->name;
|
||||
}
|
||||
#endif
|
||||
|
||||
return dlthis;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Procedure dload_get_section_info
|
||||
*
|
||||
* Parameters:
|
||||
* minfo Handle from dload_module_open for this module
|
||||
* sectionName Pointer to the string name of the section desired
|
||||
* sectionInfo Address of a section info structure pointer to be
|
||||
* initialized
|
||||
*
|
||||
* Effect:
|
||||
* Finds the specified section in the module information, and initializes
|
||||
* the provided struct ldr_section_info pointer.
|
||||
*
|
||||
* Returns:
|
||||
* true for success, false for section not found
|
||||
************************************************************************* */
|
||||
int dload_get_section_info(void *minfo, const char *sectionName,
|
||||
const struct ldr_section_info **const sectionInfo)
|
||||
{
|
||||
struct dload_state *dlthis;
|
||||
struct ldr_section_info *shp;
|
||||
u16 sec;
|
||||
|
||||
dlthis = (struct dload_state *)minfo;
|
||||
if (!dlthis)
|
||||
return false;
|
||||
|
||||
for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
|
||||
shp = DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
|
||||
if (strcmp(sectionName, shp->name) == 0) {
|
||||
*sectionInfo = shp;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
|
||||
#define REVERSE_REORDER_MAP(rawmap) ((rawmap) ^ 0x3030303)
|
||||
|
||||
/**************************************************************************
|
||||
* Procedure dload_get_section
|
||||
*
|
||||
* Parameters:
|
||||
* minfo Handle from dload_module_open for this module
|
||||
* sectionInfo Pointer to a section info structure for the desired
|
||||
* section
|
||||
* sectionData Buffer to contain the section initialized data
|
||||
*
|
||||
* Effect:
|
||||
* Copies the initialized data for the specified section into the
|
||||
* supplied buffer.
|
||||
*
|
||||
* Returns:
|
||||
* true for success, false for section not found
|
||||
************************************************************************* */
|
||||
int dload_get_section(void *minfo,
|
||||
const struct ldr_section_info *sectionInfo,
|
||||
void *sectionData)
|
||||
{
|
||||
struct dload_state *dlthis;
|
||||
u32 pos;
|
||||
struct doff_scnhdr_t *sptr = NULL;
|
||||
s32 nip;
|
||||
struct image_packet_t ipacket;
|
||||
s32 ipsize;
|
||||
u32 checks;
|
||||
s8 *dest = (s8 *) sectionData;
|
||||
|
||||
dlthis = (struct dload_state *)minfo;
|
||||
if (!dlthis)
|
||||
return false;
|
||||
sptr = LDRSEC_IS_DOFFSEC(sectionInfo);
|
||||
if (sptr == NULL)
|
||||
return false;
|
||||
|
||||
/* skip ahead to the start of the first packet */
|
||||
pos = BYTE_TO_HOST(DOFF_ALIGN((u32) sptr->ds_first_pkt_offset));
|
||||
if (dlthis->strm->set_file_posn(dlthis->strm, pos) != 0) {
|
||||
dload_error(dlthis, seek, pos);
|
||||
return false;
|
||||
}
|
||||
|
||||
nip = sptr->ds_nipacks;
|
||||
while ((nip -= 1) >= 0) { /* for each packet */
|
||||
/* get the fixed header bits */
|
||||
if (dlthis->strm->read_buffer(dlthis->strm, &ipacket,
|
||||
IPH_SIZE) != IPH_SIZE) {
|
||||
dload_error(dlthis, readstrm, "image packet");
|
||||
return false;
|
||||
}
|
||||
/* reorder the header if need be */
|
||||
if (dlthis->reorder_map)
|
||||
dload_reorder(&ipacket, IPH_SIZE, dlthis->reorder_map);
|
||||
|
||||
/* Now read the packet image bits. Note: round the size up to
|
||||
* the next multiple of 4 bytes; this is what checksum
|
||||
* routines want. */
|
||||
ipsize = BYTE_TO_HOST(DOFF_ALIGN(ipacket.packet_size));
|
||||
if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) {
|
||||
dload_error(dlthis, isiz, ipsize);
|
||||
return false;
|
||||
}
|
||||
if (dlthis->strm->read_buffer
|
||||
(dlthis->strm, dest, ipsize) != ipsize) {
|
||||
dload_error(dlthis, readstrm, "image packet");
|
||||
return false;
|
||||
}
|
||||
/* reorder the bytes if need be */
|
||||
#if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
|
||||
if (dlthis->reorder_map)
|
||||
dload_reorder(dest, ipsize, dlthis->reorder_map);
|
||||
|
||||
checks = dload_checksum(dest, ipsize);
|
||||
#else
|
||||
if (dlthis->dfile_hdr.df_byte_reshuffle !=
|
||||
TARGET_ORDER(REORDER_MAP(BYTE_RESHUFFLE_VALUE))) {
|
||||
/* put image bytes in big-endian order, not PC order */
|
||||
dload_reorder(dest, ipsize,
|
||||
TARGET_ORDER(dlthis->
|
||||
dfile_hdr.df_byte_reshuffle));
|
||||
}
|
||||
#if TARGET_AU_BITS > 8
|
||||
checks = dload_reverse_checksum16(dest, ipsize);
|
||||
#else
|
||||
checks = dload_reverse_checksum(dest, ipsize);
|
||||
#endif
|
||||
#endif
|
||||
checks += dload_checksum(&ipacket, IPH_SIZE);
|
||||
|
||||
/* NYI: unable to handle relocation entries here. Reloc
|
||||
* entries referring to fields that span the packet boundaries
|
||||
* may result in packets of sizes that are not multiple of
|
||||
* 4 bytes. Our checksum implementation works on 32-bit words
|
||||
* only. */
|
||||
if (ipacket.num_relocs != 0) {
|
||||
dload_error(dlthis, err_reloc, ipsize);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (~checks) {
|
||||
dload_error(dlthis, err_checksum, "image packet");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*Advance destination ptr by the size of the just-read packet */
|
||||
dest += ipsize;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Procedure dload_module_close
|
||||
*
|
||||
* Parameters:
|
||||
* minfo Handle from dload_module_open for this module
|
||||
*
|
||||
* Effect:
|
||||
* Releases any storage associated with the module handle. On return,
|
||||
* the module handle is invalid.
|
||||
*
|
||||
* Returns:
|
||||
* Zero for success. On error, the number of errors detected is returned.
|
||||
* Individual errors are reported using syms->error_report(), where syms was
|
||||
* an argument to dload_module_open
|
||||
************************************************************************* */
|
||||
void dload_module_close(void *minfo)
|
||||
{
|
||||
struct dload_state *dlthis;
|
||||
|
||||
dlthis = (struct dload_state *)minfo;
|
||||
if (!dlthis)
|
||||
return;
|
||||
|
||||
if (dlthis->str_head)
|
||||
dlthis->mysym->dload_deallocate(dlthis->mysym,
|
||||
dlthis->str_head);
|
||||
|
||||
if (dlthis->sect_hdrs)
|
||||
dlthis->mysym->dload_deallocate(dlthis->mysym,
|
||||
dlthis->sect_hdrs);
|
||||
|
||||
#if BITS_PER_AU > BITS_PER_BYTE
|
||||
if (dlthis->xstrings)
|
||||
dlthis->mysym->dload_deallocate(dlthis->mysym,
|
||||
dlthis->xstrings);
|
||||
|
||||
#endif
|
||||
|
||||
dlthis->mysym->dload_deallocate(dlthis->mysym, dlthis);
|
||||
}
|
55
drivers/staging/tidspbridge/dynload/header.h
Normal file
55
drivers/staging/tidspbridge/dynload/header.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* header.h
|
||||
*
|
||||
* DSP-BIOS Bridge driver support functions for TI OMAP processors.
|
||||
*
|
||||
* Copyright (C) 2005-2006 Texas Instruments, Inc.
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#include <linux/string.h>
|
||||
#define DL_STRCMP strcmp
|
||||
|
||||
/* maximum parenthesis nesting in relocation stack expressions */
|
||||
#define STATIC_EXPR_STK_SIZE 10
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "doff.h"
|
||||
#include <dspbridge/dynamic_loader.h>
|
||||
#include "params.h"
|
||||
#include "dload_internal.h"
|
||||
#include "reloc_table.h"
|
||||
|
||||
/*
|
||||
* Plausibility limits
|
||||
*
|
||||
* These limits are imposed upon the input DOFF file as a check for validity.
|
||||
* They are hard limits, in that the load will fail if they are exceeded.
|
||||
* The numbers selected are arbitrary, in that the loader implementation does
|
||||
* not require these limits.
|
||||
*/
|
||||
|
||||
/* maximum number of bytes in string table */
|
||||
#define MAX_REASONABLE_STRINGTAB (0x100000)
|
||||
/* maximum number of code,data,etc. sections */
|
||||
#define MAX_REASONABLE_SECTIONS (200)
|
||||
/* maximum number of linker symbols */
|
||||
#define MAX_REASONABLE_SYMBOLS (100000)
|
||||
|
||||
/* shift count to align F_BIG with DLOAD_LITTLE */
|
||||
#define ALIGN_COFF_ENDIANNESS 7
|
||||
#define ENDIANNESS_MASK (DF_BYTE_ORDER >> ALIGN_COFF_ENDIANNESS)
|
159
drivers/staging/tidspbridge/dynload/module_list.h
Normal file
159
drivers/staging/tidspbridge/dynload/module_list.h
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* dspbridge/mpu_driver/src/dynload/module_list.h
|
||||
*
|
||||
* DSP-BIOS Bridge driver support functions for TI OMAP processors.
|
||||
*
|
||||
* Copyright (C) 2008 Texas Instruments, Inc.
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This C header file gives the layout of the data structure created by the
|
||||
* dynamic loader to describe the set of modules loaded into the DSP.
|
||||
*
|
||||
* Linked List Structure:
|
||||
* ----------------------
|
||||
* The data structure defined here is a singly-linked list. The list
|
||||
* represents the set of modules which are currently loaded in the DSP memory.
|
||||
* The first entry in the list is a header record which contains a flag
|
||||
* representing the state of the list. The rest of the entries in the list
|
||||
* are module records.
|
||||
*
|
||||
* Global symbol _DLModules designates the first record in the list (i.e. the
|
||||
* header record). This symbol must be defined in any program that wishes to
|
||||
* use DLLview plug-in.
|
||||
*
|
||||
* String Representation:
|
||||
* ----------------------
|
||||
* The string names of the module and its sections are stored in a block of
|
||||
* memory which follows the module record itself. The strings are ordered:
|
||||
* module name first, followed by section names in order from the first
|
||||
* section to the last. String names are tightly packed arrays of 8-bit
|
||||
* characters (two characters per 16-bit word on the C55x). Strings are
|
||||
* zero-byte-terminated.
|
||||
*
|
||||
* Creating and updating the list:
|
||||
* -------------------------------
|
||||
* Upon loading a new module into the DSP memory the dynamic loader inserts a
|
||||
* new module record as the first module record in the list. The fields of
|
||||
* this module record are initialized to reflect the properties of the module.
|
||||
* The dynamic loader does NOT increment the flag/counter in the list's header
|
||||
* record.
|
||||
*
|
||||
* Upon unloading a module from the DSP memory the dynamic loader removes the
|
||||
* module's record from this list. The dynamic loader also increments the
|
||||
* flag/counter in the list's header record to indicate that the list has been
|
||||
* changed.
|
||||
*/
|
||||
|
||||
#ifndef _MODULE_LIST_H_
|
||||
#define _MODULE_LIST_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* Global pointer to the modules_header structure */
|
||||
#define MODULES_HEADER "_DLModules"
|
||||
#define MODULES_HEADER_NO_UNDERSCORE "DLModules"
|
||||
|
||||
/* Initial version number */
|
||||
#define INIT_VERSION 1
|
||||
|
||||
/* Verification number -- to be recorded in each module record */
|
||||
#define VERIFICATION 0x79
|
||||
|
||||
/* forward declarations */
|
||||
struct dll_module;
|
||||
struct dll_sect;
|
||||
|
||||
/* the first entry in the list is the modules_header record;
|
||||
* its address is contained in the global _DLModules pointer */
|
||||
struct modules_header {
|
||||
|
||||
/*
|
||||
* Address of the first dll_module record in the list or NULL.
|
||||
* Note: for C55x this is a word address (C55x data is
|
||||
* word-addressable)
|
||||
*/
|
||||
u32 first_module;
|
||||
|
||||
/* Combined storage size (in target addressable units) of the
|
||||
* dll_module record which follows this header record, or zero
|
||||
* if the list is empty. This size includes the module's string table.
|
||||
* Note: for C55x the unit is a 16-bit word */
|
||||
u16 first_module_size;
|
||||
|
||||
/* Counter is incremented whenever a module record is removed from
|
||||
* the list */
|
||||
u16 update_flag;
|
||||
|
||||
};
|
||||
|
||||
/* for each 32-bits in above structure, a bitmap, LSB first, whose bits are:
|
||||
* 0 => a 32-bit value, 1 => 2 16-bit values */
|
||||
/* swapping bitmap for type modules_header */
|
||||
#define MODULES_HEADER_BITMAP 0x2
|
||||
|
||||
/* information recorded about each section in a module */
|
||||
struct dll_sect {
|
||||
|
||||
/* Load-time address of the section.
|
||||
* Note: for C55x this is a byte address for program sections, and
|
||||
* a word address for data sections. C55x program memory is
|
||||
* byte-addressable, while data memory is word-addressable. */
|
||||
u32 sect_load_adr;
|
||||
|
||||
/* Run-time address of the section.
|
||||
* Note 1: for C55x this is a byte address for program sections, and
|
||||
* a word address for data sections.
|
||||
* Note 2: for C55x two most significant bits of this field indicate
|
||||
* the section type: '00' for a code section, '11' for a data section
|
||||
* (C55 addresses are really only 24-bits wide). */
|
||||
u32 sect_run_adr;
|
||||
|
||||
};
|
||||
|
||||
/* the rest of the entries in the list are module records */
|
||||
struct dll_module {
|
||||
|
||||
/* Address of the next dll_module record in the list, or 0 if this is
|
||||
* the last record in the list.
|
||||
* Note: for C55x this is a word address (C55x data is
|
||||
* word-addressable) */
|
||||
u32 next_module;
|
||||
|
||||
/* Combined storage size (in target addressable units) of the
|
||||
* dll_module record which follows this one, or zero if this is the
|
||||
* last record in the list. This size includes the module's string
|
||||
* table.
|
||||
* Note: for C55x the unit is a 16-bit word. */
|
||||
u16 next_module_size;
|
||||
|
||||
/* version number of the tooling; set to INIT_VERSION for Phase 1 */
|
||||
u16 version;
|
||||
|
||||
/* the verification word; set to VERIFICATION */
|
||||
u16 verification;
|
||||
|
||||
/* Number of sections in the sects array */
|
||||
u16 num_sects;
|
||||
|
||||
/* Module's "unique" id; copy of the timestamp from the host
|
||||
* COFF file */
|
||||
u32 timestamp;
|
||||
|
||||
/* Array of num_sects elements of the module's section records */
|
||||
struct dll_sect sects[1];
|
||||
};
|
||||
|
||||
/* for each 32 bits in above structure, a bitmap, LSB first, whose bits are:
|
||||
* 0 => a 32-bit value, 1 => 2 16-bit values */
|
||||
#define DLL_MODULE_BITMAP 0x6 /* swapping bitmap for type dll_module */
|
||||
|
||||
#endif /* _MODULE_LIST_H_ */
|
226
drivers/staging/tidspbridge/dynload/params.h
Normal file
226
drivers/staging/tidspbridge/dynload/params.h
Normal file
@ -0,0 +1,226 @@
|
||||
/*
|
||||
* params.h
|
||||
*
|
||||
* DSP-BIOS Bridge driver support functions for TI OMAP processors.
|
||||
*
|
||||
* This file defines host and target properties for all machines
|
||||
* supported by the dynamic loader. To be tedious...
|
||||
*
|
||||
* host: the machine on which the dynamic loader runs
|
||||
* target: the machine that the dynamic loader is loading
|
||||
*
|
||||
* Host and target may or may not be the same, depending upon the particular
|
||||
* use.
|
||||
*
|
||||
* Copyright (C) 2005-2006 Texas Instruments, Inc.
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Host Properties
|
||||
*
|
||||
**************************************************************************** */
|
||||
|
||||
#define BITS_PER_BYTE 8 /* bits in the standard PC/SUN byte */
|
||||
#define LOG_BITS_PER_BYTE 3 /* log base 2 of same */
|
||||
#define BYTE_MASK ((1U<<BITS_PER_BYTE)-1)
|
||||
|
||||
#if defined(__TMS320C55X__) || defined(_TMS320C5XX)
|
||||
#define BITS_PER_AU 16
|
||||
#define LOG_BITS_PER_AU 4
|
||||
/* use this print string in error messages for uint32_t */
|
||||
#define FMT_UI32 "0x%lx"
|
||||
#define FMT8_UI32 "%08lx" /* same but no 0x, fixed width field */
|
||||
#else
|
||||
/* bits in the smallest addressable data storage unit */
|
||||
#define BITS_PER_AU 8
|
||||
/* log base 2 of the same; useful for shift counts */
|
||||
#define LOG_BITS_PER_AU 3
|
||||
#define FMT_UI32 "0x%x"
|
||||
#define FMT8_UI32 "%08x"
|
||||
#endif
|
||||
|
||||
/* generic fastest method for swapping bytes and shorts */
|
||||
#define SWAP32BY16(zz) (((zz) << 16) | ((zz) >> 16))
|
||||
#define SWAP16BY8(zz) (((zz) << 8) | ((zz) >> 8))
|
||||
|
||||
/* !! don't be tempted to insert type definitions here; use <stdint.h> !! */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Target Properties
|
||||
*
|
||||
**************************************************************************** */
|
||||
|
||||
/*-------------------------------------------------------------------------- */
|
||||
/* TMS320C6x Target Specific Parameters (byte-addressable) */
|
||||
/*-------------------------------------------------------------------------- */
|
||||
#if TMS32060
|
||||
#define MEMORG 0x0L /* Size of configured memory */
|
||||
#define MEMSIZE 0x0L /* (full address space) */
|
||||
|
||||
#define CINIT_ALIGN 8 /* alignment of cinit record in TDATA AUs */
|
||||
#define CINIT_COUNT 4 /* width of count field in TDATA AUs */
|
||||
#define CINIT_ADDRESS 4 /* width of address field in TDATA AUs */
|
||||
#define CINIT_PAGE_BITS 0 /* Number of LSBs of address that
|
||||
* are page number */
|
||||
|
||||
#define LENIENT_SIGNED_RELEXPS 0 /* DOES SIGNED ALLOW MAX UNSIGNED */
|
||||
|
||||
#undef TARGET_ENDIANNESS /* may be big or little endian */
|
||||
|
||||
/* align a target address to a word boundary */
|
||||
#define TARGET_WORD_ALIGN(zz) (((zz) + 0x3) & -0x4)
|
||||
#endif
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
*
|
||||
* DEFAULT SETTINGS and DERIVED PROPERTIES
|
||||
*
|
||||
* This section establishes defaults for values not specified above
|
||||
*-------------------------------------------------------------------------- */
|
||||
#ifndef TARGET_AU_BITS
|
||||
#define TARGET_AU_BITS 8 /* width of the target addressable unit */
|
||||
#define LOG_TARGET_AU_BITS 3 /* log2 of same */
|
||||
#endif
|
||||
|
||||
#ifndef CINIT_DEFAULT_PAGE
|
||||
#define CINIT_DEFAULT_PAGE 0 /* default .cinit page number */
|
||||
#endif
|
||||
|
||||
#ifndef DATA_RUN2LOAD
|
||||
#define DATA_RUN2LOAD(zz) (zz) /* translate data run address to load address */
|
||||
#endif
|
||||
|
||||
#ifndef DBG_LIST_PAGE
|
||||
#define DBG_LIST_PAGE 0 /* page number for .dllview section */
|
||||
#endif
|
||||
|
||||
#ifndef TARGET_WORD_ALIGN
|
||||
/* align a target address to a word boundary */
|
||||
#define TARGET_WORD_ALIGN(zz) (zz)
|
||||
#endif
|
||||
|
||||
#ifndef TDATA_TO_TADDR
|
||||
#define TDATA_TO_TADDR(zz) (zz) /* target data address to target AU address */
|
||||
#define TADDR_TO_TDATA(zz) (zz) /* target AU address to target data address */
|
||||
#define TDATA_AU_BITS TARGET_AU_BITS /* bits per data AU */
|
||||
#define LOG_TDATA_AU_BITS LOG_TARGET_AU_BITS
|
||||
#endif
|
||||
|
||||
/*
|
||||
*
|
||||
* Useful properties and conversions derived from the above
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Conversions between host and target addresses
|
||||
*/
|
||||
#if LOG_BITS_PER_AU == LOG_TARGET_AU_BITS
|
||||
/* translate target addressable unit to host address */
|
||||
#define TADDR_TO_HOST(x) (x)
|
||||
/* translate host address to target addressable unit */
|
||||
#define HOST_TO_TADDR(x) (x)
|
||||
#elif LOG_BITS_PER_AU > LOG_TARGET_AU_BITS
|
||||
#define TADDR_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU-LOG_TARGET_AU_BITS))
|
||||
#define HOST_TO_TADDR(x) ((x) << (LOG_BITS_PER_AU-LOG_TARGET_AU_BITS))
|
||||
#else
|
||||
#define TADDR_TO_HOST(x) ((x) << (LOG_TARGET_AU_BITS-LOG_BITS_PER_AU))
|
||||
#define HOST_TO_TADDR(x) ((x) >> (LOG_TARGET_AU_BITS-LOG_BITS_PER_AU))
|
||||
#endif
|
||||
|
||||
#if LOG_BITS_PER_AU == LOG_TDATA_AU_BITS
|
||||
/* translate target addressable unit to host address */
|
||||
#define TDATA_TO_HOST(x) (x)
|
||||
/* translate host address to target addressable unit */
|
||||
#define HOST_TO_TDATA(x) (x)
|
||||
/* translate host address to target addressable unit, round up */
|
||||
#define HOST_TO_TDATA_ROUND(x) (x)
|
||||
/* byte offset to host offset, rounded up for TDATA size */
|
||||
#define BYTE_TO_HOST_TDATA_ROUND(x) BYTE_TO_HOST_ROUND(x)
|
||||
#elif LOG_BITS_PER_AU > LOG_TDATA_AU_BITS
|
||||
#define TDATA_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
|
||||
#define HOST_TO_TDATA(x) ((x) << (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
|
||||
#define HOST_TO_TDATA_ROUND(x) ((x) << (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
|
||||
#define BYTE_TO_HOST_TDATA_ROUND(x) BYTE_TO_HOST_ROUND(x)
|
||||
#else
|
||||
#define TDATA_TO_HOST(x) ((x) << (LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
|
||||
#define HOST_TO_TDATA(x) ((x) >> (LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
|
||||
#define HOST_TO_TDATA_ROUND(x) (((x) +\
|
||||
(1<<(LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))-1) >>\
|
||||
(LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
|
||||
#define BYTE_TO_HOST_TDATA_ROUND(x) (BYTE_TO_HOST((x) +\
|
||||
(1<<(LOG_TDATA_AU_BITS-LOG_BITS_PER_BYTE))-1) &\
|
||||
-(TDATA_AU_BITS/BITS_PER_AU))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Input in DOFF format is always expresed in bytes, regardless of loading host
|
||||
* so we wind up converting from bytes to target and host units even when the
|
||||
* host is not a byte machine.
|
||||
*/
|
||||
#if LOG_BITS_PER_AU == LOG_BITS_PER_BYTE
|
||||
#define BYTE_TO_HOST(x) (x)
|
||||
#define BYTE_TO_HOST_ROUND(x) (x)
|
||||
#define HOST_TO_BYTE(x) (x)
|
||||
#elif LOG_BITS_PER_AU >= LOG_BITS_PER_BYTE
|
||||
#define BYTE_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
|
||||
#define BYTE_TO_HOST_ROUND(x) ((x + (BITS_PER_AU/BITS_PER_BYTE-1)) >>\
|
||||
(LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
|
||||
#define HOST_TO_BYTE(x) ((x) << (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
|
||||
#else
|
||||
/* lets not try to deal with sub-8-bit byte machines */
|
||||
#endif
|
||||
|
||||
#if LOG_TARGET_AU_BITS == LOG_BITS_PER_BYTE
|
||||
/* translate target addressable unit to byte address */
|
||||
#define TADDR_TO_BYTE(x) (x)
|
||||
/* translate byte address to target addressable unit */
|
||||
#define BYTE_TO_TADDR(x) (x)
|
||||
#elif LOG_TARGET_AU_BITS > LOG_BITS_PER_BYTE
|
||||
#define TADDR_TO_BYTE(x) ((x) << (LOG_TARGET_AU_BITS-LOG_BITS_PER_BYTE))
|
||||
#define BYTE_TO_TADDR(x) ((x) >> (LOG_TARGET_AU_BITS-LOG_BITS_PER_BYTE))
|
||||
#else
|
||||
/* lets not try to deal with sub-8-bit byte machines */
|
||||
#endif
|
||||
|
||||
#ifdef _BIG_ENDIAN
|
||||
#define HOST_ENDIANNESS 1
|
||||
#else
|
||||
#define HOST_ENDIANNESS 0
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_ENDIANNESS
|
||||
#define TARGET_ENDIANNESS_DIFFERS(rtend) (HOST_ENDIANNESS^TARGET_ENDIANNESS)
|
||||
#elif HOST_ENDIANNESS
|
||||
#define TARGET_ENDIANNESS_DIFFERS(rtend) (!(rtend))
|
||||
#else
|
||||
#define TARGET_ENDIANNESS_DIFFERS(rtend) (rtend)
|
||||
#endif
|
||||
|
||||
/* the unit in which we process target image data */
|
||||
#if TARGET_AU_BITS <= 8
|
||||
typedef u8 tgt_au_t;
|
||||
#elif TARGET_AU_BITS <= 16
|
||||
typedef u16 tgt_au_t;
|
||||
#else
|
||||
typedef u32 tgt_au_t;
|
||||
#endif
|
||||
|
||||
/* size of that unit */
|
||||
#if TARGET_AU_BITS < BITS_PER_AU
|
||||
#define TGTAU_BITS BITS_PER_AU
|
||||
#define LOG_TGTAU_BITS LOG_BITS_PER_AU
|
||||
#else
|
||||
#define TGTAU_BITS TARGET_AU_BITS
|
||||
#define LOG_TGTAU_BITS LOG_TARGET_AU_BITS
|
||||
#endif
|
484
drivers/staging/tidspbridge/dynload/reloc.c
Normal file
484
drivers/staging/tidspbridge/dynload/reloc.c
Normal file
@ -0,0 +1,484 @@
|
||||
/*
|
||||
* reloc.c
|
||||
*
|
||||
* DSP-BIOS Bridge driver support functions for TI OMAP processors.
|
||||
*
|
||||
* Copyright (C) 2005-2006 Texas Instruments, Inc.
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#include "header.h"
|
||||
|
||||
#if TMS32060
|
||||
/* the magic symbol for the start of BSS */
|
||||
static const char bsssymbol[] = { ".bss" };
|
||||
#endif
|
||||
|
||||
#if TMS32060
|
||||
#include "reloc_table_c6000.c"
|
||||
#endif
|
||||
|
||||
#if TMS32060
|
||||
/* From coff.h - ignore these relocation operations */
|
||||
#define R_C60ALIGN 0x76 /* C60: Alignment info for compressor */
|
||||
#define R_C60FPHEAD 0x77 /* C60: Explicit assembly directive */
|
||||
#define R_C60NOCMP 0x100 /* C60: Don't compress this code scn */
|
||||
#endif
|
||||
|
||||
/**************************************************************************
|
||||
* Procedure dload_unpack
|
||||
*
|
||||
* Parameters:
|
||||
* data pointer to storage unit containing lowest host address of
|
||||
* image data
|
||||
* fieldsz Size of bit field, 0 < fieldsz <= sizeof(rvalue)*BITS_PER_AU
|
||||
* offset Offset from LSB, 0 <= offset < BITS_PER_AU
|
||||
* sgn Signedness of the field (ROP_SGN, ROP_UNS, ROP_MAX, ROP_ANY)
|
||||
*
|
||||
* Effect:
|
||||
* Extracts the specified field and returns it.
|
||||
************************************************************************* */
|
||||
rvalue dload_unpack(struct dload_state *dlthis, tgt_au_t * data, int fieldsz,
|
||||
int offset, unsigned sgn)
|
||||
{
|
||||
register rvalue objval;
|
||||
register int shift, direction;
|
||||
register tgt_au_t *dp = data;
|
||||
|
||||
fieldsz -= 1; /* avoid nastiness with 32-bit shift of 32-bit value */
|
||||
/* * collect up enough bits to contain the desired field */
|
||||
if (TARGET_BIG_ENDIAN) {
|
||||
dp += (fieldsz + offset) >> LOG_TGTAU_BITS;
|
||||
direction = -1;
|
||||
} else
|
||||
direction = 1;
|
||||
objval = *dp >> offset;
|
||||
shift = TGTAU_BITS - offset;
|
||||
while (shift <= fieldsz) {
|
||||
dp += direction;
|
||||
objval += (rvalue) *dp << shift;
|
||||
shift += TGTAU_BITS;
|
||||
}
|
||||
|
||||
/* * sign or zero extend the value appropriately */
|
||||
if (sgn == ROP_UNS)
|
||||
objval &= (2 << fieldsz) - 1;
|
||||
else {
|
||||
shift = sizeof(rvalue) * BITS_PER_AU - 1 - fieldsz;
|
||||
objval = (objval << shift) >> shift;
|
||||
}
|
||||
|
||||
return objval;
|
||||
|
||||
} /* dload_unpack */
|
||||
|
||||
/**************************************************************************
|
||||
* Procedure dload_repack
|
||||
*
|
||||
* Parameters:
|
||||
* val Value to insert
|
||||
* data Pointer to storage unit containing lowest host address of
|
||||
* image data
|
||||
* fieldsz Size of bit field, 0 < fieldsz <= sizeof(rvalue)*BITS_PER_AU
|
||||
* offset Offset from LSB, 0 <= offset < BITS_PER_AU
|
||||
* sgn Signedness of the field (ROP_SGN, ROP_UNS, ROP_MAX, ROP_ANY)
|
||||
*
|
||||
* Effect:
|
||||
* Stuffs the specified value in the specified field. Returns 0 for
|
||||
* success
|
||||
* or 1 if the value will not fit in the specified field according to the
|
||||
* specified signedness rule.
|
||||
************************************************************************* */
|
||||
static const unsigned char ovf_limit[] = { 1, 2, 2 };
|
||||
|
||||
int dload_repack(struct dload_state *dlthis, rvalue val, tgt_au_t * data,
|
||||
int fieldsz, int offset, unsigned sgn)
|
||||
{
|
||||
register urvalue objval, mask;
|
||||
register int shift, direction;
|
||||
register tgt_au_t *dp = data;
|
||||
|
||||
fieldsz -= 1; /* avoid nastiness with 32-bit shift of 32-bit value */
|
||||
/* clip the bits */
|
||||
mask = ((UINT32_C(2) << fieldsz) - 1);
|
||||
objval = (val & mask);
|
||||
/* * store the bits through the specified mask */
|
||||
if (TARGET_BIG_ENDIAN) {
|
||||
dp += (fieldsz + offset) >> LOG_TGTAU_BITS;
|
||||
direction = -1;
|
||||
} else
|
||||
direction = 1;
|
||||
|
||||
/* insert LSBs */
|
||||
*dp = (*dp & ~(mask << offset)) + (objval << offset);
|
||||
shift = TGTAU_BITS - offset;
|
||||
/* align mask and objval with AU boundary */
|
||||
objval >>= shift;
|
||||
mask >>= shift;
|
||||
|
||||
while (mask) {
|
||||
dp += direction;
|
||||
*dp = (*dp & ~mask) + objval;
|
||||
objval >>= TGTAU_BITS;
|
||||
mask >>= TGTAU_BITS;
|
||||
}
|
||||
|
||||
/*
|
||||
* check for overflow
|
||||
*/
|
||||
if (sgn) {
|
||||
unsigned tmp = (val >> fieldsz) + (sgn & 0x1);
|
||||
if (tmp > ovf_limit[sgn - 1])
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
} /* dload_repack */
|
||||
|
||||
/* lookup table for the scaling amount in a C6x instruction */
|
||||
#if TMS32060
|
||||
#define SCALE_BITS 4 /* there are 4 bits in the scale field */
|
||||
#define SCALE_MASK 0x7 /* we really only use the bottom 3 bits */
|
||||
static const u8 c60_scale[SCALE_MASK + 1] = {
|
||||
1, 0, 0, 0, 1, 1, 2, 2
|
||||
};
|
||||
#endif
|
||||
|
||||
/**************************************************************************
|
||||
* Procedure dload_relocate
|
||||
*
|
||||
* Parameters:
|
||||
* data Pointer to base of image data
|
||||
* rp Pointer to relocation operation
|
||||
*
|
||||
* Effect:
|
||||
* Performs the specified relocation operation
|
||||
************************************************************************* */
|
||||
void dload_relocate(struct dload_state *dlthis, tgt_au_t * data,
|
||||
struct reloc_record_t *rp, bool * tramps_genereted,
|
||||
bool second_pass)
|
||||
{
|
||||
rvalue val, reloc_amt, orig_val = 0;
|
||||
unsigned int fieldsz = 0;
|
||||
unsigned int offset = 0;
|
||||
unsigned int reloc_info = 0;
|
||||
unsigned int reloc_action = 0;
|
||||
register int rx = 0;
|
||||
rvalue *stackp = NULL;
|
||||
int top;
|
||||
struct local_symbol *svp = NULL;
|
||||
#ifdef RFV_SCALE
|
||||
unsigned int scale = 0;
|
||||
#endif
|
||||
struct image_packet_t *img_pkt = NULL;
|
||||
|
||||
/* The image packet data struct is only used during first pass
|
||||
* relocation in the event that a trampoline is needed. 2nd pass
|
||||
* relocation doesn't guarantee that data is coming from an
|
||||
* image_packet_t structure. See cload.c, dload_data for how img_data is
|
||||
* set. If that changes this needs to be updated!!! */
|
||||
if (second_pass == false)
|
||||
img_pkt = (struct image_packet_t *)((u8 *) data -
|
||||
sizeof(struct
|
||||
image_packet_t));
|
||||
|
||||
rx = HASH_FUNC(rp->TYPE);
|
||||
while (rop_map1[rx] != rp->TYPE) {
|
||||
rx = HASH_L(rop_map2[rx]);
|
||||
if (rx < 0) {
|
||||
#if TMS32060
|
||||
switch (rp->TYPE) {
|
||||
case R_C60ALIGN:
|
||||
case R_C60NOCMP:
|
||||
case R_C60FPHEAD:
|
||||
/* Ignore these reloc types and return */
|
||||
break;
|
||||
default:
|
||||
/* Unknown reloc type, print error and return */
|
||||
dload_error(dlthis, "Bad coff operator 0x%x",
|
||||
rp->TYPE);
|
||||
}
|
||||
#else
|
||||
dload_error(dlthis, "Bad coff operator 0x%x", rp->TYPE);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
rx = HASH_I(rop_map2[rx]);
|
||||
if ((rx < (sizeof(rop_action) / sizeof(u16)))
|
||||
&& (rx < (sizeof(rop_info) / sizeof(u16))) && (rx > 0)) {
|
||||
reloc_action = rop_action[rx];
|
||||
reloc_info = rop_info[rx];
|
||||
} else {
|
||||
dload_error(dlthis, "Buffer Overflow - Array Index Out "
|
||||
"of Bounds");
|
||||
}
|
||||
|
||||
/* Compute the relocation amount for the referenced symbol, if any */
|
||||
reloc_amt = rp->UVAL;
|
||||
if (RFV_SYM(reloc_info)) { /* relocation uses a symbol reference */
|
||||
/* If this is first pass, use the module local symbol table,
|
||||
* else use the trampoline symbol table. */
|
||||
if (second_pass == false) {
|
||||
if ((u32) rp->SYMNDX < dlthis->dfile_hdr.df_no_syms) {
|
||||
/* real symbol reference */
|
||||
svp = &dlthis->local_symtab[rp->SYMNDX];
|
||||
reloc_amt = (RFV_SYM(reloc_info) == ROP_SYMD) ?
|
||||
svp->delta : svp->value;
|
||||
}
|
||||
/* reloc references current section */
|
||||
else if (rp->SYMNDX == -1) {
|
||||
reloc_amt = (RFV_SYM(reloc_info) == ROP_SYMD) ?
|
||||
dlthis->delta_runaddr :
|
||||
dlthis->image_secn->run_addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* relocation uses a symbol reference */
|
||||
/* Handle stack adjustment */
|
||||
val = 0;
|
||||
top = RFV_STK(reloc_info);
|
||||
if (top) {
|
||||
top += dlthis->relstkidx - RSTK_UOP;
|
||||
if (top >= STATIC_EXPR_STK_SIZE) {
|
||||
dload_error(dlthis,
|
||||
"Expression stack overflow in %s at offset "
|
||||
FMT_UI32, dlthis->image_secn->name,
|
||||
rp->vaddr + dlthis->image_offset);
|
||||
return;
|
||||
}
|
||||
val = dlthis->relstk[dlthis->relstkidx];
|
||||
dlthis->relstkidx = top;
|
||||
stackp = &dlthis->relstk[top];
|
||||
}
|
||||
/* Derive field position and size, if we need them */
|
||||
if (reloc_info & ROP_RW) { /* read or write action in our future */
|
||||
fieldsz = RFV_WIDTH(reloc_action);
|
||||
if (fieldsz) { /* field info from table */
|
||||
offset = RFV_POSN(reloc_action);
|
||||
if (TARGET_BIG_ENDIAN)
|
||||
/* make sure vaddr is the lowest target
|
||||
* address containing bits */
|
||||
rp->vaddr += RFV_BIGOFF(reloc_info);
|
||||
} else { /* field info from relocation op */
|
||||
fieldsz = rp->FIELDSZ;
|
||||
offset = rp->OFFSET;
|
||||
if (TARGET_BIG_ENDIAN)
|
||||
/* make sure vaddr is the lowest target
|
||||
address containing bits */
|
||||
rp->vaddr += (rp->WORDSZ - offset - fieldsz)
|
||||
>> LOG_TARGET_AU_BITS;
|
||||
}
|
||||
data = (tgt_au_t *) ((char *)data + TADDR_TO_HOST(rp->vaddr));
|
||||
/* compute lowest host location of referenced data */
|
||||
#if BITS_PER_AU > TARGET_AU_BITS
|
||||
/* conversion from target address to host address may lose
|
||||
address bits; add loss to offset */
|
||||
if (TARGET_BIG_ENDIAN) {
|
||||
offset += -((rp->vaddr << LOG_TARGET_AU_BITS) +
|
||||
offset + fieldsz) &
|
||||
(BITS_PER_AU - TARGET_AU_BITS);
|
||||
} else {
|
||||
offset += (rp->vaddr << LOG_TARGET_AU_BITS) &
|
||||
(BITS_PER_AU - 1);
|
||||
}
|
||||
#endif
|
||||
#ifdef RFV_SCALE
|
||||
scale = RFV_SCALE(reloc_info);
|
||||
#endif
|
||||
}
|
||||
/* read the object value from the current image, if so ordered */
|
||||
if (reloc_info & ROP_R) {
|
||||
/* relocation reads current image value */
|
||||
val = dload_unpack(dlthis, data, fieldsz, offset,
|
||||
RFV_SIGN(reloc_info));
|
||||
/* Save off the original value in case the relo overflows and
|
||||
* we can trampoline it. */
|
||||
orig_val = val;
|
||||
|
||||
#ifdef RFV_SCALE
|
||||
val <<= scale;
|
||||
#endif
|
||||
}
|
||||
/* perform the necessary arithmetic */
|
||||
switch (RFV_ACTION(reloc_action)) { /* relocation actions */
|
||||
case RACT_VAL:
|
||||
break;
|
||||
case RACT_ASGN:
|
||||
val = reloc_amt;
|
||||
break;
|
||||
case RACT_ADD:
|
||||
val += reloc_amt;
|
||||
break;
|
||||
case RACT_PCR:
|
||||
/*-----------------------------------------------------------
|
||||
* Handle special cases of jumping from absolute sections
|
||||
* (special reloc type) or to absolute destination
|
||||
* (symndx == -1). In either case, set the appropriate
|
||||
* relocation amount to 0.
|
||||
*----------------------------------------------------------- */
|
||||
if (rp->SYMNDX == -1)
|
||||
reloc_amt = 0;
|
||||
val += reloc_amt - dlthis->delta_runaddr;
|
||||
break;
|
||||
case RACT_ADDISP:
|
||||
val += rp->R_DISP + reloc_amt;
|
||||
break;
|
||||
case RACT_ASGPC:
|
||||
val = dlthis->image_secn->run_addr + reloc_amt;
|
||||
break;
|
||||
case RACT_PLUS:
|
||||
if (stackp != NULL)
|
||||
val += *stackp;
|
||||
break;
|
||||
case RACT_SUB:
|
||||
if (stackp != NULL)
|
||||
val = *stackp - val;
|
||||
break;
|
||||
case RACT_NEG:
|
||||
val = -val;
|
||||
break;
|
||||
case RACT_MPY:
|
||||
if (stackp != NULL)
|
||||
val *= *stackp;
|
||||
break;
|
||||
case RACT_DIV:
|
||||
if (stackp != NULL)
|
||||
val = *stackp / val;
|
||||
break;
|
||||
case RACT_MOD:
|
||||
if (stackp != NULL)
|
||||
val = *stackp % val;
|
||||
break;
|
||||
case RACT_SR:
|
||||
if (val >= sizeof(rvalue) * BITS_PER_AU)
|
||||
val = 0;
|
||||
else if (stackp != NULL)
|
||||
val = (urvalue) *stackp >> val;
|
||||
break;
|
||||
case RACT_ASR:
|
||||
if (val >= sizeof(rvalue) * BITS_PER_AU)
|
||||
val = sizeof(rvalue) * BITS_PER_AU - 1;
|
||||
else if (stackp != NULL)
|
||||
val = *stackp >> val;
|
||||
break;
|
||||
case RACT_SL:
|
||||
if (val >= sizeof(rvalue) * BITS_PER_AU)
|
||||
val = 0;
|
||||
else if (stackp != NULL)
|
||||
val = *stackp << val;
|
||||
break;
|
||||
case RACT_AND:
|
||||
if (stackp != NULL)
|
||||
val &= *stackp;
|
||||
break;
|
||||
case RACT_OR:
|
||||
if (stackp != NULL)
|
||||
val |= *stackp;
|
||||
break;
|
||||
case RACT_XOR:
|
||||
if (stackp != NULL)
|
||||
val ^= *stackp;
|
||||
break;
|
||||
case RACT_NOT:
|
||||
val = ~val;
|
||||
break;
|
||||
#if TMS32060
|
||||
case RACT_C6SECT:
|
||||
/* actually needed address of secn containing symbol */
|
||||
if (svp != NULL) {
|
||||
if (rp->SYMNDX >= 0)
|
||||
if (svp->secnn > 0)
|
||||
reloc_amt = dlthis->ldr_sections
|
||||
[svp->secnn - 1].run_addr;
|
||||
}
|
||||
/* !!! FALL THRU !!! */
|
||||
case RACT_C6BASE:
|
||||
if (dlthis->bss_run_base == 0) {
|
||||
struct dynload_symbol *symp;
|
||||
symp = dlthis->mysym->find_matching_symbol
|
||||
(dlthis->mysym, bsssymbol);
|
||||
/* lookup value of global BSS base */
|
||||
if (symp)
|
||||
dlthis->bss_run_base = symp->value;
|
||||
else
|
||||
dload_error(dlthis,
|
||||
"Global BSS base referenced in %s "
|
||||
"offset" FMT_UI32 " but not "
|
||||
"defined",
|
||||
dlthis->image_secn->name,
|
||||
rp->vaddr + dlthis->image_offset);
|
||||
}
|
||||
reloc_amt -= dlthis->bss_run_base;
|
||||
/* !!! FALL THRU !!! */
|
||||
case RACT_C6DSPL:
|
||||
/* scale factor determined by 3 LSBs of field */
|
||||
scale = c60_scale[val & SCALE_MASK];
|
||||
offset += SCALE_BITS;
|
||||
fieldsz -= SCALE_BITS;
|
||||
val >>= SCALE_BITS; /* ignore the scale field hereafter */
|
||||
val <<= scale;
|
||||
val += reloc_amt; /* do the usual relocation */
|
||||
if (((1 << scale) - 1) & val)
|
||||
dload_error(dlthis,
|
||||
"Unaligned reference in %s offset "
|
||||
FMT_UI32, dlthis->image_secn->name,
|
||||
rp->vaddr + dlthis->image_offset);
|
||||
break;
|
||||
#endif
|
||||
} /* relocation actions */
|
||||
/* * Put back result as required */
|
||||
if (reloc_info & ROP_W) { /* relocation writes image value */
|
||||
#ifdef RFV_SCALE
|
||||
val >>= scale;
|
||||
#endif
|
||||
if (dload_repack(dlthis, val, data, fieldsz, offset,
|
||||
RFV_SIGN(reloc_info))) {
|
||||
/* Check to see if this relo can be trampolined,
|
||||
* but only in first phase relocation. 2nd phase
|
||||
* relocation cannot trampoline. */
|
||||
if ((second_pass == false) &&
|
||||
(dload_tramp_avail(dlthis, rp) == true)) {
|
||||
|
||||
/* Before generating the trampoline, restore
|
||||
* the value to its original so the 2nd pass
|
||||
* relo will work. */
|
||||
dload_repack(dlthis, orig_val, data, fieldsz,
|
||||
offset, RFV_SIGN(reloc_info));
|
||||
if (!dload_tramp_generate(dlthis,
|
||||
(dlthis->image_secn -
|
||||
dlthis->ldr_sections),
|
||||
dlthis->image_offset,
|
||||
img_pkt, rp)) {
|
||||
dload_error(dlthis,
|
||||
"Failed to "
|
||||
"generate trampoline for "
|
||||
"bit overflow");
|
||||
dload_error(dlthis,
|
||||
"Relocation val " FMT_UI32
|
||||
" overflows %d bits in %s "
|
||||
"offset " FMT_UI32, val,
|
||||
fieldsz,
|
||||
dlthis->image_secn->name,
|
||||
dlthis->image_offset +
|
||||
rp->vaddr);
|
||||
} else
|
||||
*tramps_genereted = true;
|
||||
} else {
|
||||
dload_error(dlthis, "Relocation value "
|
||||
FMT_UI32 " overflows %d bits in %s"
|
||||
" offset " FMT_UI32, val, fieldsz,
|
||||
dlthis->image_secn->name,
|
||||
dlthis->image_offset + rp->vaddr);
|
||||
}
|
||||
}
|
||||
} else if (top)
|
||||
*stackp = val;
|
||||
} /* reloc_value */
|
102
drivers/staging/tidspbridge/dynload/reloc_table.h
Normal file
102
drivers/staging/tidspbridge/dynload/reloc_table.h
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* reloc_table.h
|
||||
*
|
||||
* DSP-BIOS Bridge driver support functions for TI OMAP processors.
|
||||
*
|
||||
* Copyright (C) 2005-2006 Texas Instruments, Inc.
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef _RELOC_TABLE_H_
|
||||
#define _RELOC_TABLE_H_
|
||||
/*
|
||||
* Table of relocation operator properties
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
|
||||
/* How does this relocation operation access the program image? */
|
||||
#define ROP_N 0 /* does not access image */
|
||||
#define ROP_R 1 /* read from image */
|
||||
#define ROP_W 2 /* write to image */
|
||||
#define ROP_RW 3 /* read from and write to image */
|
||||
|
||||
/* For program image access, what are the overflow rules for the bit field? */
|
||||
/* Beware! Procedure repack depends on this encoding */
|
||||
#define ROP_ANY 0 /* no overflow ever, just truncate the value */
|
||||
#define ROP_SGN 1 /* signed field */
|
||||
#define ROP_UNS 2 /* unsigned field */
|
||||
#define ROP_MAX 3 /* allow maximum range of either signed or unsigned */
|
||||
|
||||
/* How does the relocation operation use the symbol reference */
|
||||
#define ROP_IGN 0 /* no symbol is referenced */
|
||||
#define ROP_LIT 0 /* use rp->UVAL literal field */
|
||||
#define ROP_SYM 1 /* symbol value is used in relocation */
|
||||
#define ROP_SYMD 2 /* delta value vs last link is used */
|
||||
|
||||
/* How does the reloc op use the stack? */
|
||||
#define RSTK_N 0 /* Does not use */
|
||||
#define RSTK_POP 1 /* Does a POP */
|
||||
#define RSTK_UOP 2 /* Unary op, stack position unaffected */
|
||||
#define RSTK_PSH 3 /* Does a push */
|
||||
|
||||
/*
|
||||
* Computational actions performed by the dynamic loader
|
||||
*/
|
||||
enum dload_actions {
|
||||
/* don't alter the current val (from stack or mem fetch) */
|
||||
RACT_VAL,
|
||||
/* set value to reference amount (from symbol reference) */
|
||||
RACT_ASGN,
|
||||
RACT_ADD, /* add reference to value */
|
||||
RACT_PCR, /* add reference minus PC delta to value */
|
||||
RACT_ADDISP, /* add reference plus R_DISP */
|
||||
RACT_ASGPC, /* set value to section addr plus reference */
|
||||
|
||||
RACT_PLUS, /* stack + */
|
||||
RACT_SUB, /* stack - */
|
||||
RACT_NEG, /* stack unary - */
|
||||
|
||||
RACT_MPY, /* stack * */
|
||||
RACT_DIV, /* stack / */
|
||||
RACT_MOD, /* stack % */
|
||||
|
||||
RACT_SR, /* stack unsigned >> */
|
||||
RACT_ASR, /* stack signed >> */
|
||||
RACT_SL, /* stack << */
|
||||
RACT_AND, /* stack & */
|
||||
RACT_OR, /* stack | */
|
||||
RACT_XOR, /* stack ^ */
|
||||
RACT_NOT, /* stack ~ */
|
||||
RACT_C6SECT, /* for C60 R_SECT op */
|
||||
RACT_C6BASE, /* for C60 R_BASE op */
|
||||
RACT_C6DSPL, /* for C60 scaled 15-bit displacement */
|
||||
RACT_PCR23T /* for ARM Thumb long branch */
|
||||
};
|
||||
|
||||
/*
|
||||
* macros used to extract values
|
||||
*/
|
||||
#define RFV_POSN(aaa) ((aaa) & 0xF)
|
||||
#define RFV_WIDTH(aaa) (((aaa) >> 4) & 0x3F)
|
||||
#define RFV_ACTION(aaa) ((aaa) >> 10)
|
||||
|
||||
#define RFV_SIGN(iii) (((iii) >> 2) & 0x3)
|
||||
#define RFV_SYM(iii) (((iii) >> 4) & 0x3)
|
||||
#define RFV_STK(iii) (((iii) >> 6) & 0x3)
|
||||
#define RFV_ACCS(iii) ((iii) & 0x3)
|
||||
|
||||
#if (TMS32060)
|
||||
#define RFV_SCALE(iii) ((iii) >> 11)
|
||||
#define RFV_BIGOFF(iii) (((iii) >> 8) & 0x7)
|
||||
#else
|
||||
#define RFV_BIGOFF(iii) ((iii) >> 8)
|
||||
#endif
|
||||
|
||||
#endif /* _RELOC_TABLE_H_ */
|
257
drivers/staging/tidspbridge/dynload/reloc_table_c6000.c
Normal file
257
drivers/staging/tidspbridge/dynload/reloc_table_c6000.c
Normal file
@ -0,0 +1,257 @@
|
||||
/*
|
||||
* reloc_table_c6000.c
|
||||
*
|
||||
* DSP-BIOS Bridge driver support functions for TI OMAP processors.
|
||||
*
|
||||
* Copyright (C) 2005-2006 Texas Instruments, Inc.
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/* Tables generated for c6000 */
|
||||
|
||||
#define HASH_FUNC(zz) (((((zz) + 1) * UINT32_C(1845)) >> 11) & 63)
|
||||
#define HASH_L(zz) ((zz) >> 8)
|
||||
#define HASH_I(zz) ((zz) & 0xFF)
|
||||
|
||||
static const u16 rop_map1[] = {
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
20,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
15,
|
||||
80,
|
||||
81,
|
||||
82,
|
||||
83,
|
||||
84,
|
||||
85,
|
||||
86,
|
||||
87,
|
||||
17,
|
||||
18,
|
||||
19,
|
||||
21,
|
||||
16,
|
||||
16394,
|
||||
16404,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
32,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
40,
|
||||
112,
|
||||
113,
|
||||
65535,
|
||||
16384,
|
||||
16385,
|
||||
16386,
|
||||
16387,
|
||||
16388,
|
||||
16389,
|
||||
16390,
|
||||
16391,
|
||||
16392,
|
||||
16393,
|
||||
16395,
|
||||
16396,
|
||||
16397,
|
||||
16398,
|
||||
16399,
|
||||
16400,
|
||||
16401,
|
||||
16402,
|
||||
16403,
|
||||
16405,
|
||||
16406,
|
||||
65535,
|
||||
65535,
|
||||
65535
|
||||
};
|
||||
|
||||
static const s16 rop_map2[] = {
|
||||
-256,
|
||||
-255,
|
||||
-254,
|
||||
-245,
|
||||
-253,
|
||||
-252,
|
||||
-251,
|
||||
-250,
|
||||
-241,
|
||||
-240,
|
||||
-239,
|
||||
-238,
|
||||
-237,
|
||||
-236,
|
||||
1813,
|
||||
5142,
|
||||
-248,
|
||||
-247,
|
||||
778,
|
||||
-244,
|
||||
-249,
|
||||
-221,
|
||||
-211,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-243,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-242,
|
||||
-233,
|
||||
-232,
|
||||
-1,
|
||||
-231,
|
||||
-230,
|
||||
-229,
|
||||
-228,
|
||||
-227,
|
||||
-226,
|
||||
-225,
|
||||
-224,
|
||||
-223,
|
||||
5410,
|
||||
-220,
|
||||
-219,
|
||||
-218,
|
||||
-217,
|
||||
-216,
|
||||
-215,
|
||||
-214,
|
||||
-213,
|
||||
5676,
|
||||
-210,
|
||||
-209,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
static const u16 rop_action[] = {
|
||||
2560,
|
||||
2304,
|
||||
2304,
|
||||
2432,
|
||||
2432,
|
||||
2560,
|
||||
2176,
|
||||
2304,
|
||||
2560,
|
||||
3200,
|
||||
3328,
|
||||
3584,
|
||||
3456,
|
||||
2304,
|
||||
4208,
|
||||
20788,
|
||||
21812,
|
||||
3415,
|
||||
3245,
|
||||
2311,
|
||||
4359,
|
||||
19764,
|
||||
2311,
|
||||
3191,
|
||||
3280,
|
||||
6656,
|
||||
7680,
|
||||
8704,
|
||||
9728,
|
||||
10752,
|
||||
11776,
|
||||
12800,
|
||||
13824,
|
||||
14848,
|
||||
15872,
|
||||
16896,
|
||||
17920,
|
||||
18944,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1536,
|
||||
1536,
|
||||
1536,
|
||||
5632,
|
||||
512,
|
||||
0
|
||||
};
|
||||
|
||||
static const u16 rop_info[] = {
|
||||
0,
|
||||
35,
|
||||
35,
|
||||
35,
|
||||
35,
|
||||
35,
|
||||
35,
|
||||
35,
|
||||
35,
|
||||
39,
|
||||
39,
|
||||
39,
|
||||
39,
|
||||
35,
|
||||
34,
|
||||
283,
|
||||
299,
|
||||
4135,
|
||||
4391,
|
||||
291,
|
||||
33059,
|
||||
283,
|
||||
295,
|
||||
4647,
|
||||
4135,
|
||||
64,
|
||||
64,
|
||||
128,
|
||||
64,
|
||||
64,
|
||||
64,
|
||||
64,
|
||||
64,
|
||||
64,
|
||||
64,
|
||||
64,
|
||||
64,
|
||||
128,
|
||||
201,
|
||||
197,
|
||||
74,
|
||||
70,
|
||||
208,
|
||||
196,
|
||||
200,
|
||||
192,
|
||||
192,
|
||||
66
|
||||
};
|
1143
drivers/staging/tidspbridge/dynload/tramp.c
Normal file
1143
drivers/staging/tidspbridge/dynload/tramp.c
Normal file
File diff suppressed because it is too large
Load Diff
164
drivers/staging/tidspbridge/dynload/tramp_table_c6000.c
Normal file
164
drivers/staging/tidspbridge/dynload/tramp_table_c6000.c
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
* tramp_table_c6000.c
|
||||
*
|
||||
* DSP-BIOS Bridge driver support functions for TI OMAP processors.
|
||||
*
|
||||
* Copyright (C) 2005-2006 Texas Instruments, Inc.
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#include "dload_internal.h"
|
||||
|
||||
/* These are defined in coff.h, but may not be available on all platforms
|
||||
so we'll go ahead and define them here. */
|
||||
#ifndef R_C60LO16
|
||||
#define R_C60LO16 0x54 /* C60: MVK Low Half Register */
|
||||
#define R_C60HI16 0x55 /* C60: MVKH/MVKLH High Half Register */
|
||||
#endif
|
||||
|
||||
#define C6X_TRAMP_WORD_COUNT 8
|
||||
#define C6X_TRAMP_MAX_RELOS 8
|
||||
|
||||
/* THIS HASH FUNCTION MUST MATCH THE ONE IN reloc_table_c6000.c */
|
||||
#define HASH_FUNC(zz) (((((zz) + 1) * UINT32_C(1845)) >> 11) & 63)
|
||||
|
||||
/* THIS MUST MATCH reloc_record_t FOR A SYMBOL BASED RELO */
|
||||
struct c6000_relo_record {
|
||||
s32 vaddr;
|
||||
s32 symndx;
|
||||
#ifndef _BIG_ENDIAN
|
||||
u16 disp;
|
||||
u16 type;
|
||||
#else
|
||||
u16 type;
|
||||
u16 disp;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct c6000_gen_code {
|
||||
struct tramp_gen_code_hdr hdr;
|
||||
u32 tramp_instrs[C6X_TRAMP_WORD_COUNT];
|
||||
struct c6000_relo_record relos[C6X_TRAMP_MAX_RELOS];
|
||||
};
|
||||
|
||||
/* Hash mapping for relos that can cause trampolines. */
|
||||
static const u16 tramp_map[] = {
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
0,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
65535
|
||||
};
|
||||
|
||||
static const struct c6000_gen_code tramp_gen_info[] = {
|
||||
/* Tramp caused by R_C60PCR21 */
|
||||
{
|
||||
/* Header - 8 instructions, 2 relos */
|
||||
{
|
||||
sizeof(u32) * C6X_TRAMP_WORD_COUNT,
|
||||
2,
|
||||
FIELD_OFFSET(struct c6000_gen_code, relos)
|
||||
},
|
||||
|
||||
/* Trampoline instructions */
|
||||
{
|
||||
0x053C54F7, /* STW.D2T2 B10, *sp--[2] */
|
||||
0x0500002A, /* || MVK.S2 <blank>, B10 */
|
||||
0x0500006A, /* MVKH.S2 <blank>, B10 */
|
||||
0x00280362, /* B.S2 B10 */
|
||||
0x053C52E6, /* LDW.D2T2 *++sp[2], B10 */
|
||||
0x00006000, /* NOP 4 */
|
||||
0x00000000, /* NOP */
|
||||
0x00000000 /* NOP */
|
||||
},
|
||||
|
||||
/* Relocations */
|
||||
{
|
||||
{4, 0, 0, R_C60LO16},
|
||||
{8, 0, 0, R_C60HI16},
|
||||
{0, 0, 0, 0x0000},
|
||||
{0, 0, 0, 0x0000},
|
||||
{0, 0, 0, 0x0000},
|
||||
{0, 0, 0, 0x0000},
|
||||
{0, 0, 0, 0x0000},
|
||||
{0, 0, 0, 0x0000}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* TARGET SPECIFIC FUNCTIONS THAT MUST BE DEFINED */
|
||||
static u32 tramp_size_get(void)
|
||||
{
|
||||
return sizeof(u32) * C6X_TRAMP_WORD_COUNT;
|
||||
}
|
||||
|
||||
static u32 tramp_img_pkt_size_get(void)
|
||||
{
|
||||
return sizeof(struct c6000_gen_code);
|
||||
}
|
Loading…
Reference in New Issue
Block a user