URL
https://opencores.org/ocsvn/tinyvliw8/tinyvliw8/trunk
Subversion Repositories tinyvliw8
[/] [tinyvliw8/] [trunk/] [tools/] [bin2hex/] [src/] [main.c] - Rev 5
Go to most recent revision | Compare with Previous | Blame | View Log
/** * \file main.c * \date 25.07.2013 * \author Oliver Stecklina <stecklina@ihp-microelectronics.com> */ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> typedef enum _mem_width_e { _mem_width_8bit = 0, _mem_width_16bit, _mem_width_32bit } _mem_width_t; static char *_infile = NULL; static _mem_width_t _mem_width = _mem_width_32bit; static unsigned int _start_addr = 0x0000; static char *_outfile = NULL; static unsigned char _ascii = 0; static int _parse_args(int argc, char *argv[]) { int err, i; err = 0; for (i = 1; 0 == err && i < argc; i++) { if ('-' != *argv[i]) { if ((i + 1) == argc) { _infile = argv[i]; break; } fprintf(stderr, "\tERROR! bad option <%s>\n", argv[i]); err = -EINVAL; break; } switch (*(argv[i] + 1)) { case 'a': _ascii = 1; break; case 'o': if ((i + 1) < argc) { i++; _outfile = argv[i]; break; } fprintf(stderr, "\tERROR! option <%s> requires an argument\n", argv[i]); err = -EINVAL; break; case 's': if ((i + 1) < argc) { long num; i++; num = strtol(argv[i], NULL, 0); if (0 <= num && 0x10000 > num) { _start_addr = num; } else { fprintf(stderr, "\tERROR! bogus start address\n"); err = -ERANGE; } break; } fprintf(stderr, "\tERROR! option <%s> requires an argument\n", argv[i]); err = -EINVAL; break; case 'w': if ((i + 1) < argc) { long num; i++; num = strtol(argv[i], NULL, 0); switch (num) { case 8: _mem_width = _mem_width_8bit; break; case 16: _mem_width = _mem_width_16bit; break; case 32: _mem_width = _mem_width_32bit; break; default: fprintf(stderr, "\tERROR! invalid memory width\n"); err = -ERANGE; } break; } fprintf(stderr, "\tERROR! option <%s> requires an argument\n", argv[i]); err = -EINVAL; break; case 'h': printf("%s [option] <input>\n", argv[0]); printf("\t-a ascii input\n"); printf("\t-o <file> output filename (default: stdout)\n"); printf("\t-s <num> start address (default: 0x0000)\n"); printf("\t-w [8|16|32] memory width in bit (default: 32)\n"); printf("\t-h useful help\n"); exit(0); } } if (0 == err && NULL == _infile) { fprintf(stderr, "\tERROR! no input file given\n"); err = -EINVAL; } return err; } static unsigned char _mem_width2byte(const _mem_width_t mwidth) { unsigned char width; switch (mwidth) { case _mem_width_8bit: width = 1; break; case _mem_width_16bit: width = 2; break; case _mem_width_32bit: width = 4; break; } return width; } static char *_asci2bin(char *img, unsigned int *size_ptr) { unsigned int i, j, k; unsigned char c; char *p; for (i = 0, j = 0, k = 7, c = 0; i < *size_ptr; i++) { switch (*(img + i)) { case '0': break; case '1': c |= 1 << k; break; default: /* ignore */ continue; } if (0 == k) { /* move char to buffer */ *(img + j) = c; /* reset bit pos and char */ k = 7; c = 0; /* increment pos in output buffer */ j++; } else k--; } if (7 != k) { fprintf(stderr, "\tWARNING! input is not byte aligned.\n"); *(img + j) = c; j++; } p = NULL; *size_ptr = j; if (0 < j) { p = malloc(j); if (NULL != p) memcpy(p, img, j); } free(img); return p; } static char *_load_image(const char *filename, unsigned int *size_ptr, const unsigned char ascii, const _mem_width_t mwidth) { char *img; int err; img = NULL; err = open(filename, O_RDONLY); if (0 <= err) { struct stat s; int fd; fd = err; err = fstat(fd, &s); if (0 == err) { img = malloc(s.st_size); if (NULL != img) { unsigned int done; done = 0; do { err = read(fd, img + done, s.st_size - done); if (0 > err) { err = -errno; if (-EINTR == err) { err = 0; continue; } break; } done += err; err = 0; } while (0 == err && done < s.st_size); if (0 == err) { unsigned int size; size = s.st_size; if (0 != ascii) { img = _asci2bin(img, &size); } if (0 != (s.st_size & (_mem_width2byte(mwidth) - 1))) { fprintf(stderr, "\tWARNING! input size does not match with memory width\n"); } *size_ptr = size; } else { free(img); img = NULL; } } else err = -ENOMEM; } else err = -errno; close(fd); } else err = -errno; if (0 != err) fprintf(stderr, "\tERROR! loading input file <%s>", filename); return img; } #define _BUFSIZ ((16 << 1) + 4 + 2 + 2 + 2 + 1 + 1 + 1) static int _ihex_out(const int fd, const unsigned short addr, const char *data, const unsigned int len) { unsigned int j, i; char buf[_BUFSIZ]; int err; if (0 < len) { unsigned char chksum; chksum = 0; i = snprintf(&buf[0], _BUFSIZ, ":%02x%04x00", len, addr); if (_BUFSIZ < i) return -ENOSPC; for (j = 0; j < len; j++) { i += snprintf(&buf[i], _BUFSIZ - i, "%02x", (unsigned char) *(data + j)); if (_BUFSIZ < i) return -ENOSPC; chksum += *(data + j); } chksum += len; chksum += addr & 0x00ff; chksum += addr >> 8; chksum = (chksum ^ 0xff) + 0x01; i += snprintf(&buf[i], _BUFSIZ - i, "%02x\n", chksum); if (_BUFSIZ < i) return -ENOSPC; } else i = snprintf(&buf[0], _BUFSIZ, ":00000001ff\n"); j = 0; do { err = write(fd, &buf[j], i - j); if (0 > err) { err = -errno; if (-EINTR == err) { err = 0; continue; } break; } j += err; err = 0; } while (0 == err && j < i); return err; } static int _out_image(const char *image, const unsigned int size, const _mem_width_t mwidth, const char *outfile) { int err; if (NULL != outfile) { err = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (0 > err) err = -errno; } else err = fileno(stdout); if (0 <= err) { const unsigned int offset = _mem_width2byte(mwidth); unsigned short addr; unsigned int i; int fd; fd = err; addr = _start_addr; i = 0; do { char buf[4]; memset(&buf[0], 0x00, offset); memcpy(&buf[0], &image[i], ((size - i) < offset) ? (size - i) : offset); err = _ihex_out(fd, addr, &image[i], offset); i += offset; addr += 1; } while (0 == err && i < size); /* finish line */ if (0 == err) err = _ihex_out(fd, 0x00, NULL, 0); if (fd != fileno(stderr)) close(fd); } if (0 != err) fprintf(stderr, "\tERROR! dump image failed\n"); return err; } int main(int argc, char *argv[]) { int err; err = _parse_args(argc, argv); if (0 == err) { unsigned int size; char *img; img = _load_image(_infile, &size, _ascii, _mem_width); if (img) { err = _out_image(img, size, _mem_width, _outfile); free(img); } else err = -EIO; } return err; }
Go to most recent revision | Compare with Previous | Blame | View Log