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
;