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 };
38 * we use the fact that DOFF section records are shaped just like
39 * ldr_section_info to reduce our section storage usage. These macros
40 * marks the places where that assumption is made
42 #define DOFFSEC_IS_LDRSEC(pdoffsec) ((struct ldr_section_info *)(pdoffsec))
43 #define LDRSEC_IS_DOFFSEC(ldrsec) ((struct doff_scnhdr_t *)(ldrsec))
45 /************************************************************** */
46 /********************* SUPPORT FUNCTIONS ********************** */
47 /************************************************************** */
49 #if BITS_PER_AU > BITS_PER_BYTE
50 /**************************************************************************
51 * Procedure unpack_sec_name
54 * dlthis Handle from dload_module_open for this module
55 * soffset Byte offset into the string table
56 * dst Place to store the expanded string
59 * Stores a string from the string table into the destination, expanding
60 * it in the process. Returns a pointer just past the end of the stored
61 * string on success, or NULL on failure.
63 ************************************************************************ */
64 static char *unpack_sec_name(struct dload_state *dlthis, u32 soffset, char *dst)
68 if (soffset >= dlthis->dfile_hdr.df_scn_name_size) {
69 dload_error(dlthis, stbl, soffset);
72 src = (u8 *) dlthis->str_head +
73 (soffset >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE));
75 *dst++ = *src++; /* only 1 character in first word */
78 *dst = (tmp >> BITS_PER_BYTE)
81 } while ((*dst++ = tmp & BYTE_MASK));
86 /**************************************************************************
87 * Procedure expand_sec_names
90 * dlthis Handle from dload_module_open for this module
93 * Allocates a buffer, unpacks and copies strings from string table into it.
94 * Stores a pointer to the buffer into a state variable.
95 ************************************************************************* */
96 static void expand_sec_names(struct dload_state *dlthis)
98 char *xstrings, *curr, *next;
101 struct ldr_section_info *shp;
102 /* assume worst-case size requirement */
103 xsize = dlthis->dfile_hdr.df_max_str_len * dlthis->dfile_hdr.df_no_scns;
104 xstrings = (char *)dlthis->mysym->dload_allocate(dlthis->mysym, xsize);
105 if (xstrings == NULL) {
106 dload_error(dlthis, err_alloc, xsize);
109 dlthis->xstrings = xstrings;
110 /* For each sec, copy and expand its name */
112 for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
113 shp = DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
114 next = unpack_sec_name(dlthis, *(u32 *) &shp->name, curr);
124 /************************************************************** */
125 /********************* EXPORTED FUNCTIONS ********************* */
126 /************************************************************** */
128 /**************************************************************************
129 * Procedure dload_module_open
132 * module The input stream that supplies the module image
133 * syms Host-side malloc/free and error reporting functions.
134 * Other methods are unused.
137 * Reads header information from a dynamic loader module using the
139 * stream object, and returns a handle for the module information. This
140 * handle may be used in subsequent query calls to obtain information
141 * contained in the module.
144 * NULL if an error is encountered, otherwise a module handle for use
145 * in subsequent operations.
146 ************************************************************************* */
147 void *dload_module_open(struct dynamic_loader_stream *module,
148 struct dynamic_loader_sym *syms)
150 struct dload_state *dlthis; /* internal state for this call */
153 #if BITS_PER_AU <= BITS_PER_BYTE
157 /* Check that mandatory arguments are present */
158 if (!module || !syms) {
160 dload_syms_error(syms, "Required parameter is NULL");
165 dlthis = (struct dload_state *)
166 syms->dload_allocate(syms, sizeof(struct dload_state));
168 /* not enough storage */
169 dload_syms_error(syms, "Can't allocate module info");
173 /* clear our internal state */
174 dp = (unsigned *)dlthis;
175 for (sz = sizeof(struct dload_state) / sizeof(unsigned);
179 dlthis->strm = module;
180 dlthis->mysym = syms;
182 /* read in the doff image and store in our state variable */
183 dload_headers(dlthis);
185 if (!dlthis->dload_errcount)
186 dload_strings(dlthis, true);
188 /* skip ahead past the unread portion of the string table */
189 sec_start = sizeof(struct doff_filehdr_t) +
190 sizeof(struct doff_verify_rec_t) +
191 BYTE_TO_HOST(DOFF_ALIGN(dlthis->dfile_hdr.df_strtab_size));
193 if (dlthis->strm->set_file_posn(dlthis->strm, sec_start) != 0) {
194 dload_error(dlthis, seek, sec_start);
198 if (!dlthis->dload_errcount)
199 dload_sections(dlthis);
201 if (dlthis->dload_errcount) {
202 dload_module_close(dlthis); /* errors, blow off our state */
206 #if BITS_PER_AU > BITS_PER_BYTE
207 /* Expand all section names from the string table into the */
208 /* state variable, and convert section names from a relative */
209 /* string table offset to a pointers to the expanded string. */
210 expand_sec_names(dlthis);
212 /* Convert section names from a relative string table offset */
213 /* to a pointer into the string table. */
214 for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
215 struct ldr_section_info *shp =
216 DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
217 shp->name = dlthis->str_head + *(u32 *) &shp->name;
224 /***************************************************************************
225 * Procedure dload_get_section_info
228 * minfo Handle from dload_module_open for this module
229 * sectionName Pointer to the string name of the section desired
230 * sectionInfo Address of a section info structure pointer to be
234 * Finds the specified section in the module information, and initializes
235 * the provided struct ldr_section_info pointer.
238 * true for success, false for section not found
239 ************************************************************************* */
240 int dload_get_section_info(void *minfo, const char *sectionName,
241 const struct ldr_section_info **const sectionInfo)
243 struct dload_state *dlthis;
244 struct ldr_section_info *shp;
247 dlthis = (struct dload_state *)minfo;
251 for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
252 shp = DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
253 if (strcmp(sectionName, shp->name) == 0) {
262 #define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
263 #define REVERSE_REORDER_MAP(rawmap) ((rawmap) ^ 0x3030303)
265 /**************************************************************************
266 * Procedure dload_get_section
269 * minfo Handle from dload_module_open for this module
270 * sectionInfo Pointer to a section info structure for the desired
272 * sectionData Buffer to contain the section initialized data
275 * Copies the initialized data for the specified section into the
279 * true for success, false for section not found
280 ************************************************************************* */
281 int dload_get_section(void *minfo,
282 const struct ldr_section_info *sectionInfo,
285 struct dload_state *dlthis;
287 struct doff_scnhdr_t *sptr = NULL;
289 struct image_packet_t ipacket;
292 s8 *dest = (s8 *) sectionData;
294 dlthis = (struct dload_state *)minfo;
297 sptr = LDRSEC_IS_DOFFSEC(sectionInfo);
301 /* skip ahead to the start of the first packet */
302 pos = BYTE_TO_HOST(DOFF_ALIGN((u32) sptr->ds_first_pkt_offset));
303 if (dlthis->strm->set_file_posn(dlthis->strm, pos) != 0) {
304 dload_error(dlthis, seek, pos);
308 nip = sptr->ds_nipacks;
309 while ((nip -= 1) >= 0) { /* for each packet */
310 /* get the fixed header bits */
311 if (dlthis->strm->read_buffer(dlthis->strm, &ipacket,
312 IPH_SIZE) != IPH_SIZE) {
313 dload_error(dlthis, readstrm, "image packet");
316 /* reorder the header if need be */
317 if (dlthis->reorder_map)
318 dload_reorder(&ipacket, IPH_SIZE, dlthis->reorder_map);
320 /* Now read the packet image bits. Note: round the size up to
321 * the next multiple of 4 bytes; this is what checksum
323 ipsize = BYTE_TO_HOST(DOFF_ALIGN(ipacket.packet_size));
324 if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) {
325 dload_error(dlthis, isiz, ipsize);
328 if (dlthis->strm->read_buffer
329 (dlthis->strm, dest, ipsize) != ipsize) {
330 dload_error(dlthis, readstrm, "image packet");
333 /* reorder the bytes if need be */
334 #if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
335 if (dlthis->reorder_map)
336 dload_reorder(dest, ipsize, dlthis->reorder_map);
338 checks = dload_checksum(dest, ipsize);
340 if (dlthis->dfile_hdr.df_byte_reshuffle !=
341 TARGET_ORDER(REORDER_MAP(BYTE_RESHUFFLE_VALUE))) {
342 /* put image bytes in big-endian order, not PC order */
343 dload_reorder(dest, ipsize,
344 TARGET_ORDER(dlthis->
345 dfile_hdr.df_byte_reshuffle));
347 #if TARGET_AU_BITS > 8
348 checks = dload_reverse_checksum16(dest, ipsize);
350 checks = dload_reverse_checksum(dest, ipsize);
353 checks += dload_checksum(&ipacket, IPH_SIZE);
355 /* NYI: unable to handle relocation entries here. Reloc
356 * entries referring to fields that span the packet boundaries
357 * may result in packets of sizes that are not multiple of
358 * 4 bytes. Our checksum implementation works on 32-bit words
360 if (ipacket.num_relocs != 0) {
361 dload_error(dlthis, err_reloc, ipsize);
366 dload_error(dlthis, err_checksum, "image packet");
370 /*Advance destination ptr by the size of the just-read packet */
377 /***************************************************************************
378 * Procedure dload_module_close
381 * minfo Handle from dload_module_open for this module
384 * Releases any storage associated with the module handle. On return,
385 * the module handle is invalid.
388 * Zero for success. On error, the number of errors detected is returned.
389 * Individual errors are reported using syms->error_report(), where syms was
390 * an argument to dload_module_open
391 ************************************************************************* */
392 void dload_module_close(void *minfo)
394 struct dload_state *dlthis;
396 dlthis = (struct dload_state *)minfo;
400 if (dlthis->str_head)
401 dlthis->mysym->dload_deallocate(dlthis->mysym,
404 if (dlthis->sect_hdrs)
405 dlthis->mysym->dload_deallocate(dlthis->mysym,
408 #if BITS_PER_AU > BITS_PER_BYTE
409 if (dlthis->xstrings)
410 dlthis->mysym->dload_deallocate(dlthis->mysym,
415 dlthis->mysym->dload_deallocate(dlthis->mysym, dlthis);