staging: ti dspbridge: add DOFF binaries loader
[pandora-kernel.git] / drivers / staging / tidspbridge / dynload / dload_internal.h
1 /*
2  * dload_internal.h
3  *
4  * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5  *
6  * Copyright (C) 2005-2006 Texas Instruments, Inc.
7  *
8  * This package is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15  */
16
17 #ifndef _DLOAD_INTERNAL_
18 #define _DLOAD_INTERNAL_
19
20 #include <linux/types.h>
21
22 /*
23  * Internal state definitions for the dynamic loader
24  */
25
26 #define TRUE 1
27 #define FALSE 0
28
29 /* type used for relocation intermediate results */
30 typedef s32 rvalue;
31
32 /* unsigned version of same; must have at least as many bits */
33 typedef u32 urvalue;
34
35 /*
36  * Dynamic loader configuration constants
37  */
38 /* error issued if input has more sections than this limit */
39 #define REASONABLE_SECTION_LIMIT 100
40
41 /* (Addressable unit) value used to clear BSS section */
42 #define DLOAD_FILL_BSS 0
43
44 /*
45  * Reorder maps explained (?)
46  *
47  * The doff file format defines a 32-bit pattern used to determine the
48  * byte order of an image being read.  That value is
49  * BYTE_RESHUFFLE_VALUE == 0x00010203
50  * For purposes of the reorder routine, we would rather have the all-is-OK
51  * for 32-bits pattern be 0x03020100.  This first macro makes the
52  * translation from doff file header value to MAP value: */
53 #define REORDER_MAP(rawmap) ((rawmap) ^ 0x3030303)
54 /* This translation is made in dload_headers.  Thereafter, the all-is-OK
55  * value for the maps stored in dlthis is REORDER_MAP(BYTE_RESHUFFLE_VALUE).
56  * But sadly, not all bits of the doff file are 32-bit integers.
57  * The notable exceptions are strings and image bits.
58  * Strings obey host byte order: */
59 #if defined(_BIG_ENDIAN)
60 #define HOST_BYTE_ORDER(cookedmap) ((cookedmap) ^ 0x3030303)
61 #else
62 #define HOST_BYTE_ORDER(cookedmap) (cookedmap)
63 #endif
64 /* Target bits consist of target AUs (could be bytes, or 16-bits,
65  * or 32-bits) stored as an array in host order.  A target order
66  * map is defined by: */
67 #if !defined(_BIG_ENDIAN) || TARGET_AU_BITS > 16
68 #define TARGET_ORDER(cookedmap) (cookedmap)
69 #elif TARGET_AU_BITS > 8
70 #define TARGET_ORDER(cookedmap) ((cookedmap) ^ 0x2020202)
71 #else
72 #define TARGET_ORDER(cookedmap) ((cookedmap) ^ 0x3030303)
73 #endif
74
75 /* forward declaration for handle returned by dynamic loader */
76 struct my_handle;
77
78 /*
79  * a list of module handles, which mirrors the debug list on the target
80  */
81 struct dbg_mirror_root {
82         /* must be same as dbg_mirror_list; __DLModules address on target */
83         u32 dbthis;
84         struct my_handle *hnext;        /* must be same as dbg_mirror_list */
85         u16 changes;            /* change counter */
86         u16 refcount;           /* number of modules referencing this root */
87 };
88
89 struct dbg_mirror_list {
90         u32 dbthis;
91         struct my_handle *hnext, *hprev;
92         struct dbg_mirror_root *hroot;
93         u16 dbsiz;
94         u32 context;    /* Save context for .dllview memory allocation */
95 };
96
97 #define VARIABLE_SIZE 1
98 /*
99  * the structure we actually return as an opaque module handle
100  */
101 struct my_handle {
102         struct dbg_mirror_list dm;      /* !!! must be first !!! */
103         /* sections following << 1, LSB is set for big-endian target */
104         u16 secn_count;
105         struct ldr_section_info secns[VARIABLE_SIZE];
106 };
107 #define MY_HANDLE_SIZE (sizeof(struct my_handle) -\
108                         sizeof(struct ldr_section_info))
109 /* real size of my_handle */
110
111 /*
112  * reduced symbol structure used for symbols during relocation
113  */
114 struct local_symbol {
115         s32 value;              /* Relocated symbol value */
116         s32 delta;              /* Original value in input file */
117         s16 secnn;              /* section number */
118         s16 sclass;             /* symbol class */
119 };
120
121 /*
122  * Trampoline data structures
123  */
124 #define TRAMP_NO_GEN_AVAIL              65535
125 #define TRAMP_SYM_PREFIX                "__$dbTR__"
126 #define TRAMP_SECT_NAME                 ".dbTR"
127 /* MUST MATCH THE LENGTH ABOVE!! */
128 #define TRAMP_SYM_PREFIX_LEN            9
129 /* Includes NULL termination */
130 #define TRAMP_SYM_HEX_ASCII_LEN         9
131
132 #define GET_CONTAINER(ptr, type, field) ((type *)((unsigned long)ptr -\
133                                 (unsigned long)(&((type *)0)->field)))
134 #ifndef FIELD_OFFSET
135 #define FIELD_OFFSET(type, field)       ((unsigned long)(&((type *)0)->field))
136 #endif
137
138 /*
139     The trampoline code for the target is located in a table called
140     "tramp_gen_info" with is indexed by looking up the index in the table
141     "tramp_map".  The tramp_map index is acquired using the target
142     HASH_FUNC on the relocation type that caused the trampoline.  Each
143     trampoline code table entry MUST follow this format:
144
145     |----------------------------------------------|
146     |  tramp_gen_code_hdr                          |
147     |----------------------------------------------|
148     |  Trampoline image code                       |
149     |  (the raw instruction code for the target)   |
150     |----------------------------------------------|
151     |  Relocation entries for the image code       |
152     |----------------------------------------------|
153
154     This is very similar to how image data is laid out in the DOFF file
155     itself.
156  */
157 struct tramp_gen_code_hdr {
158         u32 tramp_code_size;    /*  in BYTES */
159         u32 num_relos;
160         u32 relo_offset;        /*  in BYTES */
161 };
162
163 struct tramp_img_pkt {
164         struct tramp_img_pkt *next;     /*  MUST BE FIRST */
165         u32 base;
166         struct tramp_gen_code_hdr hdr;
167         u8 payload[VARIABLE_SIZE];
168 };
169
170 struct tramp_img_dup_relo {
171         struct tramp_img_dup_relo *next;
172         struct reloc_record_t relo;
173 };
174
175 struct tramp_img_dup_pkt {
176         struct tramp_img_dup_pkt *next; /*  MUST BE FIRST */
177         s16 secnn;
178         u32 offset;
179         struct image_packet_t img_pkt;
180         struct tramp_img_dup_relo *relo_chain;
181
182         /*  PAYLOAD OF IMG PKT FOLLOWS */
183 };
184
185 struct tramp_sym {
186         struct tramp_sym *next; /*  MUST BE FIRST */
187         u32 index;
188         u32 str_index;
189         struct local_symbol sym_info;
190 };
191
192 struct tramp_string {
193         struct tramp_string *next;      /*  MUST BE FIRST */
194         u32 index;
195         char str[VARIABLE_SIZE];        /*  NULL terminated */
196 };
197
198 struct tramp_info {
199         u32 tramp_sect_next_addr;
200         struct ldr_section_info sect_info;
201
202         struct tramp_sym *symbol_head;
203         struct tramp_sym *symbol_tail;
204         u32 tramp_sym_next_index;
205         struct local_symbol *final_sym_table;
206
207         struct tramp_string *string_head;
208         struct tramp_string *string_tail;
209         u32 tramp_string_next_index;
210         u32 tramp_string_size;
211         char *final_string_table;
212
213         struct tramp_img_pkt *tramp_pkts;
214         struct tramp_img_dup_pkt *dup_pkts;
215 };
216
217 /*
218  * States of the .cinit state machine
219  */
220 enum cinit_mode {
221         CI_COUNT = 0,           /* expecting a count */
222         CI_ADDRESS,             /* expecting an address */
223 #if CINIT_ALIGN < CINIT_ADDRESS /* handle case of partial address field */
224         CI_PARTADDRESS,         /* have only part of the address */
225 #endif
226         CI_COPY,                /* in the middle of copying data */
227         CI_DONE                 /* end of .cinit table */
228 };
229
230 /*
231  * The internal state of the dynamic loader, which is passed around as
232  * an object
233  */
234 struct dload_state {
235         struct dynamic_loader_stream *strm;     /* The module input stream */
236         struct dynamic_loader_sym *mysym;       /* Symbols for this session */
237         /* target memory allocator */
238         struct dynamic_loader_allocate *myalloc;
239         struct dynamic_loader_initialize *myio; /* target memory initializer */
240         unsigned myoptions;     /* Options parameter dynamic_load_module */
241
242         char *str_head;         /* Pointer to string table */
243 #if BITS_PER_AU > BITS_PER_BYTE
244         char *str_temp;         /* Pointer to temporary buffer for strings */
245         /* big enough to hold longest string */
246         unsigned temp_len;      /* length of last temporary string */
247         char *xstrings;         /* Pointer to buffer for expanded */
248         /* strings for sec names */
249 #endif
250         /* Total size of strings for DLLView section names */
251         unsigned debug_string_size;
252         /* Pointer to parallel section info for allocated sections only */
253         struct doff_scnhdr_t *sect_hdrs;        /* Pointer to section table */
254         struct ldr_section_info *ldr_sections;
255 #if TMS32060
256         /* The address of the start of the .bss section */
257         ldr_addr bss_run_base;
258 #endif
259         struct local_symbol *local_symtab;      /* Relocation symbol table */
260
261         /* pointer to DL section info for the section being relocated */
262         struct ldr_section_info *image_secn;
263         /* change in run address for current section during relocation */
264         ldr_addr delta_runaddr;
265         ldr_addr image_offset;  /* offset of current packet in section */
266         enum cinit_mode cinit_state;    /* current state of cload_cinit() */
267         int cinit_count;        /* the current count */
268         ldr_addr cinit_addr;    /* the current address */
269         s16 cinit_page;         /* the current page */
270         /* Handle to be returned by dynamic_load_module */
271         struct my_handle *myhandle;
272         unsigned dload_errcount;        /* Total # of errors reported so far */
273         /* Number of target sections that require allocation and relocation */
274         unsigned allocated_secn_count;
275 #ifndef TARGET_ENDIANNESS
276         int big_e_target;       /* Target data in big-endian format */
277 #endif
278         /* map for reordering bytes, 0 if not needed */
279         u32 reorder_map;
280         struct doff_filehdr_t dfile_hdr;        /* DOFF file header structure */
281         struct doff_verify_rec_t verify;        /* Verify record */
282
283         struct tramp_info tramp;        /* Trampoline data, if needed */
284
285         int relstkidx;          /* index into relocation value stack */
286         /* relocation value stack used in relexp.c */
287         rvalue relstk[STATIC_EXPR_STK_SIZE];
288
289 };
290
291 #ifdef TARGET_ENDIANNESS
292 #define TARGET_BIG_ENDIAN TARGET_ENDIANNESS
293 #else
294 #define TARGET_BIG_ENDIAN (dlthis->big_e_target)
295 #endif
296
297 /*
298  * Exports from cload.c to rest of the world
299  */
300 extern void dload_error(struct dload_state *dlthis, const char *errtxt, ...);
301 extern void dload_syms_error(struct dynamic_loader_sym *syms,
302                              const char *errtxt, ...);
303 extern void dload_headers(struct dload_state *dlthis);
304 extern void dload_strings(struct dload_state *dlthis, bool sec_names_only);
305 extern void dload_sections(struct dload_state *dlthis);
306 extern void dload_reorder(void *data, int dsiz, u32 map);
307 extern u32 dload_checksum(void *data, unsigned siz);
308
309 #if HOST_ENDIANNESS
310 extern uint32_t dload_reverse_checksum(void *data, unsigned siz);
311 #if (TARGET_AU_BITS > 8) && (TARGET_AU_BITS < 32)
312 extern uint32_t dload_reverse_checksum16(void *data, unsigned siz);
313 #endif
314 #endif
315
316 #define IS_DATA_SCN(zzz) (DLOAD_SECTION_TYPE((zzz)->type) != DLOAD_TEXT)
317 #define IS_DATA_SCN_NUM(zzz) \
318                 (DLOAD_SECT_TYPE(&dlthis->sect_hdrs[(zzz)-1]) != DLOAD_TEXT)
319
320 /*
321  * exported by reloc.c
322  */
323 extern void dload_relocate(struct dload_state *dlthis, tgt_au_t * data,
324                            struct reloc_record_t *rp, bool * tramps_generated,
325                            bool second_pass);
326
327 extern rvalue dload_unpack(struct dload_state *dlthis, tgt_au_t * data,
328                            int fieldsz, int offset, unsigned sgn);
329
330 extern int dload_repack(struct dload_state *dlthis, rvalue val, tgt_au_t * data,
331                         int fieldsz, int offset, unsigned sgn);
332
333 /*
334  * exported by tramp.c
335  */
336 extern bool dload_tramp_avail(struct dload_state *dlthis,
337                               struct reloc_record_t *rp);
338
339 int dload_tramp_generate(struct dload_state *dlthis, s16 secnn,
340                          u32 image_offset, struct image_packet_t *ipacket,
341                          struct reloc_record_t *rp);
342
343 extern int dload_tramp_pkt_udpate(struct dload_state *dlthis,
344                                   s16 secnn, u32 image_offset,
345                                   struct image_packet_t *ipacket);
346
347 extern int dload_tramp_finalize(struct dload_state *dlthis);
348
349 extern void dload_tramp_cleanup(struct dload_state *dlthis);
350
351 #endif /* _DLOAD_INTERNAL_ */