- reworked image handling to support multiple sections (tested with ihex file contain...
[openocd.git] / 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 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)