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;
245 char *resource_identifier = NULL;
247 /* try to identify file location */
248 if ((resource_identifier = strstr(url, "bootp://")) && (resource_identifier == url))
250 ERROR("bootp resource location isn't supported yet");
251 return ERROR_FILEIO_RESOURCE_TYPE_UNKNOWN;
253 else if ((resource_identifier = strstr(url, "tftp://")) && (resource_identifier == url))
255 ERROR("tftp resource location isn't supported yet");
256 return ERROR_FILEIO_RESOURCE_TYPE_UNKNOWN;
260 /* default to local files */
261 fileio->location = FILEIO_LOCAL;
264 fileio->access = access;
265 fileio->pri_type = pri_type;
266 fileio->sec_type = sec_type;
267 fileio->url = strdup(url);
269 switch (fileio->location)
272 retval = fileio_open_local(fileio);
275 ERROR("BUG: should never get here");
279 if (retval != ERROR_OK)
282 if (fileio->pri_type == FILEIO_TEXT)
284 /* do nothing for now */
287 else if (fileio->pri_type == FILEIO_IMAGE)
289 fileio_image_t *image = malloc(sizeof(fileio_image_t));
290 fileio_image_t *image_info = pri_info;
292 fileio->pri_type_private = image;
293 *image = *image_info;
295 if (fileio->sec_type == FILEIO_PLAIN)
297 fileio->sec_type_private = NULL;
299 else if (fileio->sec_type == FILEIO_IHEX)
301 fileio_ihex_t *fileio_ihex;
303 if (fileio->access != FILEIO_READ)
305 ERROR("can't write/append to a IHEX file");
306 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "can't write/append to a IHEX file");
307 fileio_close(fileio);
308 return ERROR_FILEIO_OPERATION_FAILED;
311 fileio_ihex = malloc(sizeof(fileio_ihex_t));
312 fileio->sec_type_private = fileio_ihex;
314 fileio_ihex->position = 0;
315 fileio_ihex->raw_size = fileio->size;
316 #ifdef FILEIO_BUFFER_COMPLETE_IHEX
317 if (fileio_ihex_buffer_complete(fileio) != ERROR_OK)
319 fileio_close(fileio);
320 return ERROR_FILEIO_OPERATION_FAILED;
329 int fileio_close_local(fileio_t *fileio)
332 fileio_local_t *fileio_local = fileio->location_private;
334 if ((retval = fclose(fileio_local->file)) != 0)
338 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "BUG: fileio_local->file not a valid file descriptor");
342 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "couldn't close %s: %s", fileio->url, strerror(errno));
345 return ERROR_FILEIO_OPERATION_FAILED;
348 free(fileio->location_private);
353 int fileio_close(fileio_t *fileio)
357 switch (fileio->location)
360 retval = fileio_close_local(fileio);
363 ERROR("BUG: should never get here");
364 retval = ERROR_FILEIO_OPERATION_FAILED;
367 if (retval != ERROR_OK)
372 if (fileio->pri_type == FILEIO_TEXT)
374 /* do nothing for now */
376 else if (fileio->pri_type == FILEIO_IMAGE)
378 if (fileio->sec_type == FILEIO_PLAIN)
380 /* nothing special to do for plain binary */
382 else if (fileio->sec_type == FILEIO_IHEX)
384 fileio_ihex_t *fileio_ihex = fileio->sec_type_private;
386 if (fileio_ihex->buffer)
387 free(fileio_ihex->buffer);
389 free(fileio->sec_type_private);
392 free(fileio->pri_type_private);
398 int fileio_seek_local(fileio_t *fileio, u32 position)
401 fileio_local_t *fileio_local = fileio->location_private;
403 if ((retval = fseek(fileio_local->file, position, SEEK_SET)) != 0)
405 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "couldn't seek file %s: %s", fileio->url, strerror(errno));
406 return ERROR_FILEIO_OPERATION_FAILED;
412 int fileio_seek(fileio_t *fileio, u32 position)
414 switch (fileio->location)
417 return fileio_seek_local(fileio, position);
420 ERROR("BUG: should never get here");
426 int fileio_local_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
428 fileio_local_t *fileio_local = fileio->location_private;
430 *size_read = fread(buffer, 1, size, fileio_local->file);
435 int fileio_dispatch_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
437 switch (fileio->location)
440 return fileio_local_read(fileio, size, buffer, size_read);
443 ERROR("BUG: should never get here");
448 int fileio_read_ihex(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
450 fileio_ihex_t *fileio_ihex = fileio->sec_type_private;
452 if ((fileio_ihex->position + size) > fileio->size)
454 /* don't read past the end of the file */
455 size = (fileio->size - fileio_ihex->position);
458 #ifdef FILEIO_BUFFER_COMPLETE_IHEX
459 memcpy(buffer, fileio_ihex->buffer + fileio_ihex->position, size);
466 int fileio_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
468 if (fileio->sec_type == FILEIO_PLAIN)
470 return fileio_dispatch_read(fileio, size, buffer, size_read);
472 else if (fileio->sec_type == FILEIO_IHEX)
474 return fileio_read_ihex(fileio, size, buffer, size_read);
480 int fileio_local_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
482 fileio_local_t *fileio_local = fileio->location_private;
484 *size_written = fwrite(buffer, 1, size, fileio_local->file);
489 int fileio_dispatch_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
491 switch (fileio->location)
494 return fileio_local_write(fileio, size, buffer, size_written);
497 ERROR("BUG: should never get here");
503 int fileio_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
505 int retval = ERROR_FILEIO_OPERATION_NOT_SUPPORTED;
506 if (fileio->sec_type == FILEIO_PLAIN)
508 retval = fileio_dispatch_write(fileio, size, buffer, size_written);
510 else if (fileio->sec_type == FILEIO_IHEX)
512 return ERROR_FILEIO_OPERATION_NOT_SUPPORTED;
515 if (retval != ERROR_OK)
518 fileio->size += size;
523 int fileio_identify_image_type(enum fileio_sec_type *sec_type, char *type_string)
527 if (!strcmp(type_string, "bin"))
529 *sec_type = FILEIO_PLAIN;
531 else if (!strcmp(type_string, "ihex"))
533 *sec_type = FILEIO_IHEX;
537 return ERROR_FILEIO_RESOURCE_TYPE_UNKNOWN;
542 *sec_type = FILEIO_PLAIN;