cornwell@hamlet.uucp (Richard P. Cornwell) (12/14/89)
Hi, I have just finished construction of a 68010 single board computer. The EPROM monitor I choose will read Motorola S-records from the serial port. I was wondering if anybody has a BSD Unix a.out to S-record converter program. I would prefere PD or Free-ware since funds are tight and this is a personal project. Rich ========================================================================== Richard P. Cornwell cornwell@snow-white.ece.syr.edu Syracuse University - ECE Office: (315)443-4233 111 Link Hall Home: (315)451-3838 Syracuse NY 13244-1240 ==========================================================================
mwjester@wsucsa.uucp (12/19/89)
In article <2141@cmx.npac.syr.edu>, cornwell@hamlet.uucp (Richard P. Cornwell) writes: > Hi, I have just finished construction of a 68010 single board computer. > The EPROM monitor I choose will read Motorola S-records from the serial port. > I was wondering if anybody has a BSD Unix a.out to S-record converter program. > I would prefere PD or Free-ware since funds are tight and this is a personal > project. > > Rich > ========================================================================== I'm not sure if it could be converted to do the job for you, but a program was posted to comp.sources.atari.st a while back that builds S-records from TTP executables (an Atari ST binary format). The source can be obtained from the Panarthea archive server (panarthea.ebay.sun.com). Hope it helps! Max
kaul@icarus.eng.ohio-state.edu (Rich Kaul) (12/20/89)
In article <9128@wsucsa.uucp> mwjester@wsucsa.uucp writes: In article <2141@cmx.npac.syr.edu>, cornwell@hamlet.uucp (Richard P. Cornwell) writes: > I was wondering if anybody has a BSD Unix a.out to S-record converter program. > I would prefere PD or Free-ware since funds are tight and this is a personal > project. I'm not sure if it could be converted to do the job for you, but a program was posted to comp.sources.atari.st a while back that builds S-records from TTP executables (an Atari ST binary format). The source can be obtained from the Panarthea archive server (panarthea.ebay.sun.com). As I mentioned to Rich, there is a program to convert BSD Unix a.out to Motorola S-recs, Intel Hex format or Tektronics format. It is easily ported to convert SysV binaries (someone did that the last time I posted the program to this newsgroup). It works well and we have done some projects with a MC68020 based robotics controller hanging off a uVAX using a Sun workstation and this program. The program was posted some time ago to mod.sources and is called tohex (you might find it in the volume 1 archives of comp.sources.misc, also). If you need a copy drop me a line and I'll send it to you -- with sufficient demand I'll post it again. -(another) rich -=- Rich Kaul | "It is dangerous to be sincere unless kaul@icarus.eng.ohio-state.edu | you are also stupid." -Bernard Shaw
kaul@icarus.eng.ohio-state.edu (Rich Kaul) (12/20/89)
In article <KAUL.89Dec19140322@icarus.eng.ohio-state.edu> I write:
[tohex] -- with sufficient demand I'll post it again.
Having gotten nearly a dozen requests already, I just decided to post
the source here. I'd crosspost to alt.sources, but this should be on
archive sites anyway (although comp.sources.misc volume 1 has been
deleted from uunet from what I hear). It's reasonably short.
Remember, I didn't write this, I'm just reposting for all those
interested.
-rich
#!/bin/sh
echo 'Start of Tohex, part 01 of 01:'
echo 'x - tohex.1'
sed 's/^X//' > tohex.1 << '/'
X.TH TOHEX 1L
X.. Copyright 1984, 1987 by Phillip L. Harbison
X.SH NAME
Xtohex - convert UNIX a.out files to readable hex formats.
X.SH SYNOPSIS
X.bo
Xtohex
X{ -i | -s | -t } [-ln] [+n] file
X.SH DESCRIPTION
X.ad
X.ul
XTohex
Xreads a file in UNIX a.out format and converts
Xto one of several hex-ascii formats.
XOutput is directed to the standard output.
XThe
X.ul
X-s
Xoption specifies Motorola S-record format.
XThe
X.ul
X-i
Xoption specifies Intel hex format.
XThe
X.ul
X-t
Xoption specifies Tektronix hex (tekhex) format.
XA valid hex format and input filename
Xmust be specified on the command line.
X.LP
XA record length may be specified using the
X.ul
X-ln
Xoption,
Xwhere n is the record length (decimal).
XThe default record length is 32 byte-pairs.
XThe maximum record length is 251 byte-pairs
Xfor S-record format,
Xand 255 byte-pairs for Intel-hex and Tekhex format.
X.LP
XTohex will derive the starting address offset
Xfrom the header information in the a.out file.
XA starting address offset may also
Xbe provided using the
X.ul
X+n
Xoption.
XThe offset n (hexadecimal) will be used
Xinstead of the value derived from the a.out header.
XSpecifying an offset is usually unnecessary
Xfor object files generated by the UNIX loader.
X.SH EXAMPLES
XThe first example shows the file
X.ul
Xnewprog
Xbeing converted to Intel-hex records
Xwith a starting address offset of A000 (hex)
Xand written to
X.ul
Xnewprog.hex.
XThe second example shows the file
X.ul
Xnewprog
Xbeing converted to S-records
Xwith a length of 64 byte-pairs,
Xthe output being redirected to
X.ul
Xnewprog.hex.
X.sp 1
X.nf
X tohex -i +0A000 newprog > newprog.hex
X tohex -s -l64 newprog > newprog.hex
X.fi
X.SH DIAGNOSTICS
X.ul
XTohex
Xwill complain if it cannot find a valid format
Xspecifier and input filename on the command line,
Xif the record length exceeds the maximum record
Xlength for the specified format,
Xor if the input file is not stripped
Xof symbol table information.
XMessages should be self-explaining.
X.SH NOTES
XThe magic number is defined as FMAGIC in the
Xa.out.h file on the author's system,
Xand may not be correct for other systems.
XPure executable a.out files are not supported,
Xsince initialized data is assumed to follow
Xdirectly after text.
XThe S-record format supported is the S2/S8 record,
Xproviding 24-bit addressing.
XThe termination (S8) record will contain the starting address.
XThe Intel-hex format only supports 16-bit addressing.
X.SH FILES
X/usr/include/a.out.h
X.SH "SEE ALSO"
Xa.out(5)
X.SH AUTHOR
XPhil Harbison
/
echo 'x - tohex.c'
sed 's/^X//' > tohex.c << '/'
X/*
X * Tohex is a utility for converting UNIX a.out files into various
X * readable hex formats suitable for downloading or inter-system
X * file transfer. Motorola S-records, Tek-hex, and Intel Hex are
X * currently supported. Other formats can be added easily by
X * adding a formatter module and modifying getargs. Toshex,
X * toihex, and totekhex are the current formatter modules. Tohex
X * does not support System V COFF object files.
X *
X * (c) Copyright 1984, 1987 by Phillip L. Harbison
X *
X * Permission is granted to use, reproduce and distribute this pro-
X * gram by any means, as long as no fee is charged, and provided
X * this notice is always included in any copies.
X *
X * The author hereby dislaims any and all guarantees and
X * warranties, both expressed and implied; and no fitness for any
X * purpose whatsoever is claimed or implied. The author will not
X * be responsible for any damages resulting from the use of this
X * software. Tohex is provided as is, with no promise of support,
X * but I will try to respond to polite bug reports or suggestions
X * for improvements that are forwarded to me via any of the
X * following means.
X *
X * Live: Phil Harbison
X * Mail: 3409 Grassfort Drive, Huntsville, AL 35805-5421
X * UUCP: uunet!madhat!alvitar or alvitar@madhat.uu.net
X * BELL: 205-881-4317, 205-535-2500
X *
X */
X
X#include <stdio.h>
X#include <a.out.h>
X
X#define MAXSIZE 256
X#define NULL 0
X#define TRUE 1
X#define FALSE 0
X#define INTEL 'i'
X#define LENGTH 'l'
X#define MOT 's'
X#define TEKHEX 't'
X
Xchar digits[]="0123456789ABCDEF"; /* for use in output conversion */
Xchar record[MAXSIZE+1]; /* where we put binary input data */
Xint (*hexout)(); /* pointer to conversion function */
Xint offset; /* starting address */
Xint oflag; /* starting address specified as arg */
Xint recsize; /* maximum data bytes/output record */
Xint chksum; /* output record checksum */
Xint toshex(), toihex(), totekhex(); /* conversion functions */
Xstruct bhdr header; /* where we put the a.out header */
XFILE *infile; /* input file descriptor */
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X int addr, maxaddr, count;
X
X /* process the command line arguments */
X if ( !getargs(argc, argv) ) {
X usage();
X exit(1);
X }
X
X /* read the a.out file header */
X if ( !fread(&header, sizeof (struct bhdr), 1, infile) ) {
X fprintf(stderr,"tohex: unable to read file header\n");
X }
X if ( header.fmagic != FMAGIC ) {
X fprintf(stderr,"tohex: not an a.out file\n");
X exit(1);
X }
X if ( header.rtsize || header.rdsize ) {
X fprintf(stderr, "tohex: input file not stripped\n");
X exit(1);
X }
X
X /* print interesting trivia about the file */
X fprintf(stderr, "entry point: %08X\n", header.entry);
X fprintf(stderr, "text size: %06X (%d)\n", header.tsize, header.tsize);
X fprintf(stderr, "data size: %06X (%d)\n", header.dsize, header.dsize);
X
X /*
X * if no starting address was specified use the entry
X * point specified in the header. This is usually
X * appropriate for a.out files.
X */
X if ( !oflag )
X offset = header.entry;
X
X /* calculate size of input */
X maxaddr = header.tsize + header.dsize;
X
X /* loop until out of input */
X for ( addr= 0; addr <= maxaddr; ) {
X /*
X * try to read count bytes from infile into record
X * where count is the lesser of recsize or the number
X * of bytes remaining in the object image.
X */
X count = ((addr + recsize) <= maxaddr) ?
X recsize : (maxaddr - addr);
X count = fread(record,1,count,infile);
X /* are we at EOF ? */
X if ( !count ) {
X break;
X }
X /*
X * convert record from binary to hex format. hexout
X * points to the specified conversion function.
X */
X (*hexout)(count, addr, record);
X addr += count;
X }
X /*
X * force the termination record by
X * requesting a zero-length packet.
X */
X (*hexout)(0,0,record);
X fclose(infile);
X}
X
X/*
X * getargs processes the command line arguments. It expects
X * to see hex output type an input filename, and (optionally)
X * a starting address offset in any order.
X */
Xgetargs(argc, argv)
Xint argc;
Xchar *argv[];
X{
X int index, state, maxsize, tmp;
X
X state = TRUE;
X oflag = FALSE;
X hexout = NULL;
X infile = (FILE *) NULL;
X
X /* default record size is 32 */
X recsize = 32;
X
X /* process each argument */
X for ( index= 1; index < argc; index++ ) {
X /* see if its a flag */
X if ( *argv[index] == '-' ) {
X /* must be a hex output type */
X switch ( *(argv[index] + 1) ) {
X case MOT :
X /* motorola S-records */
X hexout = toshex;
X maxsize = 251;
X break;
X case INTEL :
X hexout = toihex;
X maxsize = 255;
X break;
X case TEKHEX :
X hexout = totekhex;
X maxsize = 255;
X break;
X case LENGTH :
X if ( sscanf(argv[index]+2, "%d", &tmp) == 1 ) {
X recsize = tmp;
X }
X else {
X badarg(argv[index]);
X state = FALSE;
X }
X break;
X default :
X badarg(argv[index]);
X state = FALSE;
X }
X }
X /* is it an offset? */
X else if ( *argv[index] == '+' ) {
X /* yes, must be hexadecimal */
X if ( sscanf(argv[index]+1, "%x", &offset) == 1 ) {
X oflag = TRUE;
X }
X else {
X badarg(argv[index]);
X state = FALSE;
X }
X }
X /* else it must be a filename */
X else if ( (infile = fopen(argv[index], "r")) == NULL) {
X fprintf(stderr, "unable to open %s\n", argv[index]);
X }
X }
X /* was a format specified? */
X if ( hexout ) {
X /* does recsize exceed maxsize? */
X if ( recsize > maxsize ) {
X fprintf(stderr,"tohex: record size too large\n");
X state = FALSE;
X }
X }
X else {
X fprintf(stderr,"tohex: format not specified\n");
X state = FALSE;
X }
X /* do we have an input file? */
X if ( !infile ) {
X fprintf(stderr,"tohex: no input file\n");
X state = FALSE;
X }
X return ( state );
X}
X
X/*
X * toshex performs the binary to Motorola S-record con-
X * version function. The argument "dptr" points to a
X * string of bytes to be converted. "count" specifies
X * the size of the string, while "addr" specifies the
X * starting address for this block of output. Only S2
X * and S8 records are supported (24-bit addresses).
X */
Xtoshex(count, addr, dptr)
Xint count, addr;
Xchar *dptr;
X{
X /* adjust address for starting offset */
X addr += offset;
X /* and mask off all but 24 bits */
X addr &= 0xFFFFFF;
X /* no more bytes ? */
X if ( !count ) {
X /* build a termination (S8) record */
X sheader('8',0,offset);
X }
X else {
X /* build a data (S2) record */
X sheader('2',count,addr);
X /* output data */
X for ( ; count-- ; ) {
X hexpair(*dptr++);
X }
X }
X /* output chksum, Motorola uses 1s complement */
X hexpair(~chksum);
X putchar('\n');
X}
X
X/*
X * sheader: called by toshex to generate the header
X * of an s-record. Type is either 2 or 8.
X */
Xsheader(type,count,addr)
Xchar type;
Xint count, addr;
X{
X putchar('S');
X putchar(type);
X chksum = 0;
X
X /* output record length */
X hexpair(count + 4);
X
X /* output address */
X hexpair(addr >> 16);
X hexpair(addr >> 8);
X hexpair(addr);
X}
X
X/*
X * toihex performs the binary to Intel-hex conversion
X * function. The argument "dptr" points to a string of
X * bytes to be converted. "count" specifies the size
X * of the string, while "addr" specifies the starting
X * address for this block of output.
X */
Xtoihex(count, addr, dptr)
Xint count, addr;
Xchar *dptr;
X{
X /* no more data? */
X if ( !count ) {
X /* output termination packet */
X printf(":0000000000\n");
X }
X else {
X /* Start of header character */
X putchar(':');
X /* record length */
X chksum= 0;
X hexpair(count);
X /* address */
X hexpair(addr >> 8);
X hexpair(addr);
X /* record type, always 0 */
X hexpair(0);
X /* data */
X for ( ; count--; ) {
X hexpair(*dptr++);
X }
X /* checksum, intel uses 2s complement */
X hexpair(-chksum);
X putchar('\n');
X }
X}
X
X/*
X * totekhex performs the binary to Tek-hex conversion
X * function. The argument "dptr" points to a string of
X * bytes to be converted. "count" specifies the size
X * of the string, while "addr" specifies the starting
X * address for this block of output.
X */
Xtotekhex(count, addr, dptr)
Xint count, addr;
Xchar *dptr;
X{
X int index;
X
X /* no more data? */
X if ( !count ) {
X /* output termination packet */
X printf("/00000000\n");
X }
X else {
X chksum = 0;
X /* Start of header character */
X putchar('/');
X /* address */
X tekpair(addr >> 8);
X tekpair(addr);
X tekpair(count);
X /* header checksum */
X tekpair(chksum);
X chksum = 0;
X /* data */
X for ( ; count-- ; ) {
X tekpair(*dptr++);
X }
X /* data checksum */
X tekpair(chksum);
X putchar('\n');
X }
X}
X
X/*
X * hexpair outputs the two character hex-ascii equivalent
X * of the least significant eight bits of its argument.
X * It also performs chksum accumulation. This is a common
X * support routine for the toshex and toihex functions.
X */
Xhexpair(arg)
Xint arg;
X{
X putchar(digits[(arg >> 4) & 0x0F]);
X putchar(digits[arg & 0x0F]);
X chksum += arg;
X}
X
X/*
X * tekpair: called by totekhex to convert a byte to a
X * hex-ascii pair. Tekhex computes the checksum using
X * nibbles rather than bytes.
X */
Xtekpair(arg)
Xint arg;
X{
X int lsn, msn;
X
X msn = (arg >> 4) & 0x0F;
X lsn = arg & 0x0F;
X putchar(digits[msn]);
X putchar(digits[lsn]);
X chksum = chksum + lsn + msn;
X}
X
X/*
X * usage prints the usage message, a standard part
X * of most error messages.
X */
Xusage()
X{
X fprintf(stderr,
X "usage: tohex -{s,i} [-l<length>] [+<offset>] filename\n");
X}
X
X/*
X * badarg prints the rejected argument pointed
X * to by str, prepended by an error message.
X */
Xbadarg(str)
X char *str;
X{
X fprintf(stderr,"tohex: invalid argument %s\n", str);
X}
/
echo 'x - makefile'
sed 's/^X//' > makefile << '/'
XSHELL= /bin/sh
XBIN= /usr/lbin
XCC= /usr/ghs/compiler/gcc
X
Xinstall: tohex
X install -f $(BIN) tohex
X
Xtohex: tohex.o
X $(CC) -o tohex tohex.o
X
Xclean:
X rm -f tohex.o tohex
/
echo 'Part 01 of Tohex complete.'
exit
greg@uop.EDU (Greg Onufer) (12/22/89)
Tohex, as posted, would not compile under SunOS 4.0. Here are the changes I made to get it to compile (I tested it a little and I am fairly sure it still works correctly, but I make no guarantees). *** tohex.c Thu Dec 21 16:22:25 1989 --- tohex.c.new Thu Dec 21 16:18:20 1989 *************** *** 49,55 **** int recsize; /* maximum data bytes/output record */ int chksum; /* output record checksum */ int toshex(), toihex(), totekhex(); /* conversion functions */ ! struct bhdr header; /* where we put the a.out header */ FILE *infile; /* input file descriptor */ main(argc, argv) --- 49,55 ---- int recsize; /* maximum data bytes/output record */ int chksum; /* output record checksum */ int toshex(), toihex(), totekhex(); /* conversion functions */ ! struct exec header; /* where we put the a.out header */ FILE *infile; /* input file descriptor */ main(argc, argv) *************** *** 65,86 **** } /* read the a.out file header */ ! if ( !fread(&header, sizeof (struct bhdr), 1, infile) ) { fprintf(stderr,"tohex: unable to read file header\n"); } ! if ( header.fmagic != FMAGIC ) { fprintf(stderr,"tohex: not an a.out file\n"); exit(1); } ! if ( header.rtsize || header.rdsize ) { fprintf(stderr, "tohex: input file not stripped\n"); exit(1); } /* print interesting trivia about the file */ ! fprintf(stderr, "entry point: %08X\n", header.entry); ! fprintf(stderr, "text size: %06X (%d)\n", header.tsize, header.tsize); ! fprintf(stderr, "data size: %06X (%d)\n", header.dsize, header.dsize); /* * if no starting address was specified use the entry --- 65,88 ---- } /* read the a.out file header */ ! if ( !fread(&header, sizeof (struct exec), 1, infile) ) { fprintf(stderr,"tohex: unable to read file header\n"); } ! if ( N_BADMAG(header) ) { fprintf(stderr,"tohex: not an a.out file\n"); exit(1); } ! if ( header.a_trsize || header.a_drsize ) { fprintf(stderr, "tohex: input file not stripped\n"); exit(1); } /* print interesting trivia about the file */ ! fprintf(stderr, "entry point: %08X\n", header.a_entry); ! fprintf(stderr, "text size: %06X (%d)\n", header.a_text, ! header.a_text); ! fprintf(stderr, "data size: %06X (%d)\n", header.a_data, ! header.a_data); /* * if no starting address was specified use the entry *************** *** 88,97 **** * appropriate for a.out files. */ if ( !oflag ) ! offset = header.entry; /* calculate size of input */ ! maxaddr = header.tsize + header.dsize; /* loop until out of input */ for ( addr= 0; addr <= maxaddr; ) { --- 90,99 ---- * appropriate for a.out files. */ if ( !oflag ) ! offset = header.a_entry; /* calculate size of input */ ! maxaddr = header.a_text + header.a_data; /* loop until out of input */ for ( addr= 0; addr <= maxaddr; ) { Cheers!greg