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