2
0
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:
Omar Ramirez Luna 2010-06-23 16:02:02 +03:00 committed by Greg Kroah-Hartman
parent 6a88a4fe09
commit 26f8db7d2e
12 changed files with 5661 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View 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_ */

View 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 */

View 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);
}

View 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)

View 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_ */

View 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

View 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 */

View 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_ */

View 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
};

File diff suppressed because it is too large Load Diff

View 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);
}