1 /***************************************************************************
2 * Copyright (C) 2007 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
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. *
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. *
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 ***************************************************************************/
25 #include "replacements.h"
34 #include <sys/types.h>
39 int fileio_close(fileio_t *fileio);
40 int fileio_dispatch_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read);
42 int fileio_open_local(fileio_t *fileio)
44 fileio_local_t *fileio_local = malloc(sizeof(fileio_local_t));
47 fileio->location_private = fileio_local;
49 if ((fileio->access != FILEIO_WRITE) && (fileio->access != FILEIO_READWRITE))
51 if (stat(fileio->url, &fileio_local->file_stat) == -1)
54 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING,
55 "couldn't stat() %s: %s", fileio->url, strerror(errno));
56 return ERROR_FILEIO_NOT_FOUND;
59 if (S_ISDIR(fileio_local->file_stat.st_mode))
62 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "%s is a directory", fileio->url);
63 return ERROR_FILEIO_NOT_FOUND;
67 switch (fileio->access)
75 case FILEIO_READWRITE:
81 case FILEIO_APPENDREAD:
86 ERROR("BUG: access neither read, write nor readwrite");
87 return ERROR_INVALID_ARGUMENTS;
90 if (fileio->access == FILEIO_READ)
92 if (fileio_local->file_stat.st_size == 0)
94 /* tried to open an empty file for reading */
96 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "empty file %s", fileio->url);
97 return ERROR_FILEIO_OPERATION_FAILED;
101 if (fileio->pri_type == FILEIO_IMAGE)
104 if (!(fileio_local->file = fopen(fileio->url, access)))
107 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "couldn't open %s", fileio->url);
108 return ERROR_FILEIO_OPERATION_FAILED;
111 if ((fileio->access != FILEIO_WRITE) || (fileio->access == FILEIO_READWRITE))
113 fileio->size = fileio_local->file_stat.st_size;
123 //#ifdef FILEIO_BUFFER_COMPLETE_IHEX
124 int fileio_ihex_buffer_complete(fileio_t *fileio)
126 fileio_image_t *image = fileio->pri_type_private;
127 fileio_ihex_t *ihex = fileio->sec_type_private;
128 u32 raw_bytes_read, raw_bytes;
130 u32 full_address = image->base_address;
131 char *buffer = malloc(ihex->raw_size);
132 u32 cooked_bytes = 0x0;
134 ihex->raw_size = fileio->size;
135 ihex->buffer = malloc(ihex->raw_size >> 1);
137 if ((retval = fileio_dispatch_read(fileio, ihex->raw_size, (u8*)buffer, &raw_bytes_read)) != ERROR_OK)
140 ERROR("failed buffering IHEX file, read failed");
141 return ERROR_FILEIO_OPERATION_FAILED;
144 if (raw_bytes_read != ihex->raw_size)
147 ERROR("failed buffering complete IHEX file, only partially read");
148 return ERROR_FILEIO_OPERATION_FAILED;
152 while (raw_bytes < raw_bytes_read)
159 if (sscanf(&buffer[raw_bytes], ":%2x%4x%2x", &count, &address, &record_type) != 3)
161 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "invalid IHEX record");
162 return ERROR_FILEIO_OPERATION_FAILED;
166 if (record_type == 0)
168 if ((full_address & 0xffff) != address)
171 ERROR("can't handle non-linear IHEX file");
172 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "can't handle non-linear IHEX file");
173 return ERROR_FILEIO_OPERATION_FAILED;
178 sscanf(&buffer[raw_bytes], "%2hhx", &ihex->buffer[cooked_bytes]);
184 else if (record_type == 1)
187 fileio->size = cooked_bytes;
190 else if (record_type == 4)
194 sscanf(&buffer[raw_bytes], "%4hx", &upper_address);
197 if ((full_address >> 16) != upper_address)
200 ERROR("can't handle non-linear IHEX file");
201 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "can't handle non-linear IHEX file");
202 return ERROR_FILEIO_OPERATION_FAILED;
205 else if (record_type == 5)
209 sscanf(&buffer[raw_bytes], "%8x", &start_address);
212 image->has_start_address = 1;
213 image->start_address = be_to_h_u32((u8*)&start_address);
218 ERROR("unhandled IHEX record type: %i", record_type);
219 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "unhandled IHEX record type: %i", record_type);
220 return ERROR_FILEIO_OPERATION_FAILED;
223 sscanf(&buffer[raw_bytes], "%2x", &checksum);
226 /* consume new-line character(s) */
227 if ((buffer[raw_bytes] == '\n') || (buffer[raw_bytes] == '\r'))
230 if ((buffer[raw_bytes] == '\n') || (buffer[raw_bytes] == '\r'))
235 ERROR("premature end of IHEX file, no end-of-file record found");
236 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "premature end of IHEX file, no end-of-file record found");
237 return ERROR_FILEIO_OPERATION_FAILED;
241 int fileio_open(fileio_t *fileio, char *url, enum fileio_access access,
242 enum fileio_pri_type pri_type, void *pri_info, enum fileio_sec_type sec_type)
244 int retval = ERROR_OK;
246 if ((!url) || (strlen(url) < 3))
248 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "invalid file url");
249 return ERROR_INVALID_ARGUMENTS;
252 if ((url[0] == '/') || (isalpha(url[0])) || ((url[1] == ':') && (url[2] == '\\')))
254 fileio->location = FILEIO_LOCAL;
258 ERROR("couldn't identify resource location from URL '%s'", url);
259 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "couldn't identify resource location from URL '%s'", url);
260 return ERROR_FILEIO_LOCATION_UNKNOWN;
263 fileio->access = access;
264 fileio->pri_type = pri_type;
265 fileio->sec_type = sec_type;
266 fileio->url = strdup(url);
268 switch (fileio->location)
271 retval = fileio_open_local(fileio);
274 ERROR("BUG: should never get here");
278 if (retval != ERROR_OK)
281 if (fileio->pri_type == FILEIO_TEXT)
283 /* do nothing for now */
286 else if (fileio->pri_type == FILEIO_IMAGE)
288 fileio_image_t *image = malloc(sizeof(fileio_image_t));
289 fileio_image_t *image_info = pri_info;
291 fileio->pri_type_private = image;
292 *image = *image_info;
294 if (fileio->sec_type == FILEIO_PLAIN)
296 fileio->sec_type_private = NULL;
298 else if (fileio->sec_type == FILEIO_IHEX)
300 fileio_ihex_t *fileio_ihex;
302 if (fileio->access != FILEIO_READ)
304 ERROR("can't write/append to a IHEX file");
305 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "can't write/append to a IHEX file");
306 fileio_close(fileio);
307 return ERROR_FILEIO_OPERATION_FAILED;
310 fileio_ihex = malloc(sizeof(fileio_ihex_t));
311 fileio->sec_type_private = fileio_ihex;
313 fileio_ihex->position = 0;
314 fileio_ihex->raw_size = fileio->size;
315 #ifdef FILEIO_BUFFER_COMPLETE_IHEX
316 if (fileio_ihex_buffer_complete(fileio) != ERROR_OK)
318 fileio_close(fileio);
319 return ERROR_FILEIO_OPERATION_FAILED;
328 int fileio_close_local(fileio_t *fileio)
331 fileio_local_t *fileio_local = fileio->location_private;
333 if ((retval = fclose(fileio_local->file)) != 0)
337 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "BUG: fileio_local->file not a valid file descriptor");
341 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "couldn't close %s: %s", fileio->url, strerror(errno));
344 return ERROR_FILEIO_OPERATION_FAILED;
347 free(fileio->location_private);
352 int fileio_close(fileio_t *fileio)
356 switch (fileio->location)
359 retval = fileio_close_local(fileio);
362 ERROR("BUG: should never get here");
363 retval = ERROR_FILEIO_OPERATION_FAILED;
366 if (retval != ERROR_OK)
371 if (fileio->pri_type == FILEIO_TEXT)
373 /* do nothing for now */
375 else if (fileio->pri_type == FILEIO_IMAGE)
377 if (fileio->sec_type == FILEIO_PLAIN)
379 /* nothing special to do for plain binary */
381 else if (fileio->sec_type == FILEIO_IHEX)
383 fileio_ihex_t *fileio_ihex = fileio->sec_type_private;
385 if (fileio_ihex->buffer)
386 free(fileio_ihex->buffer);
388 free(fileio->sec_type_private);
391 free(fileio->pri_type_private);
397 int fileio_seek_local(fileio_t *fileio, u32 position)
400 fileio_local_t *fileio_local = fileio->location_private;
402 if ((retval = fseek(fileio_local->file, position, SEEK_SET)) != 0)
404 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "couldn't seek file %s: %s", fileio->url, strerror(errno));
405 return ERROR_FILEIO_OPERATION_FAILED;
411 int fileio_seek(fileio_t *fileio, u32 position)
413 switch (fileio->location)
416 return fileio_seek_local(fileio, position);
419 ERROR("BUG: should never get here");
425 int fileio_local_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
427 fileio_local_t *fileio_local = fileio->location_private;
429 *size_read = fread(buffer, 1, size, fileio_local->file);
434 int fileio_dispatch_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
436 switch (fileio->location)
439 return fileio_local_read(fileio, size, buffer, size_read);
442 ERROR("BUG: should never get here");
447 int fileio_read_ihex(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
449 fileio_ihex_t *fileio_ihex = fileio->sec_type_private;
451 if ((fileio_ihex->position + size) > fileio->size)
453 /* don't read past the end of the file */
454 size = (fileio->size - fileio_ihex->position);
457 #ifdef FILEIO_BUFFER_COMPLETE_IHEX
458 memcpy(buffer, fileio_ihex->buffer + fileio_ihex->position, size);
465 int fileio_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
467 if (fileio->sec_type == FILEIO_PLAIN)
469 return fileio_dispatch_read(fileio, size, buffer, size_read);
471 else if (fileio->sec_type == FILEIO_IHEX)
473 return fileio_read_ihex(fileio, size, buffer, size_read);
479 int fileio_local_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
481 fileio_local_t *fileio_local = fileio->location_private;
483 *size_written = fwrite(buffer, 1, size, fileio_local->file);
488 int fileio_dispatch_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
490 switch (fileio->location)
493 return fileio_local_write(fileio, size, buffer, size_written);
496 ERROR("BUG: should never get here");
502 int fileio_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
504 int retval = ERROR_FILEIO_OPERATION_NOT_SUPPORTED;
505 if (fileio->sec_type == FILEIO_PLAIN)
507 retval = fileio_dispatch_write(fileio, size, buffer, size_written);
509 else if (fileio->sec_type == FILEIO_IHEX)
511 return ERROR_FILEIO_OPERATION_NOT_SUPPORTED;
514 if (retval != ERROR_OK)
517 fileio->size += size;
522 int fileio_identify_image_type(enum fileio_sec_type *sec_type, char *type_string)
526 if (!strcmp(type_string, "bin"))
528 *sec_type = FILEIO_PLAIN;
530 else if (!strcmp(type_string, "ihex"))
532 *sec_type = FILEIO_IHEX;
536 return ERROR_FILEIO_RESOURCE_TYPE_UNKNOWN;
541 *sec_type = FILEIO_PLAIN;