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