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>
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
};
37 /************************************************************** */
38 /********************* SUPPORT FUNCTIONS ********************** */
39 /************************************************************** */
41 #if BITS_PER_AU > BITS_PER_BYTE
42 /**************************************************************************
43 * Procedure unpack_sec_name
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
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
)
60 if (soffset
>= dlthis
->dfile_hdr
.df_scn_name_size
) {
61 dload_error(dlthis
, stbl
, soffset
);
64 src
= (u8
*) dlthis
->str_head
+
65 (soffset
>> (LOG_BITS_PER_AU
- LOG_BITS_PER_BYTE
));
67 *dst
++ = *src
++; /* only 1 character in first word */
70 *dst
= (tmp
>> BITS_PER_BYTE
)
73 } while ((*dst
++ = tmp
& BYTE_MASK
));
78 /**************************************************************************
79 * Procedure expand_sec_names
82 * dlthis Handle from dload_module_open for this module
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
;
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
);
101 dlthis
->xstrings
= xstrings
;
102 /* For each sec, copy and expand its name */
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
);
116 /************************************************************** */
117 /********************* EXPORTED FUNCTIONS ********************* */
118 /************************************************************** */
120 /**************************************************************************
121 * Procedure dload_module_open
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.
129 * Reads header information from a dynamic loader module using the
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.
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 */
145 #if BITS_PER_AU <= BITS_PER_BYTE
149 /* Check that mandatory arguments are present */
150 if (!module
|| !syms
) {
152 dload_syms_error(syms
, "Required parameter is NULL");
157 dlthis
= (struct dload_state
*)
158 syms
->dload_allocate(syms
, sizeof(struct dload_state
));
160 /* not enough storage */
161 dload_syms_error(syms
, "Can't allocate module info");
165 /* clear our internal state */
166 dp
= (unsigned *)dlthis
;
167 for (sz
= sizeof(struct dload_state
) / sizeof(unsigned);
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
);
190 if (!dlthis
->dload_errcount
)
191 dload_sections(dlthis
);
193 if (dlthis
->dload_errcount
) {
194 dload_module_close(dlthis
); /* errors, blow off our state */
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
);
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
;
216 /***************************************************************************
217 * Procedure dload_get_section_info
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
226 * Finds the specified section in the module information, and initializes
227 * the provided struct ldr_section_info pointer.
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
;
239 dlthis
= (struct dload_state
*)minfo
;
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) {
254 #define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
256 /**************************************************************************
257 * Procedure dload_get_section
260 * minfo Handle from dload_module_open for this module
261 * section_info Pointer to a section info structure for the desired
263 * section_data Buffer to contain the section initialized data
266 * Copies the initialized data for the specified section into the
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
,
276 struct dload_state
*dlthis
;
278 struct doff_scnhdr_t
*sptr
= NULL
;
280 struct image_packet_t ipacket
;
283 s8
*dest
= (s8
*) section_data
;
285 dlthis
= (struct dload_state
*)minfo
;
288 sptr
= (struct doff_scnhdr_t
*)section_info
;
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
);
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");
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
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
);
319 if (dlthis
->strm
->read_buffer
320 (dlthis
->strm
, dest
, ipsize
) != ipsize
) {
321 dload_error(dlthis
, readstrm
, "image packet");
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
);
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
);
341 checks
= dload_reverse_checksum(dest
, ipsize
);
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
351 if (ipacket
.num_relocs
!= 0) {
352 dload_error(dlthis
, err_reloc
, ipsize
);
357 dload_error(dlthis
, err_checksum
, "image packet");
361 /*Advance destination ptr by the size of the just-read packet */
368 /***************************************************************************
369 * Procedure dload_module_close
372 * minfo Handle from dload_module_open for this module
375 * Releases any storage associated with the module handle. On return,
376 * the module handle is invalid.
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
;
391 if (dlthis
->str_head
)
392 dlthis
->mysym
->dload_deallocate(dlthis
->mysym
,
395 if (dlthis
->sect_hdrs
)
396 dlthis
->mysym
->dload_deallocate(dlthis
->mysym
,
399 #if BITS_PER_AU > BITS_PER_BYTE
400 if (dlthis
->xstrings
)
401 dlthis
->mysym
->dload_deallocate(dlthis
->mysym
,
406 dlthis
->mysym
->dload_deallocate(dlthis
->mysym
, dlthis
);