OpenCores
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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.