]> git.sur5r.net Git - openocd/blob - src/target/image.c
7381440ed604942f75a7c22167ad70156425b4ff
[openocd] / src / target / image.c
1 /***************************************************************************
2  *   Copyright (C) 2007 by Dominic Rath                                    *
3  *   Dominic.Rath@gmx.de                                                   *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "image.h"
28
29 #include "types.h"
30 #include "replacements.h"
31 #include "log.h"
32
33 #include "fileio.h"
34 #include "target.h"
35
36 int image_ihex_buffer_complete(image_t *image)
37 {
38         image_ihex_t *ihex = image->type_private;
39         fileio_t *fileio = &ihex->fileio;
40         u32 raw_bytes_read, raw_bytes;
41         int retval;
42         u32 full_address = 0x0;
43         char *buffer = malloc(fileio->size);
44         u32 cooked_bytes;
45         int i;
46         
47         /* we can't determine the number of sections that we'll have to create ahead of time,
48          * so we locally hold them until parsing is finished */
49         image_section_t section[IMAGE_MAX_SECTIONS];
50         u8 *section_pointer[IMAGE_MAX_SECTIONS];
51         
52         if ((retval = fileio_read(fileio, fileio->size, (u8*)buffer, &raw_bytes_read)) != ERROR_OK)
53         {
54                 free(buffer);
55                 ERROR("failed buffering IHEX file, read failed");
56                 return ERROR_FILEIO_OPERATION_FAILED;
57         }
58         
59         if (raw_bytes_read != fileio->size)
60         {
61                 free(buffer);
62                 ERROR("failed buffering complete IHEX file, only partially read");
63                 return ERROR_FILEIO_OPERATION_FAILED;
64         }
65
66         ihex->buffer = malloc(fileio->size >> 1);
67         raw_bytes = 0x0;
68         cooked_bytes = 0x0;
69         image->num_sections = 0;
70         section_pointer[image->num_sections] = &ihex->buffer[cooked_bytes];
71         section[image->num_sections].base_address = 0x0;
72         section[image->num_sections].size = 0x0;
73         section[image->num_sections].flags = 0;
74         while (raw_bytes < raw_bytes_read)
75         {
76                 u32 count;
77                 u32 address;
78                 u32 record_type;
79                 u32 checksum;
80                 
81                 if (sscanf(&buffer[raw_bytes], ":%2x%4x%2x", &count, &address, &record_type) != 3)
82                 {
83                         return ERROR_IMAGE_FORMAT_ERROR;
84                 }
85                 raw_bytes += 9;
86                 
87                 if (record_type == 0) /* Data Record */
88                 {
89                         if ((full_address & 0xffff) != address)
90                         {
91                                 /* we encountered a nonconsecutive location, create a new section,
92                                  * unless the current section has zero size, in which case this specifies
93                                  * the current section's base address
94                                  */
95                                 if (section[image->num_sections].size != 0)
96                                 {
97                                         image->num_sections++;
98                                         section[image->num_sections].size = 0x0;
99                                         section[image->num_sections].flags = 0;
100                                         section_pointer[image->num_sections] = &ihex->buffer[cooked_bytes];
101                                 }
102                                 section[image->num_sections].base_address =
103                                         (full_address & 0xffff0000) | address;
104                                 full_address = (full_address & 0xffff0000) | address;
105                         }
106                         
107                         while (count-- > 0)
108                         {
109                                 sscanf(&buffer[raw_bytes], "%2hhx", &ihex->buffer[cooked_bytes]);
110                                 raw_bytes += 2;
111                                 cooked_bytes += 1;
112                                 section[image->num_sections].size += 1;
113                                 full_address++;
114                         }
115                 }
116                 else if (record_type == 1) /* End of File Record */
117                 {
118                         /* finish the current section */
119                         image->num_sections++;
120                         
121                         /* copy section information */
122                         ihex->section_pointer = malloc(sizeof(u8*) * image->num_sections);
123                         image->sections = malloc(sizeof(image_section_t) * image->num_sections);
124                         for (i = 0; i < image->num_sections; i++)
125                         {
126                                 ihex->section_pointer[i] = section_pointer[i];
127                                 image->sections[i].base_address = section[i].base_address +
128                                         ((image->base_address_set) ? image->base_address : 0);
129                                 image->sections[i].size = section[i].size;
130                                 image->sections[i].flags = section[i].flags;
131                         }
132                         
133                         free(buffer);
134                         return ERROR_OK;
135                 }
136                 else if (record_type == 4) /* Extended Linear Address Record */
137                 {
138                         u16 upper_address;
139                         
140                         sscanf(&buffer[raw_bytes], "%4hx", &upper_address);
141                         raw_bytes += 4;
142                         
143                         if ((full_address >> 16) != upper_address)
144                         {
145                                 /* we encountered a nonconsecutive location, create a new section,
146                                  * unless the current section has zero size, in which case this specifies
147                                  * the current section's base address
148                                  */
149                                 if (section[image->num_sections].size != 0)
150                                 {
151                                         image->num_sections++;
152                                         section[image->num_sections].size = 0x0;
153                                         section[image->num_sections].flags = 0;
154                                         section_pointer[image->num_sections] = &ihex->buffer[cooked_bytes];
155                                 }
156                                 section[image->num_sections].base_address = 
157                                         (full_address & 0xffff) | (upper_address << 16);
158                                 full_address = (full_address & 0xffff) | (upper_address << 16);
159                         }
160                 }
161                 else if (record_type == 5) /* Start Linear Address Record */
162                 {
163                         u32 start_address;
164                         
165                         sscanf(&buffer[raw_bytes], "%8x", &start_address);
166                         raw_bytes += 8;
167                         
168                         image->start_address_set = 1;
169                         image->start_address = be_to_h_u32((u8*)&start_address);
170                 }
171                 else
172                 {
173                         free(buffer);
174                         ERROR("unhandled IHEX record type: %i", record_type);
175                         return ERROR_IMAGE_FORMAT_ERROR;
176                 }
177                 
178                 sscanf(&buffer[raw_bytes], "%2x", &checksum);
179                 raw_bytes += 2;
180                 
181                 /* consume new-line character(s) */
182                 if ((buffer[raw_bytes] == '\n') || (buffer[raw_bytes] == '\r'))
183                         raw_bytes++;
184
185                 if ((buffer[raw_bytes] == '\n') || (buffer[raw_bytes] == '\r'))
186                         raw_bytes++;
187         }
188
189         free(buffer);
190         ERROR("premature end of IHEX file, no end-of-file record found");
191         return ERROR_IMAGE_FORMAT_ERROR;
192 }
193
194 int image_open(image_t *image, void *source, enum fileio_access access)
195 {
196         int retval = ERROR_OK;
197         
198         if (image->type == IMAGE_BINARY)
199         {
200                 image_binary_t *image_binary;
201                 char *url = source;
202                 
203                 image_binary = image->type_private = malloc(sizeof(image_binary_t));
204                 
205                 if ((retval = fileio_open(&image_binary->fileio, url, access, FILEIO_BINARY)) != ERROR_OK)
206                 {
207                         strncpy(image->error_str, image_binary->fileio.error_str, IMAGE_MAX_ERROR_STRING); 
208                         ERROR(image->error_str);
209                         return retval;
210                 }
211                 
212                 image->num_sections = 1;
213                 image->sections = malloc(sizeof(image_section_t));
214                 image->sections[0].base_address = 0x0;
215                 image->sections[0].size = image_binary->fileio.size;
216                 image->sections[0].flags = 0;
217                 
218                 if (image->base_address_set == 1)
219                         image->sections[0].base_address = image->base_address;
220                 
221                 return ERROR_OK;
222         }
223         else if (image->type == IMAGE_IHEX)
224         {
225                 image_ihex_t *image_ihex;
226                 char *url = source;
227                 
228                 if (access != FILEIO_READ)
229                 {
230                         snprintf(image->error_str, IMAGE_MAX_ERROR_STRING,
231                                 "can't open IHEX file for writing");
232                         ERROR(image->error_str);
233                         return ERROR_FILEIO_ACCESS_NOT_SUPPORTED;
234                 }
235                 
236                 image_ihex = image->type_private = malloc(sizeof(image_ihex_t));
237                 
238                 if ((retval = fileio_open(&image_ihex->fileio, url, FILEIO_READ, FILEIO_TEXT)) != ERROR_OK)
239                 {
240                         strncpy(image->error_str, image_ihex->fileio.error_str, IMAGE_MAX_ERROR_STRING); 
241                         ERROR(image->error_str);
242                         return retval;
243                 }
244                 
245                 if ((retval = image_ihex_buffer_complete(image)) != ERROR_OK)
246                 {
247                         snprintf(image->error_str, IMAGE_MAX_ERROR_STRING,
248                                 "failed buffering IHEX image, check daemon output for additional information");
249                         ERROR(image->error_str);
250                         fileio_close(&image_ihex->fileio);
251                         return retval;
252                 }
253         }
254         else if (image->type == IMAGE_MEMORY)
255         {
256                 image_memory_t *image_memory;
257                 target_t *target = source;
258                 
259                 image_memory = image->type_private = malloc(sizeof(image_memory_t));
260                 
261                 image_memory->target = target;
262         }
263         
264         return retval;
265 };
266
267 int image_read_section(image_t *image, int section, u32 offset, u32 size, u8 *buffer, u32 *size_read)
268 {
269         int retval;
270         
271         if (image->type == IMAGE_BINARY)
272         {
273                 image_binary_t *image_binary = image->type_private;
274                 
275                 /* only one section in a plain binary */
276                 if (section != 0)
277                         return ERROR_INVALID_ARGUMENTS;
278                         
279                 if ((offset > image->sections[0].size) || (offset + size > image->sections[0].size))
280                         return ERROR_INVALID_ARGUMENTS;
281                 
282                 /* seek to offset */
283                 if ((retval = fileio_seek(&image_binary->fileio, offset)) != ERROR_OK)
284                 {
285                         strncpy(image->error_str, image_binary->fileio.error_str, IMAGE_MAX_ERROR_STRING);
286                         return retval;
287                 }
288                 
289                 /* return requested bytes */
290                 if ((retval = fileio_read(&image_binary->fileio, size, buffer, size_read)) != ERROR_OK)
291                 {
292                         strncpy(image->error_str, image_binary->fileio.error_str, IMAGE_MAX_ERROR_STRING);
293                         return retval;
294                 }
295         }
296         else if (image->type == IMAGE_IHEX)
297         {
298                 image_ihex_t *image_ihex = image->type_private;
299
300                 memcpy(buffer, image_ihex->section_pointer[section] + offset, size);
301                 *size_read = size;
302                 image->error_str[0] = '\0';
303                 
304                 return ERROR_OK;
305         }
306         else if (image->type == IMAGE_MEMORY)
307         {
308                 /* TODO: handle target memory pseudo image */
309         }
310         
311         return ERROR_OK;
312 }
313
314 int image_close(image_t *image)
315 {
316         if (image->type == IMAGE_BINARY)
317         {
318                 image_binary_t *image_binary = image->type_private;
319                 
320                 fileio_close(&image_binary->fileio);
321         }
322         else if (image->type == IMAGE_IHEX)
323         {
324                 image_ihex_t *image_ihex = image->type_private;
325                 
326                 fileio_close(&image_ihex->fileio);
327                 
328                 if (image_ihex->section_pointer)
329                         free(image_ihex->section_pointer);
330                 
331                 if (image_ihex->buffer)
332                         free(image_ihex->buffer);
333         }
334         else if (image->type == IMAGE_MEMORY)
335         {
336                 /* do nothing for now */
337         }
338
339         if (image->type_private)
340                 free(image->type_private);
341         
342         if (image->sections)
343                 free(image->sections);
344         
345         return ERROR_OK;
346 }
347
348 int identify_image_type(image_type_t *type, char *type_string)
349 {
350         if (type_string)
351         {
352                 if (!strcmp(type_string, "bin"))
353                 {
354                         *type = IMAGE_BINARY;
355                 }
356                 else if (!strcmp(type_string, "ihex"))
357                 {
358                         *type = IMAGE_IHEX;
359                 }
360                 else
361                 {
362                         return ERROR_IMAGE_TYPE_UNKNOWN;
363                 }
364         }
365         else
366         {
367                 *type = IMAGE_BINARY;
368         }
369         
370         return ERROR_OK;
371 }