]> git.sur5r.net Git - openocd/blob - src/helper/fileio.c
- fixed arm926 cp15 command bug (thanks to Vincent Palatin for this patch)
[openocd] / src / helper / fileio.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 "types.h"
25 #include "replacements.h"
26 #include "log.h"
27
28 #include "fileio.h"
29
30 #include <stdio.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <stdlib.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <errno.h>
37 #include <ctype.h>
38
39 int fileio_close(fileio_t *fileio);
40 int fileio_dispatch_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read);
41
42 int fileio_open_local(fileio_t *fileio)
43 {
44         fileio_local_t *fileio_local = malloc(sizeof(fileio_local_t));
45         char access[4];
46         
47         fileio->location_private = fileio_local;
48         
49         if ((fileio->access != FILEIO_WRITE) && (fileio->access != FILEIO_READWRITE))
50         {
51                 if (stat(fileio->url, &fileio_local->file_stat) == -1)
52                 {
53                         free(fileio_local);
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;
57                 }
58         
59                 if (S_ISDIR(fileio_local->file_stat.st_mode))
60                 {
61                         free(fileio_local);
62                         snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "%s is a directory", fileio->url);
63                         return ERROR_FILEIO_NOT_FOUND;
64                 }
65         }
66         
67         switch (fileio->access)
68         {
69                 case FILEIO_READ:
70                         strcpy(access, "r");
71                         break;
72                 case FILEIO_WRITE:
73                         strcpy(access, "w");
74                         break;
75                 case FILEIO_READWRITE:
76                         strcpy(access, "w+");
77                         break;
78                 case FILEIO_APPEND:
79                         strcpy(access, "a");    
80                         break;
81                 case FILEIO_APPENDREAD:
82                         strcpy(access, "a+");   
83                         break;
84                 default:
85                         free(fileio_local);
86                         ERROR("BUG: access neither read, write nor readwrite");
87                         return ERROR_INVALID_ARGUMENTS;
88         }
89         
90         if (fileio->access == FILEIO_READ)
91         {
92                 if (fileio_local->file_stat.st_size == 0)
93                 {
94                         /* tried to open an empty file for reading */
95                         free(fileio_local);
96                         snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "empty file %s", fileio->url);
97                         return ERROR_FILEIO_OPERATION_FAILED;
98                 }
99         }
100         
101         if (fileio->pri_type == FILEIO_IMAGE)
102                 strcat(access, "b");
103         
104         if (!(fileio_local->file = fopen(fileio->url, access)))
105         {
106                 free(fileio_local);
107                 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "couldn't open %s", fileio->url);
108                 return ERROR_FILEIO_OPERATION_FAILED;
109         }
110         
111         if ((fileio->access != FILEIO_WRITE) || (fileio->access == FILEIO_READWRITE))
112         {
113                 fileio->size = fileio_local->file_stat.st_size;
114         }
115         else
116         {
117                 fileio->size = 0x0;
118         }
119         
120         return ERROR_OK;
121 }
122
123 //#ifdef FILEIO_BUFFER_COMPLETE_IHEX
124 int fileio_ihex_buffer_complete(fileio_t *fileio)
125 {
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;
129         int retval;
130         u32 full_address = image->base_address;
131         char *buffer = malloc(ihex->raw_size);
132         u32 cooked_bytes = 0x0;
133         
134         ihex->raw_size = fileio->size;
135         ihex->buffer = malloc(ihex->raw_size >> 1);
136         
137         if ((retval = fileio_dispatch_read(fileio, ihex->raw_size, (u8*)buffer, &raw_bytes_read)) != ERROR_OK)
138         {
139                 free(buffer);
140                 ERROR("failed buffering IHEX file, read failed");
141                 return ERROR_FILEIO_OPERATION_FAILED;
142         }
143         
144         if (raw_bytes_read != ihex->raw_size)
145         {
146                 free(buffer);
147                 ERROR("failed buffering complete IHEX file, only partially read");
148                 return ERROR_FILEIO_OPERATION_FAILED;
149         }
150         
151         raw_bytes = 0x0;
152         while (raw_bytes < raw_bytes_read)
153         {
154                 u32 count;
155                 u32 address;
156                 u32 record_type;
157                 u32 checksum;
158                 
159                 if (sscanf(&buffer[raw_bytes], ":%2x%4x%2x", &count, &address, &record_type) != 3)
160                 {
161                         snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "invalid IHEX record");
162                         return ERROR_FILEIO_OPERATION_FAILED;
163                 }
164                 raw_bytes += 9;
165                 
166                 if (record_type == 0)
167                 {
168                         if ((full_address & 0xffff) != address)
169                         {
170                                 free(buffer);
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;
174                         }
175                         
176                         while (count-- > 0)
177                         {
178                                 sscanf(&buffer[raw_bytes], "%2hhx", &ihex->buffer[cooked_bytes]);
179                                 raw_bytes += 2;
180                                 cooked_bytes += 1;
181                                 full_address++;
182                         }
183                 }
184                 else if (record_type == 1)
185                 {
186                         free(buffer);
187                         fileio->size = cooked_bytes;
188                         return ERROR_OK;
189                 }
190                 else if (record_type == 4)
191                 {
192                         u16 upper_address;
193                         
194                         sscanf(&buffer[raw_bytes], "%4hx", &upper_address);
195                         raw_bytes += 4;
196                         
197                         if ((full_address >> 16) != upper_address)
198                         {
199                                 free(buffer);
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;
203                         }
204                 }
205                 else if (record_type == 5)
206                 {
207                         u32 start_address;
208                         
209                         sscanf(&buffer[raw_bytes], "%8x", &start_address);
210                         raw_bytes += 8;
211                         
212                         image->has_start_address = 1;
213                         image->start_address = be_to_h_u32((u8*)&start_address);
214                 }
215                 else
216                 {
217                         free(buffer);
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;
221                 }
222                 
223                 sscanf(&buffer[raw_bytes], "%2x", &checksum);
224                 raw_bytes += 2;
225                 
226                 /* consume new-line character(s) */
227                 if ((buffer[raw_bytes] == '\n') || (buffer[raw_bytes] == '\r'))
228                         raw_bytes++;
229
230                 if ((buffer[raw_bytes] == '\n') || (buffer[raw_bytes] == '\r'))
231                         raw_bytes++;
232         }
233
234         free(buffer);
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;   
238 }
239 //#endif
240
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)
243 {
244         int retval = ERROR_OK;
245         
246         if ((!url) || (strlen(url) < 3))
247         {
248                 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "invalid file url");
249                 return ERROR_INVALID_ARGUMENTS;
250         }
251         
252         if ((url[0] == '/') || (isalpha(url[0])) || ((url[1] == ':') && (url[2] == '\\')))
253         {
254                 fileio->location = FILEIO_LOCAL;
255         }
256         else
257         {
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;
261         }
262         
263         fileio->access = access;
264         fileio->pri_type = pri_type;
265         fileio->sec_type = sec_type;
266         fileio->url = strdup(url);
267         
268         switch (fileio->location)
269         {
270                 case FILEIO_LOCAL:
271                         retval = fileio_open_local(fileio);
272                         break;
273                 default:
274                         ERROR("BUG: should never get here");
275                         exit(-1);
276         }
277         
278         if (retval != ERROR_OK)
279                 return retval;
280         
281         if (fileio->pri_type == FILEIO_TEXT)
282         {
283                 /* do nothing for now */
284                 return ERROR_OK;
285         }
286         else if (fileio->pri_type == FILEIO_IMAGE)
287         {
288                 fileio_image_t *image = malloc(sizeof(fileio_image_t));
289                 fileio_image_t *image_info = pri_info;
290                 
291                 fileio->pri_type_private = image;
292                 *image = *image_info; 
293                 
294                 if (fileio->sec_type == FILEIO_PLAIN)
295                 {
296                         fileio->sec_type_private = NULL;
297                 }
298                 else if (fileio->sec_type == FILEIO_IHEX)
299                 {
300                         fileio_ihex_t *fileio_ihex;
301                         
302                         if (fileio->access != FILEIO_READ)
303                         {
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;
308                         }
309                         
310                         fileio_ihex = malloc(sizeof(fileio_ihex_t));
311                         fileio->sec_type_private = fileio_ihex;
312                         
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)
317                         {
318                                 fileio_close(fileio);
319                                 return ERROR_FILEIO_OPERATION_FAILED;
320                         }
321 #endif
322                 }
323         }
324         
325         return ERROR_OK;
326 }
327
328 int fileio_close_local(fileio_t *fileio)
329 {
330         int retval;
331         fileio_local_t *fileio_local = fileio->location_private;
332         
333         if ((retval = fclose(fileio_local->file)) != 0)
334         {
335                 if (retval == EBADF)
336                 {
337                         snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "BUG: fileio_local->file not a valid file descriptor");
338                 }
339                 else
340                 {
341                         snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "couldn't close %s: %s", fileio->url, strerror(errno));
342                 }
343
344                 return ERROR_FILEIO_OPERATION_FAILED;
345         }
346         
347         free(fileio->location_private);
348         
349         return ERROR_OK;
350 }
351
352 int fileio_close(fileio_t *fileio)
353 {
354         int retval;
355         
356         switch (fileio->location)
357         {
358                 case FILEIO_LOCAL:
359                         retval = fileio_close_local(fileio);
360                         break;
361                 default:
362                         ERROR("BUG: should never get here");
363                         retval = ERROR_FILEIO_OPERATION_FAILED;
364         }
365         
366         if (retval != ERROR_OK)
367                 return retval;
368         
369         free(fileio->url);
370         
371         if (fileio->pri_type == FILEIO_TEXT)
372         {
373                 /* do nothing for now */
374         }
375         else if (fileio->pri_type == FILEIO_IMAGE)
376         {
377                 if (fileio->sec_type == FILEIO_PLAIN)
378                 {
379                         /* nothing special to do for plain binary */
380                 }
381                 else if (fileio->sec_type == FILEIO_IHEX)
382                 {
383                         fileio_ihex_t *fileio_ihex = fileio->sec_type_private;
384         
385                         if (fileio_ihex->buffer)
386                                 free(fileio_ihex->buffer);
387                         
388                         free(fileio->sec_type_private);
389                 }
390                 
391                 free(fileio->pri_type_private);
392         }
393         
394         return ERROR_OK;
395 }
396
397 int fileio_seek_local(fileio_t *fileio, u32 position)
398 {
399         int retval;
400         fileio_local_t *fileio_local = fileio->location_private;
401         
402         if ((retval = fseek(fileio_local->file, position, SEEK_SET)) != 0)
403         {
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;
406         }
407         
408         return ERROR_OK;
409 }
410
411 int fileio_seek(fileio_t *fileio, u32 position)
412 {
413         switch (fileio->location)
414         {
415                 case FILEIO_LOCAL:
416                         return fileio_seek_local(fileio, position);
417                         break;
418                 default:
419                         ERROR("BUG: should never get here");
420         }
421         
422         return ERROR_OK;
423 }
424
425 int fileio_local_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
426 {
427         fileio_local_t *fileio_local = fileio->location_private;
428         
429         *size_read = fread(buffer, 1, size, fileio_local->file);
430         
431         return ERROR_OK;
432 }
433
434 int fileio_dispatch_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
435 {
436         switch (fileio->location)
437         {
438                 case FILEIO_LOCAL:
439                         return fileio_local_read(fileio, size, buffer, size_read);
440                         break;
441                 default:
442                         ERROR("BUG: should never get here");
443                         exit(-1);
444         }
445 }
446
447 int fileio_read_ihex(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
448 {
449         fileio_ihex_t *fileio_ihex = fileio->sec_type_private;
450
451         if ((fileio_ihex->position + size) > fileio->size)
452         {
453                 /* don't read past the end of the file */
454                 size = (fileio->size - fileio_ihex->position);
455         }
456         
457 #ifdef FILEIO_BUFFER_COMPLETE_IHEX
458         memcpy(buffer, fileio_ihex->buffer + fileio_ihex->position, size);
459         *size_read = size;
460 #endif
461
462         return ERROR_OK;
463 }
464
465 int fileio_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
466 {
467         if (fileio->sec_type == FILEIO_PLAIN)
468         {
469                 return fileio_dispatch_read(fileio, size, buffer, size_read);
470         }
471         else if (fileio->sec_type == FILEIO_IHEX)
472         {
473                 return fileio_read_ihex(fileio, size, buffer, size_read);
474         }
475         
476         return ERROR_OK;
477 }
478
479 int fileio_local_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
480 {
481         fileio_local_t *fileio_local = fileio->location_private;
482         
483         *size_written = fwrite(buffer, 1, size, fileio_local->file);
484         
485         return ERROR_OK;
486 }
487
488 int fileio_dispatch_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
489 {
490         switch (fileio->location)
491         {
492                 case FILEIO_LOCAL:
493                         return fileio_local_write(fileio, size, buffer, size_written);
494                         break;
495                 default:
496                         ERROR("BUG: should never get here");
497         }
498         
499         return ERROR_OK;
500 }
501
502 int fileio_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
503 {
504         int retval = ERROR_FILEIO_OPERATION_NOT_SUPPORTED;
505         if (fileio->sec_type == FILEIO_PLAIN)
506         {
507                 retval = fileio_dispatch_write(fileio, size, buffer, size_written);
508         }
509         else if (fileio->sec_type == FILEIO_IHEX)
510         {
511                 return ERROR_FILEIO_OPERATION_NOT_SUPPORTED;
512         }
513         
514         if (retval != ERROR_OK)
515                 return retval;
516                 
517         fileio->size += size;
518         
519         return ERROR_OK;
520 }
521
522 int fileio_identify_image_type(enum fileio_sec_type *sec_type, char *type_string)
523 {
524         if (type_string)
525         {
526                 if (!strcmp(type_string, "bin"))
527                 {
528                         *sec_type = FILEIO_PLAIN;
529                 }
530                 else if (!strcmp(type_string, "ihex"))
531                 {
532                         *sec_type = FILEIO_IHEX;
533                 }
534                 else
535                 {
536                         return ERROR_FILEIO_RESOURCE_TYPE_UNKNOWN;
537                 }
538         }
539         else
540         {
541                 *sec_type = FILEIO_PLAIN;
542         }
543         
544         return ERROR_OK;
545 }