📄 fileio.c
字号:
/* * avrdude - A Downloader/Uploader for AVR device programmers * Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean <bsd@bsdhome.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* $Id: fileio.c,v 1.22 2003/02/20 03:53:49 bdean Exp $ */#include "ac_cfg.h"#include <limits.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <ctype.h>#include "avr.h"#include "fileio.h"#define IHEX_MAXDATA 256#define MAX_LINE_LEN 256 /* max line length for ASCII format input files */struct ihexrec { unsigned char reclen; unsigned int loadofs; unsigned char rectyp; unsigned char data[IHEX_MAXDATA]; unsigned char cksum;};extern char * progname;extern char progbuf[];int b2ihex(unsigned char * inbuf, int bufsize, int recsize, int startaddr, char * outfile, FILE * outf);int ihex2b(char * infile, FILE * inf, unsigned char * outbuf, int bufsize);int b2srec(unsigned char * inbuf, int bufsize, int recsize, int startaddr, char * outfile, FILE * outf);int srec2b(char * infile, FILE * inf, unsigned char * outbuf, int bufsize);int ihex_readrec(struct ihexrec * ihex, char * rec);int srec_readrec(struct ihexrec * srec, char * rec); int fileio_rbin(struct fioparms * fio, char * filename, FILE * f, unsigned char * buf, int size);int fileio_ihex(struct fioparms * fio, char * filename, FILE * f, unsigned char * buf, int size);int fileio_srec(struct fioparms * fio, char * filename, FILE * f, unsigned char * buf, int size);int fmt_autodetect(char * fname);char * fmtstr(FILEFMT format){ switch (format) { case FMT_AUTO : return "auto-detect"; break; case FMT_SREC : return "Motorola S-Record"; break; case FMT_IHEX : return "Intel Hex"; break; case FMT_RBIN : return "raw binary"; break; default : return "invalid format"; break; };}int b2ihex(unsigned char * inbuf, int bufsize, int recsize, int startaddr, char * outfile, FILE * outf){ unsigned char * buf; unsigned int nextaddr; int n, nbytes, n_64k; int i; unsigned char cksum; if (recsize > 255) { fprintf(stderr, "%s: recsize=%d, must be < 256\n", progname, recsize); return -1; } n_64k = 0; nextaddr = startaddr; buf = inbuf; nbytes = 0; while (bufsize) { n = recsize; if (n > bufsize) n = bufsize; if ((nextaddr + n) > 0x10000) n = 0x10000 - nextaddr; if (n) { cksum = 0; fprintf(outf, ":%02X%04X00", n, nextaddr); cksum += n + ((nextaddr >> 8) & 0x0ff) + (nextaddr & 0x0ff); for (i=0; i<n; i++) { fprintf(outf, "%02X", buf[i]); cksum += buf[i]; } cksum = -cksum; fprintf(outf, "%02X\n", cksum); nextaddr += n; nbytes += n; } if (nextaddr >= 0x10000) { int lo, hi; /* output an extended address record */ n_64k++; lo = n_64k & 0xff; hi = (n_64k >> 8) & 0xff; cksum = 0; fprintf(outf, ":02000004%02X%02X", hi, lo); cksum += 2 + 0 + 4 + hi + lo; cksum = -cksum; fprintf(outf, "%02X\n", cksum); nextaddr = 0; } /* advance to next 'recsize' bytes */ buf += n; bufsize -= n; } /*----------------------------------------------------------------- add the end of record data line -----------------------------------------------------------------*/ cksum = 0; n = 0; nextaddr = 0; fprintf(outf, ":%02X%04X01", n, nextaddr); cksum += n + ((nextaddr >> 8) & 0x0ff) + (nextaddr & 0x0ff) + 1; cksum = -cksum; fprintf(outf, "%02X\n", cksum); return nbytes;}int ihex_readrec(struct ihexrec * ihex, char * rec){ int i, j; char buf[8]; int offset, len; char * e; unsigned char cksum; int rc; len = strlen(rec); offset = 1; cksum = 0; /* reclen */ if (offset + 2 > len) return -1; for (i=0; i<2; i++) buf[i] = rec[offset++]; buf[i] = 0; ihex->reclen = strtoul(buf, &e, 16); if (e == buf || *e != 0) return -1; /* load offset */ if (offset + 4 > len) return -1; for (i=0; i<4; i++) buf[i] = rec[offset++]; buf[i] = 0; ihex->loadofs = strtoul(buf, &e, 16); if (e == buf || *e != 0) return -1; /* record type */ if (offset + 2 > len) return -1; for (i=0; i<2; i++) buf[i] = rec[offset++]; buf[i] = 0; ihex->rectyp = strtoul(buf, &e, 16); if (e == buf || *e != 0) return -1; cksum = ihex->reclen + ((ihex->loadofs >> 8) & 0x0ff) + (ihex->loadofs & 0x0ff) + ihex->rectyp; /* data */ for (j=0; j<ihex->reclen; j++) { if (offset + 2 > len) return -1; for (i=0; i<2; i++) buf[i] = rec[offset++]; buf[i] = 0; ihex->data[j] = strtoul(buf, &e, 16); if (e == buf || *e != 0) return -1; cksum += ihex->data[j]; } /* cksum */ if (offset + 2 > len) return -1; for (i=0; i<2; i++) buf[i] = rec[offset++]; buf[i] = 0; ihex->cksum = strtoul(buf, &e, 16); if (e == buf || *e != 0) return -1; rc = -cksum & 0x000000ff; return rc;}/* * Intel Hex to binary buffer * * Given an open file 'inf' which contains Intel Hex formated data, * parse the file and lay it out within the memory buffer pointed to * by outbuf. The size of outbuf, 'bufsize' is honored; if data would * fall outsize of the memory buffer outbuf, an error is generated. * * Return the maximum memory address within 'outbuf' that was written. * If an error occurs, return -1. * * */int ihex2b(char * infile, FILE * inf, unsigned char * outbuf, int bufsize){ char buffer [ MAX_LINE_LEN ]; unsigned char * buf; unsigned int nextaddr, baseaddr, maxaddr; int i; int lineno; int len; struct ihexrec ihex; int rc; lineno = 0; buf = outbuf; baseaddr = 0; maxaddr = 0; while (fgets((char *)buffer,MAX_LINE_LEN,inf)!=NULL) { lineno++; len = strlen(buffer); if (buffer[len-1] == '\n') buffer[--len] = 0; if (buffer[0] != ':') continue; rc = ihex_readrec(&ihex, buffer); if (rc < 0) { fprintf(stderr, "%s: invalid record at line %d of \"%s\"\n", progname, lineno, infile); return -1; } else if (rc != ihex.cksum) { fprintf(stderr, "%s: ERROR: checksum mismatch at line %d of \"%s\"\n", progname, lineno, infile); fprintf(stderr, "%s: checksum=0x%02x, computed checksum=0x%02x\n", progname, ihex.cksum, rc); return -1; } switch (ihex.rectyp) { case 0: /* data record */ nextaddr = ihex.loadofs + baseaddr; if (nextaddr + ihex.reclen > bufsize) { fprintf(stderr, "%s: ERROR: address 0x%04x out of range at line %d of %s\n", progname, nextaddr+ihex.reclen, lineno, infile); return -1; } for (i=0; i<ihex.reclen; i++) { buf[nextaddr+i] = ihex.data[i]; } if (nextaddr+ihex.reclen > maxaddr) maxaddr = nextaddr+ihex.reclen; break; case 1: /* end of file record */ return maxaddr; break; case 2: /* extended segment address record */ baseaddr = (ihex.data[0] << 8 | ihex.data[1]) << 4; break; case 3: /* start segment address record */ /* we don't do anything with the start address */ break; case 4: /* extended linear address record */ baseaddr = (ihex.data[0] << 8 | ihex.data[1]) << 16; break; case 5: /* start linear address record */ /* we don't do anything with the start address */ break; default: fprintf(stderr, "%s: don't know how to deal with rectype=%d " "at line %d of %s\n", progname, ihex.rectyp, lineno, infile); return -1; break; } } /* while */ fprintf(stderr, "%s: WARNING: no end of file record found for Intel Hex " "file \"%s\"\n", progname, infile); return maxaddr;}int b2srec(unsigned char * inbuf, int bufsize, int recsize, int startaddr, char * outfile, FILE * outf){ unsigned char * buf; unsigned int nextaddr, stopaddr; int n, nbytes, addr_width; int i; unsigned char cksum; unsigned char startf, stopf ,emptyf; char * tmpl=0; if (recsize > 255) { fprintf(stderr, "%s: ERROR: recsize=%d, must be < 256\n", progname, recsize); return -1; } buf = inbuf; nextaddr = 0; stopaddr = 0; startf = 0; stopf = 0; /* search for ranges of 'real' data */ for (i=startaddr; i<bufsize; i++) { if (buf[i] == 0xff) { if (startf == 0) continue; else if (stopf == 0) { stopf = 1; stopaddr = i; } } else { if (startf == 0) { startf = 1; nextaddr = i; while (nextaddr % recsize != 0) nextaddr --; } else if (stopf == 1) { stopf = 0; stopaddr = bufsize; } } } nbytes = i; bufsize = stopaddr - nextaddr; addr_width = 0; while (bufsize) { n = recsize; if (n > bufsize) n = bufsize; if (n) { cksum = 0; if (nextaddr + n <= 0xffff) { addr_width = 2; tmpl="S1%02X%04X"; } else if (nextaddr + n <= 0xffffff) { addr_width = 3; tmpl="S2%02X%06X"; } else if (nextaddr + n <= 0xffffffff) { addr_width = 4; tmpl="S3%02X%08X"; } else { fprintf(stderr, "%s: ERROR: address=%d, out of range\n", progname, nextaddr); return -1; } /* skip the lines filled with 0xff */ emptyf = 1; for (i=nextaddr; i<nextaddr + n; i++) { if (buf[i] != 0xff) { emptyf=0; break; } } if (emptyf != 1) { fprintf(outf, tmpl, n + addr_width + 1, nextaddr); cksum += n + addr_width + 1; for (i=addr_width; i>0; i--) cksum += (nextaddr >> (i-1) * 8) & 0xff; for (i=nextaddr; i<nextaddr + n; i++) { fprintf(outf, "%02X", buf[i]); cksum += buf[i]; } cksum = 0xff - cksum; fprintf(outf, "%02X\n", cksum); } nextaddr += n; } /* advance to next 'recsize' bytes */ bufsize -= n; } /*----------------------------------------------------------------- add the end of record data line -----------------------------------------------------------------*/ cksum = 0; n = 0; nextaddr = 0; if (startaddr <= 0xffff) { addr_width = 2; tmpl="S9%02X%04X"; } else if (startaddr <= 0xffffff) { addr_width = 3; tmpl="S9%02X%06X"; } else if (startaddr <= 0xffffffff) { addr_width = 4; tmpl="S9%02X%08X";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -