staging: tidspbridge: Remove macros used as cast
[linux-2.6.git] / drivers / staging / tidspbridge / dynload / getsection.c
1 /*
2  * getsection.c
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 #include <dspbridge/getsection.h>
18 #include "header.h"
19
20 /*
21  * Error strings
22  */
23 static const char readstrm[] = { "Error reading %s from input stream" };
24 static const char seek[] = { "Set file position to %d failed" };
25 static const char isiz[] = { "Bad image packet size %d" };
26 static const char err_checksum[] = { "Checksum failed on %s" };
27
28 static const char err_reloc[] = { "dload_get_section unable to read"
29             "sections containing relocation entries"
30 };
31
32 #if BITS_PER_AU > BITS_PER_BYTE
33 static const char err_alloc[] = { "Syms->dload_allocate( %d ) failed" };
34 static const char stbl[] = { "Bad string table offset " FMT_UI32 };
35 #endif
36
37 /************************************************************** */
38 /********************* SUPPORT FUNCTIONS ********************** */
39 /************************************************************** */
40
41 #if BITS_PER_AU > BITS_PER_BYTE
42 /**************************************************************************
43  * Procedure unpack_sec_name
44  *
45  * Parameters:
46  *  dlthis              Handle from dload_module_open for this module
47  *      soffset     Byte offset into the string table
48  *  dst         Place to store the expanded string
49  *
50  * Effect:
51  *      Stores a string from the string table into the destination, expanding
52  * it in the process.  Returns a pointer just past the end of the stored
53  * string on success, or NULL on failure.
54  *
55  ************************************************************************ */
56 static char *unpack_sec_name(struct dload_state *dlthis, u32 soffset, char *dst)
57 {
58         u8 tmp, *src;
59
60         if (soffset >= dlthis->dfile_hdr.df_scn_name_size) {
61                 dload_error(dlthis, stbl, soffset);
62                 return NULL;
63         }
64         src = (u8 *) dlthis->str_head +
65             (soffset >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE));
66         if (soffset & 1)
67                 *dst++ = *src++;        /* only 1 character in first word */
68         do {
69                 tmp = *src++;
70                 *dst = (tmp >> BITS_PER_BYTE)
71                     if (!(*dst++))
72                         break;
73         } while ((*dst++ = tmp & BYTE_MASK));
74
75         return dst;
76 }
77
78 /**************************************************************************
79  * Procedure expand_sec_names
80  *
81  * Parameters:
82  *  dlthis              Handle from dload_module_open for this module
83  *
84  * Effect:
85  *    Allocates a buffer, unpacks and copies strings from string table into it.
86  * Stores a pointer to the buffer into a state variable.
87  ************************************************************************* */
88 static void expand_sec_names(struct dload_state *dlthis)
89 {
90         char *xstrings, *curr, *next;
91         u32 xsize;
92         u16 sec;
93         struct ldr_section_info *shp;
94         /* assume worst-case size requirement */
95         xsize = dlthis->dfile_hdr.df_max_str_len * dlthis->dfile_hdr.df_no_scns;
96         xstrings = (char *)dlthis->mysym->dload_allocate(dlthis->mysym, xsize);
97         if (xstrings == NULL) {
98                 dload_error(dlthis, err_alloc, xsize);
99                 return;
100         }
101         dlthis->xstrings = xstrings;
102         /* For each sec, copy and expand its name */
103         curr = xstrings;
104         for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
105                 shp = (struct ldr_section_info *)&dlthis->sect_hdrs[sec];
106                 next = unpack_sec_name(dlthis, *(u32 *) &shp->name, curr);
107                 if (next == NULL)
108                         break;  /* error */
109                 shp->name = curr;
110                 curr = next;
111         }
112 }
113
114 #endif
115
116 /************************************************************** */
117 /********************* EXPORTED FUNCTIONS ********************* */
118 /************************************************************** */
119
120 /**************************************************************************
121  * Procedure dload_module_open
122  *
123  * Parameters:
124  *      module  The input stream that supplies the module image
125  *      syms    Host-side malloc/free and error reporting functions.
126  *                      Other methods are unused.
127  *
128  * Effect:
129  *      Reads header information from a dynamic loader module using the
130     specified
131  * stream object, and returns a handle for the module information.  This
132  * handle may be used in subsequent query calls to obtain information
133  * contained in the module.
134  *
135  * Returns:
136  *      NULL if an error is encountered, otherwise a module handle for use
137  * in subsequent operations.
138  ************************************************************************* */
139 void *dload_module_open(struct dynamic_loader_stream *module,
140                                     struct dynamic_loader_sym *syms)
141 {
142         struct dload_state *dlthis;     /* internal state for this call */
143         unsigned *dp, sz;
144         u32 sec_start;
145 #if BITS_PER_AU <= BITS_PER_BYTE
146         u16 sec;
147 #endif
148
149         /* Check that mandatory arguments are present */
150         if (!module || !syms) {
151                 if (syms != NULL)
152                         dload_syms_error(syms, "Required parameter is NULL");
153
154                 return NULL;
155         }
156
157         dlthis = (struct dload_state *)
158             syms->dload_allocate(syms, sizeof(struct dload_state));
159         if (!dlthis) {
160                 /* not enough storage */
161                 dload_syms_error(syms, "Can't allocate module info");
162                 return NULL;
163         }
164
165         /* clear our internal state */
166         dp = (unsigned *)dlthis;
167         for (sz = sizeof(struct dload_state) / sizeof(unsigned);
168              sz > 0; sz -= 1)
169                 *dp++ = 0;
170
171         dlthis->strm = module;
172         dlthis->mysym = syms;
173
174         /* read in the doff image and store in our state variable */
175         dload_headers(dlthis);
176
177         if (!dlthis->dload_errcount)
178                 dload_strings(dlthis, true);
179
180         /* skip ahead past the unread portion of the string table */
181         sec_start = sizeof(struct doff_filehdr_t) +
182             sizeof(struct doff_verify_rec_t) +
183             BYTE_TO_HOST(DOFF_ALIGN(dlthis->dfile_hdr.df_strtab_size));
184
185         if (dlthis->strm->set_file_posn(dlthis->strm, sec_start) != 0) {
186                 dload_error(dlthis, seek, sec_start);
187                 return NULL;
188         }
189
190         if (!dlthis->dload_errcount)
191                 dload_sections(dlthis);
192
193         if (dlthis->dload_errcount) {
194                 dload_module_close(dlthis);     /* errors, blow off our state */
195                 dlthis = NULL;
196                 return NULL;
197         }
198 #if BITS_PER_AU > BITS_PER_BYTE
199         /* Expand all section names from the string table into the */
200         /* state variable, and convert section names from a relative */
201         /* string table offset to a pointers to the expanded string. */
202         expand_sec_names(dlthis);
203 #else
204         /* Convert section names from a relative string table offset */
205         /* to a pointer into the string table. */
206         for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
207                 struct ldr_section_info *shp =
208                     (struct ldr_section_info *)&dlthis->sect_hdrs[sec];
209                 shp->name = dlthis->str_head + *(u32 *) &shp->name;
210         }
211 #endif
212
213         return dlthis;
214 }
215
216 /***************************************************************************
217  * Procedure dload_get_section_info
218  *
219  * Parameters:
220  *  minfo               Handle from dload_module_open for this module
221  *      section_name    Pointer to the string name of the section desired
222  *      section_info    Address of a section info structure pointer to be
223  *                      initialized
224  *
225  * Effect:
226  *      Finds the specified section in the module information, and initializes
227  * the provided struct ldr_section_info pointer.
228  *
229  * Returns:
230  *      true for success, false for section not found
231  ************************************************************************* */
232 int dload_get_section_info(void *minfo, const char *section_name,
233                            const struct ldr_section_info **const section_info)
234 {
235         struct dload_state *dlthis;
236         struct ldr_section_info *shp;
237         u16 sec;
238
239         dlthis = (struct dload_state *)minfo;
240         if (!dlthis)
241                 return false;
242
243         for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
244                 shp = (struct ldr_section_info *)&dlthis->sect_hdrs[sec];
245                 if (strcmp(section_name, shp->name) == 0) {
246                         *section_info = shp;
247                         return true;
248                 }
249         }
250
251         return false;
252 }
253
254 #define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
255 #define REVERSE_REORDER_MAP(rawmap) ((rawmap) ^ 0x3030303)
256
257 /**************************************************************************
258  * Procedure dload_get_section
259  *
260  * Parameters:
261  *  minfo               Handle from dload_module_open for this module
262  *      section_info    Pointer to a section info structure for the desired
263  *                      section
264  *      section_data    Buffer to contain the section initialized data
265  *
266  * Effect:
267  *      Copies the initialized data for the specified section into the
268  * supplied buffer.
269  *
270  * Returns:
271  *      true for success, false for section not found
272  ************************************************************************* */
273 int dload_get_section(void *minfo,
274                       const struct ldr_section_info *section_info,
275                       void *section_data)
276 {
277         struct dload_state *dlthis;
278         u32 pos;
279         struct doff_scnhdr_t *sptr = NULL;
280         s32 nip;
281         struct image_packet_t ipacket;
282         s32 ipsize;
283         u32 checks;
284         s8 *dest = (s8 *) section_data;
285
286         dlthis = (struct dload_state *)minfo;
287         if (!dlthis)
288                 return false;
289         sptr = (struct doff_scnhdr_t *)section_info;
290         if (sptr == NULL)
291                 return false;
292
293         /* skip ahead to the start of the first packet */
294         pos = BYTE_TO_HOST(DOFF_ALIGN((u32) sptr->ds_first_pkt_offset));
295         if (dlthis->strm->set_file_posn(dlthis->strm, pos) != 0) {
296                 dload_error(dlthis, seek, pos);
297                 return false;
298         }
299
300         nip = sptr->ds_nipacks;
301         while ((nip -= 1) >= 0) {       /* for each packet */
302                 /* get the fixed header bits */
303                 if (dlthis->strm->read_buffer(dlthis->strm, &ipacket,
304                                               IPH_SIZE) != IPH_SIZE) {
305                         dload_error(dlthis, readstrm, "image packet");
306                         return false;
307                 }
308                 /* reorder the header if need be */
309                 if (dlthis->reorder_map)
310                         dload_reorder(&ipacket, IPH_SIZE, dlthis->reorder_map);
311
312                 /* Now read the packet image bits. Note: round the size up to
313                  * the next multiple of 4 bytes; this is what checksum
314                  * routines want. */
315                 ipsize = BYTE_TO_HOST(DOFF_ALIGN(ipacket.packet_size));
316                 if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) {
317                         dload_error(dlthis, isiz, ipsize);
318                         return false;
319                 }
320                 if (dlthis->strm->read_buffer
321                     (dlthis->strm, dest, ipsize) != ipsize) {
322                         dload_error(dlthis, readstrm, "image packet");
323                         return false;
324                 }
325                 /* reorder the bytes if need be */
326 #if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
327                 if (dlthis->reorder_map)
328                         dload_reorder(dest, ipsize, dlthis->reorder_map);
329
330                 checks = dload_checksum(dest, ipsize);
331 #else
332                 if (dlthis->dfile_hdr.df_byte_reshuffle !=
333                     TARGET_ORDER(REORDER_MAP(BYTE_RESHUFFLE_VALUE))) {
334                         /* put image bytes in big-endian order, not PC order */
335                         dload_reorder(dest, ipsize,
336                                       TARGET_ORDER(dlthis->
337                                                 dfile_hdr.df_byte_reshuffle));
338                 }
339 #if TARGET_AU_BITS > 8
340                 checks = dload_reverse_checksum16(dest, ipsize);
341 #else
342                 checks = dload_reverse_checksum(dest, ipsize);
343 #endif
344 #endif
345                 checks += dload_checksum(&ipacket, IPH_SIZE);
346
347                 /* NYI: unable to handle relocation entries here.  Reloc
348                  * entries referring to fields that span the packet boundaries
349                  * may result in packets of sizes that are not multiple of
350                  * 4 bytes. Our checksum implementation works on 32-bit words
351                  * only. */
352                 if (ipacket.num_relocs != 0) {
353                         dload_error(dlthis, err_reloc, ipsize);
354                         return false;
355                 }
356
357                 if (~checks) {
358                         dload_error(dlthis, err_checksum, "image packet");
359                         return false;
360                 }
361
362                 /*Advance destination ptr by the size of the just-read packet */
363                 dest += ipsize;
364         }
365
366         return true;
367 }
368
369 /***************************************************************************
370  * Procedure dload_module_close
371  *
372  * Parameters:
373  *  minfo               Handle from dload_module_open for this module
374  *
375  * Effect:
376  *      Releases any storage associated with the module handle.  On return,
377  * the module handle is invalid.
378  *
379  * Returns:
380  *      Zero for success. On error, the number of errors detected is returned.
381  * Individual errors are reported using syms->error_report(), where syms was
382  * an argument to dload_module_open
383  ************************************************************************* */
384 void dload_module_close(void *minfo)
385 {
386         struct dload_state *dlthis;
387
388         dlthis = (struct dload_state *)minfo;
389         if (!dlthis)
390                 return;
391
392         if (dlthis->str_head)
393                 dlthis->mysym->dload_deallocate(dlthis->mysym,
394                                                 dlthis->str_head);
395
396         if (dlthis->sect_hdrs)
397                 dlthis->mysym->dload_deallocate(dlthis->mysym,
398                                                 dlthis->sect_hdrs);
399
400 #if BITS_PER_AU > BITS_PER_BYTE
401         if (dlthis->xstrings)
402                 dlthis->mysym->dload_deallocate(dlthis->mysym,
403                                                 dlthis->xstrings);
404
405 #endif
406
407         dlthis->mysym->dload_deallocate(dlthis->mysym, dlthis);
408 }