Xinu7/src/cmd/download/OLD/upload.c
/*----------------------------------------------------------------------*/
/* */
/* upload +++ copy LSI-11 memory to ./core11 +++ */
/* */
/* This program takes LSI-11 memory and places it into a file named */
/* core11 on the host system */
/* */
/* Configuration - */
/* VAX tty line connected to LSI 11 ODT (console) port */
/* */
/* Usage: */
/* upload [filename] [-lx] [-o filename] */
/* */
/* Authors: */
/* R. Brown & C. Kent */
/* Purdue University/CS Deptartment */
/* September, 1981 */
/* mods by Comer, 11/81-11/83 */
/* */
/*----------------------------------------------------------------------*/
#include <stdio.h>
#include <sgtty.h>
#include <signal.h>
#include <errno.h>
#include "/usr/Xinu/include/core11.h"
#include "/usr/Xinu/include/a.out.h"
#include "/usr/Xinu/include/baud.h"
#include "getdev.h"
#define MAXADDR 0157777
#define CSRBASE 0177560
#define LOADSTART 0
typedef unsigned short lsiword;
#ifndef TRUE
#define TRUE 1
#define FALSE 0
typedef int Bool;
#endif
#define EOS ((char)0)
#define SOH '/'
#define ESC '\033'
#define LOADER "/usr/Xinu/lib/ul"
#define MAXPACKSIZE 526
#define STACKLEN 20
#define settimer(t,m) msgval = m; alarm(t)
#define canceltimer() alarm(0)
#define unctrl(ch) (_unctrl[ch])
char *_unctrl[] = { /* unctrl codes for ttys */
"^@","^A","^B","^C","^D","^E","^F","^G","^H","^I","^J","^K",
"^L","^M","^N","^O","^P","^Q","^R","^S","^T","^U","^V","^W",
"^X","^Y","^Z","^[","^\\","^]","^~","^_",
" ","!","\"","#","$", "%","&","'","(",")","*","+",",","-",
".","/","0", "1","2", "3","4","5","6","7","8","9",":",";",
"<","=",">", "?","@", "A","B","C","D","E","F","G","H","I",
"J","K","L", "M","N", "O","P","Q","R","S","T","U","V","W",
"X","Y","Z", "[","\\","]","^","_","`","a","b","c","d","e",
"f","g","h", "i","j", "k","l","m","n","o","p","q","r","s",
"t","u","v", "w","x", "y","z","{","|","}","~","^?"
};
struct packet {
lsiword len, base;
lsiword buf[MAXPACKSIZE];
lsiword sum;
};
struct {
char *odtline;
int baudrate;
char *corefile;
char *loader;
int lowaddr;
int highaddr;
Bool verbose;
Bool silent;
Bool noload;
char *outfile;
} A;
char *msgval;
char *Openfiles[20];
struct core11 Corehead;
int Devfd, Corefd;
int Haltedat;
struct sgttyb VAXttyb;
lsiword *Memory;
char *index();
char class[MAXNAMELEN];
int useclass;
int machnum;
char dev[MAXNAMELEN], devname[MAXNAMELEN];
char lockfile[40];
int touch(), getdev();
extern int errno;
int use;
/*----------------------------------------------------------------------
* upload -- upload an LSI 11 memory image
*----------------------------------------------------------------------
*/
main(argc,argv)
int argc;
char *argv[];
{
int alarmhandler(), inthandler();
int ldrfd, bytes;
int base,length,i;
char buf[32];
struct exec bhdr;
short entry;
/*
* set up terminal modes...prepare to reset on interrupt
*/
procargs(argc, argv);
if ((machnum = getdev(useclass,class,machnum,&Devfd,lockfile)) < 0)
exit(1);
if (machnum == 0) {
strcpy(devname, class);
if (! A.silent)
printf("Using %s\n", class);
}
else {
sprintf(devname, DEVNAME, DEVDIR, class);
if (! A.silent)
printf("Using %s #%d\n", class, machnum);
}
Openfiles[Devfd] = sprintf(dev, devname, machnum);
Corefd = creat(A.corefile,0666);
ldrfd = openfile(A.loader,0);
gtty(Devfd,&VAXttyb);
/*
* trap software signals so that lines can be restored to their
* original state and the core file can be written
*/
if ( signal(SIGINT,SIG_IGN) != SIG_IGN )
signal(SIGINT,inthandler);
if ( signal(SIGTERM,SIG_IGN) != SIG_IGN )
signal(SIGTERM,inthandler);
if ( signal(SIGQUIT,SIG_IGN) != SIG_IGN )
signal(SIGQUIT,inthandler);
linemode(Devfd,A.baudrate,RAW); /*|TANDEM*/
signal(SIGALRM, alarmhandler);
/*
* allocate memory array - this written to the core file when the
* program terminates
*/
if (A.verbose)
printf("Alocating %d (0%o) bytes for image\n",MAXADDR+1,
MAXADDR+1);
Memory = (lsiword *)malloc(MAXADDR+1);
for ( i=0 ; i<(MAXADDR+1)/2 ; i++ )
Memory[i] = 0;
Corehead.c_zero1 = 0;
Corehead.c_zero2 = 0;
Corehead.c_zero3 = 0;
Corehead.c_zero4 = 0;
Corehead.c_zero5 = 0;
Corehead.c_magic = COREMAGIC;
message("Getting ODT...",0,0);
getodt(Devfd);
/*
* Get the contents of the registers
*/
message("Getting registers...",0,0);
getregs(Devfd,Corehead.c_regs);
getpsw(Devfd,&Corehead.c_psw);
if (A.verbose)
message("Getting a.out header",0,0);
gethdr(ldrfd,&bhdr);
bytes = bhdr.a_text+bhdr.a_data+STACKLEN;
if (A.verbose)
message("Number of bytes = %d",bytes,0);
if ( !A.noload ) {
message("Deposit boot loader...",0,0);
entry = odtload(ldrfd,&bhdr,0,Memory);
} else {
message("Not loading boot loader...",0,0);
read ( ldrfd, Memory, bytes*sizeof(lsiword) );
}
/*
* Set up arguments to upl and start it running...
*/
if (A.verbose)
message("Getting ODT again...",0,0);
getodt(Devfd);
message("Starting load of 0%o-0%o...",A.lowaddr,A.highaddr);
base = (A.lowaddr < bytes ? bytes : A.lowaddr);
length = (A.highaddr-base + 1)/2;
if (A.verbose)
message("Setting argument registers",0,0);
setreg(Devfd,0,base);
setreg(Devfd,1,length);
setreg(Devfd,4,CSRBASE);
setreg(Devfd,6,base);
if (A.verbose)
message("Starting LSI 11 execution",0,0);
sendodt(Devfd,"P",TRUE);
fastread(Devfd,Memory);
message("Writing core file...",0,0);
write(Corefd,&Corehead,sizeof Corehead);
write(Corefd,Memory,A.highaddr+1);
touch(lockfile);
message("Done",0,0);
}
/*
*===================================================
* procargs - process argument in global structure
*===================================================
*
* This procedure continas the logic for converting the UNIX argument
* list into global variables
*/
procargs(argc, argv)
int argc;
char *argv[];
{
int arg, i, unswitched, more;
int afd;
struct exec ahdr;
char *swptr;
/*
* assign default values
*/
A.lowaddr = 0;
A.highaddr = MAXADDR;
A.corefile = "core11";
A.odtline = NULL;
A.baudrate = B9600;
strcpy(class, "LSI");
useclass = FALSE;
machnum = MYDEV;
A.loader = LOADER;
A.verbose = FALSE;
A.silent = FALSE;
A.noload = FALSE;
unswitched = 0;
for ( arg=1 ; arg<argc ; arg++ ) {
if ( argv[arg][0] == '-' ) {
more = TRUE;
swptr = &argv[arg][1];
while ( more && *swptr!='\0' ) {
switch ( *swptr ) {
case 'o':
if ( arg+1 >= argc )
usagexit(argv[0]);
A.corefile = argv[arg++];
more = FALSE;
break;
case 'v':
A.verbose = TRUE;
break;
case 's':
A.silent = TRUE;
break;
case 'n':
A.noload = TRUE;
break;
case 'a':
afd = openfile(argv[arg++],0);
if ( arg+1 >= argc )
usagexit(argv[0]);
gethdr(afd,&ahdr);
A.lowaddr = ahdr.a_text;
A.highaddr = ahdr.a_text+ahdr.a_data+
ahdr.a_bss;
more = FALSE;
break;
case 'c':
argv[arg] += 2;
strcpy(class, argv[arg]);
useclass = TRUE;
more = FALSE;
break;
case 'l':
argv[arg] += 2;
if ( (machnum = atoi(argv[arg])) < 0)
usagexit(argv[0]);
more = FALSE;
break;
case 't':
argv[arg] += 2;
strcpy(class, argv[arg]);
machnum = TTYNAME;
more = FALSE;
break;
case 'B':
if (*(argv[arg]+=2) == '\0') {
A.baudrate = NOBAUD;
break;
}
for (i = 0; i < NBAUD; ++i)
if (strcmp(baudlist[i].name,
argv[arg]) == 0)
break;
if (i < NBAUD) {
printf("baud = %s (%d)\n", baudlist[i].name, baudlist[i].rate);
A.baudrate = baudlist[i].rate;
}
else {
fprintf(stderr,
"Unknown baud rate: %s\n",
argv[arg]);
exit(1);
}
more = FALSE;
break;
default:
usagexit(argv[0]);
}
swptr++;
}
} else { /* there's no dash in front */
switch ( unswitched++ ) {
case 0:
A.highaddr = atoi(argv[arg]);
message("highaddr=%o",A.highaddr,0);
break;
case 1:
A.lowaddr = A.highaddr;
A.highaddr = atoi(argv[arg]);
message("lowaddr=%o",A.lowaddr,0);
message("highaddr=%o",A.highaddr,0);
break;
default:
usagexit(argv[0]);
}
}
}
}
usagexit(pgm)
char *pgm;
{
fprintf(stderr,"usage: %s [-options] [[lowaddr] highaddr]\n",pgm);
exit(1);
}
/*
*==========================================================
* openfile - try to open file, exit with message if error
*==========================================================
*/
openfile(name,mode)
char *name;
int mode;
{
int fd;
settimer(10, "open timed out");
if ((fd=open(name,mode)) < 0 ) {
perror(name);
exit(1);
}
canceltimer();
Openfiles[fd] = name;
return(fd);
}
/*
*=========================================
* alarmhandler - return from alarm calls
*=========================================
*/
alarmhandler()
{
signal(SIGALRM, alarmhandler);
fprintf(stdout, "%s\n", msgval);
exit(1);
}
/*
*=====================================
* inthandler -- interrupt processing
*=====================================
*/
inthandler()
{
write(Corefd,&Corehead,sizeof Corehead);
write(Corefd,Memory,A.highaddr+1);
touch(lockfile);
callexit(2);
}
/*
*=======================================
* callexit - restore ttymodes and exit
*=======================================
*/
callexit(ret)
int ret;
{
/* stty(Devfd,&VAXttyb); */
exit(ret);
}
/*
*==========================================
* odtload - load bootstrap loader via ODT
*==========================================
* input state: after ODT prompt
* output state: same
*
* fdin - a.out file to download
* hdr - a.out header for file to load
* loc - location to begin loading (overrides default 0)
* outaddr - ptr to int array to hold current contents, or NULL
*/
odtload(fdin, hdr, loc, outaddr)
int fdin;
int loc;
lsiword *outaddr;
struct exec *hdr;
{
int addr, lsival;
int i, length;
lsiword word;
char buf[32], filebuf[BUFSIZ],c,*val;
FILE *infile;
infile = fdopen(dup(fdin),"r");
fseek(infile,sizeof *hdr,0);
setbuf(stdout,NULL);
setbuf(infile,filebuf);
length = hdr->a_text+hdr->a_data+STACKLEN;
addr = LOADSTART;
do {
fread(&word, sizeof word, 1, infile);
if ( addr == LOADSTART ) {
sprintf(buf,"%o/",addr+loc);
sendodt(Devfd,buf,TRUE);
readuntil(Devfd, " ?", buf, 7);
val = buf;
} else {
sendodt(Devfd, "\n",TRUE);
readuntil(Devfd, " ?", buf, 7);
val = index(buf,'/')+1;
}
if ( outaddr != NULL ) {
sscanf(val,"%o ",&lsival);
outaddr[(addr+loc)/2] = lsival & 0xffff;
}
sprintf(buf, "%o", word & 0xffff);
sendodt(Devfd, buf,TRUE);
if ( !A.silent && !A.verbose )
displayval(addr);
addr += sizeof (lsiword);
} while ( word != 0177777 );
if ( !A.silent && !A.verbose )
printf("\r");
sendodt(Devfd,"\r",TRUE);
readuntil(Devfd, "@", buf, 5);
/*
* now, run this half to load the other half faster
*/
fseek(infile,sizeof(struct exec),0);
setreg(Devfd,1,length);
setreg(Devfd,-1,0340);
setreg(Devfd,7,LOADSTART);
sendodt(Devfd,"P",FALSE);
sleep(1);
for ( i=0 ; i<length ; i++ ){
c = getc(infile);
if (A.verbose){
fprintf(stdout,"AT: %06o ", i&0xffff);
fprintf(stdout,"OUT: %03o ",c&0xff);
}
write(Devfd,&c,1);
read(Devfd,&c,1);
if (A.verbose) fprintf(stdout,"IN: %03o\n",c&0xff);
if ( i>=addr && outaddr != NULL )
*(((char *)outaddr)+i) = c;
}
readuntil(Devfd,"@", buf, 8);
return(addr);
}
/*
*===============================================
* getpsw - get the current contents of the PSW
*===============================================
*/
getpsw(fd,psw)
int fd;
short *psw;
{
char buf[60];
char *reply;
sendodt(Devfd,"$S/",TRUE);
readuntil(Devfd," ?", buf, 5);
reply = index(buf,'/');
sscanf( ((0==(int)reply) ? buf : reply+1),"%o ",psw);
sendodt(Devfd,"\r",TRUE);
readuntil(Devfd,"@",buf,5);
}
/*
*==========================================
* getregs - get contents of the registers
*==========================================
*/
getregs(fd,regs)
int fd;
short *regs;
{
int r;
int lsival;
char buf[32], *val;
for ( r=0 ; r<REGISTERS ; r++ ) {
if ( r==0 ) {
sprintf(buf,"R%d/",r);
sendodt(Devfd,buf,TRUE);
readuntil(Devfd, " ?", buf, 7);
val = buf;
} else {
sendodt(Devfd, "\n",TRUE);
readuntil(Devfd, " ?", buf, 7);
val = index(buf,'/')+1;
}
sscanf(val,"%o ",&lsival);
regs[r] = lsival & 0xffff;
if ( !A.silent && !A.verbose )
displayval(r);
}
if ( !A.silent && !A.verbose )
printf("\r");
sendodt(Devfd,"\r",TRUE);
readuntil(Devfd, "@", buf, 5);
}
/*
*===============================
* getodt - get ODT's attention
*===============================
* Input state - undefined
* Output state - immediately after ODT prompt
*/
getodt(fd)
int fd;
{
char buf[BUFSIZ];
ioctl(fd, TIOCSBRK, NULL);
sleep(2);
ioctl(fd, TIOCCBRK, NULL);
readuntil(fd,"@",buf,5);
sscanf(buf,"%o",&Haltedat);
}
/*
*==================================================
* readuntil - read from line until some character
*==================================================
*/
readuntil ( fd, ch, buf, time )
int fd, time;
char *ch, *buf;
{
settimer(time, "read timed out");
if ( A.verbose )
printf("IN: ");
do {
if ( read(fd, buf, 1) != 1 ) {
perror(Openfiles[fd]);
callexit(1);
}
if (A.verbose )
printf("%s",unctrl(*buf));
} while ( *buf == '\0' || index(ch,*buf++) == NULL );
*buf = EOS;
canceltimer();
if ( A.verbose )
printf("\n");
}
/*
*==============================================
* sendodt - send a message to ODT half duplex
*==============================================
*/
sendodt(fd, msg, wait)
int fd;
char *msg;
Bool wait;
{
char buf[32], *ptr, tmpstr[2];
if ( A.verbose ) {
printf("OUT: ");
for ( ptr=msg ; *ptr!=EOS ; ptr++ ) {
printf("%s",unctrl(*ptr));
}
printf("\n");
}
while (*msg!=EOS) {
write(fd,msg,1);
if ( wait ) {
tmpstr[0] = *msg;
tmpstr[1] = EOS;
readuntil(fd, tmpstr, buf, 5);
}
msg++;
}
}
/*
*==========================================
* setreg - preload a register through ODT
*==========================================
*/
setreg(fd, reg, value)
int fd, reg, value;
{
char buf[32];
if (A.verbose)
message("Setting register %d to 0%o",reg,value&0xffff);
if ( reg >= 0 )
sprintf(buf,"R%d/",reg);
else
sprintf(buf,"$S/");
sendodt(fd,buf,TRUE);
readuntil(fd," ",buf,5);
sprintf(buf,"%o\r",value&0xffff);
sendodt(fd,buf,TRUE);
readuntil(fd,"@",buf,5);
}
/*
*=================================================
* message - conditionally display status message
*=================================================
*/
message(str,arg,arg2)
char *str;
{
if ( !A.silent ) {
printf(str,arg,arg2);
printf("\n");
}
}
/*
*=======================================
* linemode - set up linemode and speed
*=======================================
*/
linemode(fd,speed,mode)
int fd, speed, mode;
{
struct sgttyb tcb;
if ( gtty(fd,&tcb) < 0 ) {
perror(Openfiles[fd]);
callexit(1);
}
if (speed != NOBAUD)
tcb.sg_ispeed = tcb.sg_ospeed = speed;
tcb.sg_flags = mode;
stty(fd,&tcb);
}
/*
*================================
* gethdr - read an a.out header
*================================
*/
gethdr(fd,hdr)
int fd;
struct exec *hdr;
{
if ( read(fd, hdr, sizeof *hdr) != sizeof *hdr) {
fprintf(stderr,"%s: EOF reading a.out header\n",Openfiles[fd]);
callexit(1);
}
if ( hdr->a_magic != A_MAGIC1 ) {
fprintf(stderr,"%s: wrong magic number\n",Openfiles[fd]);
callexit(1);
}
}
/*
*============================================
* displayval - display a number on one line
*============================================
*/
displayval(val)
int val;
{
char buf[32];
sprintf(buf,"%o ",val);
printf("\r%s",buf);
fflush(stdout);
}
/*
*==================================================
* fastread - receive packets from high speed line
*==================================================
*/
fastread(fd,ptr)
int fd;
lsiword *ptr;
{
struct packet packet;
FILE *in;
lsiword sum;
int i;
in = fdopen(fd,"r");
message("Reading LSI 11 memory...",0,0);
do {
do {
getpack(in,&packet);
if ( packet.len <= MAXPACKSIZE ) {
sum = packet.len + packet.base;
for ( i=0 ; i<packet.len ; i++ )
sum += packet.buf[i];
if ( A.verbose )
message("exp./actual sum=0%o/0%o",
sum, packet.sum);
if ( sum == packet.sum )
break;
}
if ( !A.silent )
fprintf(stdout,"NAK\n");
write(fd,"n",1);
} while ( TRUE ) ;
write(fd,"y",1);
for ( i=0 ; i<packet.len ; i++ )
Memory[i+(packet.base/sizeof(lsiword))] = packet.buf[i];
if ( !A.silent )
displayval((int)(packet.base&0xffff));
} while ( packet.len != 0 );
if ( !A.silent ) {
displayval(0);
printf("\r");
}
}
/*
*=======================================
* getpack - read next packet from line
*=======================================
*/
getpack(fd,pptr)
FILE *fd;
struct packet *pptr;
{
char c;
Bool success;
int i;
/*
* wait for start of heading character
*/
success = FALSE;
do {
while ( (c=getc(fd)) != SOH ) ; /* nil */
if (A.verbose)
fprintf(stdout,"SOH\n");
pptr->len = getword(fd);
pptr->base = getword(fd);
if ( A.verbose )
fprintf(stdout,"len, base = %o %o\n",pptr->len,
pptr->base);
if ( pptr->len > MAXPACKSIZE ) {
return;
}
for ( i=0 ; i<pptr->len ; i++ ) {
pptr->buf[i] = getword(fd);
}
pptr->sum = getword(fd);
success = TRUE;
} while ( !success );
}
getword(fd)
FILE *fd;
{
lsiword word;
word = getbyte(fd);
word = word | (getbyte(fd)<<8);
return(word);
}
getbyte(fd)
FILE *fd;
{
char c;
c = getc(fd);
if (A.verbose) fprintf(stdout,"%03o ",c&0xff);
if ( c==ESC ) {
c = getc(fd);
if (A.verbose) fprintf(stdout,"(%03o) ",c&0xff);
}
return(c&0xff);
}