blob: b9d079b961905315d8832c7e4fc0eb6d92cb7daf [file] [log] [blame]
/*
* 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
*/
/* 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 *next; /* 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 *next, *prev;
struct dbg_mirror_root *root;
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
/*
* 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_ */