cnic: Do not call bnx2i when bnx2i is calling cnic_unregister_driver()
[linux-2.6/btrfs-unstable.git] / drivers / staging / tidspbridge / dynload / getsection.c
blobe0b37714dd65ec5c01cc56b71883d36d40145e1c
1 /*
2 * getsection.c
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
6 * Copyright (C) 2005-2006 Texas Instruments, Inc.
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.
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.
17 #include <dspbridge/getsection.h>
18 #include "header.h"
21 * Error strings
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" };
28 static const char err_reloc[] = { "dload_get_section unable to read"
29 "sections containing relocation entries"
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
37 /************************************************************** */
38 /********************* SUPPORT FUNCTIONS ********************** */
39 /************************************************************** */
41 #if BITS_PER_AU > BITS_PER_BYTE
42 /**************************************************************************
43 * Procedure unpack_sec_name
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
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.
55 ************************************************************************ */
56 static char *unpack_sec_name(struct dload_state *dlthis, u32 soffset, char *dst)
58 u8 tmp, *src;
60 if (soffset >= dlthis->dfile_hdr.df_scn_name_size) {
61 dload_error(dlthis, stbl, soffset);
62 return NULL;
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));
75 return dst;
78 /**************************************************************************
79 * Procedure expand_sec_names
81 * Parameters:
82 * dlthis Handle from dload_module_open for this module
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)
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;
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;
114 #endif
116 /************************************************************** */
117 /********************* EXPORTED FUNCTIONS ********************* */
118 /************************************************************** */
120 /**************************************************************************
121 * Procedure dload_module_open
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.
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.
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)
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
149 /* Check that mandatory arguments are present */
150 if (!module || !syms) {
151 if (syms != NULL)
152 dload_syms_error(syms, "Required parameter is NULL");
154 return NULL;
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;
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;
171 dlthis->strm = module;
172 dlthis->mysym = syms;
174 /* read in the doff image and store in our state variable */
175 dload_headers(dlthis);
177 if (!dlthis->dload_errcount)
178 dload_strings(dlthis, true);
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));
185 if (dlthis->strm->set_file_posn(dlthis->strm, sec_start) != 0) {
186 dload_error(dlthis, seek, sec_start);
187 return NULL;
190 if (!dlthis->dload_errcount)
191 dload_sections(dlthis);
193 if (dlthis->dload_errcount) {
194 dload_module_close(dlthis); /* errors, blow off our state */
195 dlthis = NULL;
196 return NULL;
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;
211 #endif
213 return dlthis;
216 /***************************************************************************
217 * Procedure dload_get_section_info
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
225 * Effect:
226 * Finds the specified section in the module information, and initializes
227 * the provided struct ldr_section_info pointer.
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)
235 struct dload_state *dlthis;
236 struct ldr_section_info *shp;
237 u16 sec;
239 dlthis = (struct dload_state *)minfo;
240 if (!dlthis)
241 return false;
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;
251 return false;
254 #define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
256 /**************************************************************************
257 * Procedure dload_get_section
259 * Parameters:
260 * minfo Handle from dload_module_open for this module
261 * section_info Pointer to a section info structure for the desired
262 * section
263 * section_data Buffer to contain the section initialized data
265 * Effect:
266 * Copies the initialized data for the specified section into the
267 * supplied buffer.
269 * Returns:
270 * true for success, false for section not found
271 ************************************************************************* */
272 int dload_get_section(void *minfo,
273 const struct ldr_section_info *section_info,
274 void *section_data)
276 struct dload_state *dlthis;
277 u32 pos;
278 struct doff_scnhdr_t *sptr = NULL;
279 s32 nip;
280 struct image_packet_t ipacket;
281 s32 ipsize;
282 u32 checks;
283 s8 *dest = (s8 *) section_data;
285 dlthis = (struct dload_state *)minfo;
286 if (!dlthis)
287 return false;
288 sptr = (struct doff_scnhdr_t *)section_info;
289 if (sptr == NULL)
290 return false;
292 /* skip ahead to the start of the first packet */
293 pos = BYTE_TO_HOST(DOFF_ALIGN((u32) sptr->ds_first_pkt_offset));
294 if (dlthis->strm->set_file_posn(dlthis->strm, pos) != 0) {
295 dload_error(dlthis, seek, pos);
296 return false;
299 nip = sptr->ds_nipacks;
300 while ((nip -= 1) >= 0) { /* for each packet */
301 /* get the fixed header bits */
302 if (dlthis->strm->read_buffer(dlthis->strm, &ipacket,
303 IPH_SIZE) != IPH_SIZE) {
304 dload_error(dlthis, readstrm, "image packet");
305 return false;
307 /* reorder the header if need be */
308 if (dlthis->reorder_map)
309 dload_reorder(&ipacket, IPH_SIZE, dlthis->reorder_map);
311 /* Now read the packet image bits. Note: round the size up to
312 * the next multiple of 4 bytes; this is what checksum
313 * routines want. */
314 ipsize = BYTE_TO_HOST(DOFF_ALIGN(ipacket.packet_size));
315 if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) {
316 dload_error(dlthis, isiz, ipsize);
317 return false;
319 if (dlthis->strm->read_buffer
320 (dlthis->strm, dest, ipsize) != ipsize) {
321 dload_error(dlthis, readstrm, "image packet");
322 return false;
324 /* reorder the bytes if need be */
325 #if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
326 if (dlthis->reorder_map)
327 dload_reorder(dest, ipsize, dlthis->reorder_map);
329 checks = dload_checksum(dest, ipsize);
330 #else
331 if (dlthis->dfile_hdr.df_byte_reshuffle !=
332 TARGET_ORDER(REORDER_MAP(BYTE_RESHUFFLE_VALUE))) {
333 /* put image bytes in big-endian order, not PC order */
334 dload_reorder(dest, ipsize,
335 TARGET_ORDER(dlthis->
336 dfile_hdr.df_byte_reshuffle));
338 #if TARGET_AU_BITS > 8
339 checks = dload_reverse_checksum16(dest, ipsize);
340 #else
341 checks = dload_reverse_checksum(dest, ipsize);
342 #endif
343 #endif
344 checks += dload_checksum(&ipacket, IPH_SIZE);
346 /* NYI: unable to handle relocation entries here. Reloc
347 * entries referring to fields that span the packet boundaries
348 * may result in packets of sizes that are not multiple of
349 * 4 bytes. Our checksum implementation works on 32-bit words
350 * only. */
351 if (ipacket.num_relocs != 0) {
352 dload_error(dlthis, err_reloc, ipsize);
353 return false;
356 if (~checks) {
357 dload_error(dlthis, err_checksum, "image packet");
358 return false;
361 /*Advance destination ptr by the size of the just-read packet */
362 dest += ipsize;
365 return true;
368 /***************************************************************************
369 * Procedure dload_module_close
371 * Parameters:
372 * minfo Handle from dload_module_open for this module
374 * Effect:
375 * Releases any storage associated with the module handle. On return,
376 * the module handle is invalid.
378 * Returns:
379 * Zero for success. On error, the number of errors detected is returned.
380 * Individual errors are reported using syms->error_report(), where syms was
381 * an argument to dload_module_open
382 ************************************************************************* */
383 void dload_module_close(void *minfo)
385 struct dload_state *dlthis;
387 dlthis = (struct dload_state *)minfo;
388 if (!dlthis)
389 return;
391 if (dlthis->str_head)
392 dlthis->mysym->dload_deallocate(dlthis->mysym,
393 dlthis->str_head);
395 if (dlthis->sect_hdrs)
396 dlthis->mysym->dload_deallocate(dlthis->mysym,
397 dlthis->sect_hdrs);
399 #if BITS_PER_AU > BITS_PER_BYTE
400 if (dlthis->xstrings)
401 dlthis->mysym->dload_deallocate(dlthis->mysym,
402 dlthis->xstrings);
404 #endif
406 dlthis->mysym->dload_deallocate(dlthis->mysym, dlthis);