aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/tidspbridge/dynload/dload_internal.h
blob: b9d079b961905315d8832c7e4fc0eb6d92cb7daf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
/*
 * 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_ */