koreth@panarthea.ebay.sun.com (Steven Grimm) (10/02/89)
Submitted-by: johan@motstk.se (Johan Hagman) Posting-number: Volume 2, Issue 83 Archive-name: builds09 These are the source files of builds 0.9, a program which creates Motorola S-records from Atari ST binary (.ttp) files. --- Johan Hagman Motorola Computer Systems, Dalv. 2, 17136 Solna, Sweden Phone: +46 8 7348800 uucp: ..uunet!mcvax!sunic!motstk!johan Fax: +46 8 7354473 email: johan@motstk.{UUCP,SE} #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # README # builds.c # makefile # This archive created: Thu Sep 28 21:49:10 1989 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'README'" '(951 characters)' if test -f 'README' then echo shar: "will not over-write existing file 'README'" else sed 's/^X//' << \SHAR_EOF > 'README' X X builds version 0.9 17-Sep-89 X ----------------------------- X XThis program was developed to allow downloading code/data to a target X68000 system via the serial port using the Motorola S-record format. X XBuilds produces S2-record files from ST .ttp executables. (There are Xthree different S-record formats; S1, S2 and S3, for 16-, 24- and 32-bit Xaddresses, respectively.) X XUsage: builds [-address] [-v] file X X "address" is the (24-bit) load- and execution address, and X should be entered in hex format WITHOUT a leading "0x". The X code is relocated in the same way as the ST does when loading X a program. "address" defaults to zero. X X "v" displays the program version. X XThe S-record file is written to stdout to allow redirection to a file Xor the serial port using your favourite shell. X XCompiled with Sozobon C. X X Johan Hagman Motorola Computer Systems, Stockholm, Sweden X e-mail: johan@motstk.{uucp,se} X uucp: ..uunet!mcvax!sunic!motstk!johan SHAR_EOF if test 951 -ne "`wc -c < 'README'`" then echo shar: "error transmitting 'README'" '(should have been 951 characters)' fi fi echo shar: "extracting 'builds.c'" '(6157 characters)' if test -f 'builds.c' then echo shar: "will not over-write existing file 'builds.c'" else sed 's/^X//' << \SHAR_EOF > 'builds.c' X/* X * @(#)builds.c 0.9 17-Sep-89 X * X * Builds Motorola S-records from an Atari ST object file. X * X * Copyright (c) 1989 Johan Hagman. X * X * This program may be freely distributed, provided it retains X * my copyright notice. It is provided as is, with no warranty X * expressed or implied. X * X * History: X * X * Ver Date Author Comments X * --- ------- ------ ------------------- X * 0.9 22-Aug-88 J.H Initial coding. X * 17-Sep-89 Last edit. X */ X X#include <stdio.h> X#include <ctype.h> X X#define VERS "0.9 17-Sep-89" X#define OBJMAGIC 0x601A /* magic number of ST object file */ X#define SRECL 28 /* # of data bytes in each S-record */ X Xtypedef unsigned char BOOLEAN; X Xtypedef struct { X WORD magic; X LONG tsiz; /* text length */ X LONG dsiz; /* data length */ X LONG bsiz; /* bss length */ X LONG unused[3]; X WORD unusedToo; X} HEADER; X Xstatic char *myName; Xstatic LONG relocAddr = 0L; /* relocation address */ Xstatic HEADER hdr; X X X/*---------------------------------------- X * X * readHeader -- open object file, read X * and check header. X */ Xstatic FILE *readHeader(fname) Xchar *fname; X{ X FILE *fd; X X if ((fd = fopen(fname, "rb")) == NULL) { X fprintf(stderr, "%s: cannot open \"%s\"\n", myName, fname); X exit(1); X } X if (fread(&hdr, sizeof(HEADER), 1, fd) != 1) X perror("fread"); X if (hdr.magic != OBJMAGIC) { X fprintf(stderr, "%s: \"%s\" is not an object file\n", X myName, fname); X exit(1); X } X return(fd); X} X X X/*---------------------------------------- X * X * getEntry -- returns relocation offset in *val, X * advancing *rltpos to next entry. Returns -1L in X * *val at end of table. X */ Xstatic void getEntry(fd, rltpos, val) XFILE *fd; XLONG *rltpos; XLONG *val; X{ X static BOOLEAN first = TRUE; X register int c; X LONG streamOffset; X X if (fgetpos(fd, &streamOffset) != 0) /* store current offset */ X perror("fgetpos"); X X if (fseek(fd, *rltpos, 0) != 0) /* seek to relocation table */ X c = 0; /* no table: PIC */ X else X do { X if ((c = fgetc(fd)) == EOF) { X c = 0; /* end of table */ X break; X } X (*rltpos)++; /* advance to next entry */ X X if (first) { /* first entry is special */ X first = FALSE; X *val += (LONG)c << 8; X c = 1; /* loop once more */ X } else X if (c == 1) X *val += 0xfeL; /* offset exceeds 0xff */ X X } while (c == 1); X X if (fsetpos(fd, &streamOffset) != 0) /* return to where we were */ X perror("fsetpos"); X X if (c == 0) X *val = -1L; /* end of table */ X else X *val += (LONG)c; /* accumulated rel. addr */ X} X X X/*---------------------------------------- X * X * putSrec -- outputs a data record (S1 or S2). X */ Xstatic void putSrec(type, addr, len, data) Xchar type; XLONG addr; Xint len; XBYTE data[]; X{ X register BYTE cs; /* checksum */ X register int i; X X /* Calculate record length */ X cs = len + ((addr == -1) ? 1 : (type == '1' ? 3 : 4)); X printf("S%c%02X", type, cs); X X if (addr != -1) /* suppress addr if -1 */ X switch(type) { X case '1': /* S1 record */ X printf("%04lX", addr); X cs += (addr >> 8) + addr; X break; X case '2': /* S2 record */ X printf("%06lX", addr); X cs += (addr >> 16) + (addr >> 8) + addr; X /* S3 records not applicable for the 68k */ X } X X for (i = 0; i < len; i++) { X cs += data[i]; X printf("%02X", data[i] & 0xff); /* binary data */ X } X printf("%02X\n", ~cs & 0xff); /* checksum */ X} X X X/*---------------------------------------- X * X * buildSrec -- creates the S-record file, adjusting absolute X * (32-bit) addresses according to user's relocation offset. X */ Xstatic void buildSrec(fname) Xchar *fname; X{ X BYTE dlist[SRECL]; X int input, /* must keep track of two input */ X nextInput; /* values at each iteration */ X LONG rlval = 0L, X rltpos, /* relocation table position in file */ X bytesToDo, /* # bytes in text + data section */ X SrecAddr, X curOffset; /* used for relocation */ X register int col; /* "column" value for S-record data */ X register LONG idx; /* index into text/data sections */ X FILE *fd; X X fd = readHeader(fname); /* get object file header */ X X /* calculate relocation table offset */ X rltpos = sizeof(HEADER) + hdr.tsiz + hdr.dsiz + 2; X X getEntry(fd, &rltpos, &rlval); /* read relocation entry */ X X if (fseek(fd, (long)sizeof(HEADER), 0) != 0) /* position at text */ X perror("fseek"); X X putSrec('0', -1L, strlen(fname), fname); /* the header record */ X X bytesToDo = hdr.tsiz + hdr.dsiz; X SrecAddr = relocAddr; X X if ((input = fgetc(fd)) == EOF) /* read first byte in file */ X perror("fgetc"); X X col = 0; X for (idx = curOffset = 0L; idx < bytesToDo; idx++) { X X if ((nextInput = fgetc(fd)) == EOF) /* get byte from file */ X perror("fgetc"); X X if (idx == rlval) { X X /* Oops! The next four bytes must be relocated */ X X getEntry(fd, &rltpos, &rlval); /* find next relocation entry */ X X curOffset = relocAddr; /* define relocation offset */ X } X X dlist[col] = (BYTE)(input + (curOffset >> 24)); X X if (curOffset != 0L) X /* we're currently relocating, now check for overflow */ X if (nextInput + (BYTE)(curOffset >> 16) > 0xff) X dlist[col]++; /* overflow */ X X input = nextInput; /* advance one byte */ X curOffset <<= 8; /* shift in next less signif. byte */ X X if (++col == SRECL || idx == bytesToDo - 1) { X X /* End of line or end of data - print the record */ X X putSrec('2', SrecAddr, col, dlist); X col = 0; /* begin new record */ X SrecAddr += SRECL; /* with a new address */ X } X } X putSrec('9', -1L, 0); X fclose(fd); X} X X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X char *opt; /* arg. ptr */ X LONG strtoul(); X X myName = "builds"; X X while (--argc > 0 && (*++argv)[0] == '-') { X opt = &argv[0][1]; X switch (*opt) { X case 'v': X printf("%s v%s\n", myName, VERS); X exit(0); X default: X if (isxdigit(*opt)) { /* hexadecimal? */ X relocAddr = strtoul(opt, NULL, 16); X break; X } X fprintf(stderr, "%s: illegal option \"%c\"\n", myName, *opt); Xusage: fprintf(stderr, "usage: %s [-hexOffset] [-v] objFile\n", myName); X exit(0); X } X } X X if (argc == 0) /* must have a filename */ X goto usage; X X buildSrec(argv[0]); X} SHAR_EOF if test 6157 -ne "`wc -c < 'builds.c'`" then echo shar: "error transmitting 'builds.c'" '(should have been 6157 characters)' fi fi echo shar: "extracting 'makefile'" '(126 characters)' if test -f 'makefile' then echo shar: "will not over-write existing file 'makefile'" else sed 's/^X//' << \SHAR_EOF > 'makefile' X# X# A makefile for builds X# XCCOPT = -O XFILES = builds.c XBIN = builds.ttp X X$(BIN): $(FILES) X cc $(CCOPT) -o $(BIN) $(FILES) SHAR_EOF if test 126 -ne "`wc -c < 'makefile'`" then echo shar: "error transmitting 'makefile'" '(should have been 126 characters)' fi fi exit 0 # End of shell archive