|
|
1.1 root 1: #define M32LD "/bin/32reloc"
2: #define BINARY_LOAD 0
3: #define HEX_LOAD 1
4: int Loadtype = BINARY_LOAD;
5:
6: /*
7: * MAC-32 (down)loader
8: */
9:
10: char Usage[] = "Usage: 32ld [-d] [-p] [-z] objectfile";
11: /* also a [-l] flag, but the user never sees this */
12: char *name;
13:
14: /*
15: * swapw words must be swapped between host and MAC-32
16: * swapb bytes must be swapped between host and MAC-32
17: */
18: #ifdef pdp11
19: #define swapb 1
20: #define swapw 0
21: #endif
22: #ifdef vax
23: #define swapb 1
24: #define swapw 1
25: #endif
26: #ifdef u3b
27: #define swapb 0
28: #define swapw 0
29: #endif
30: #ifdef u3b2
31: #define swapb 0
32: #define swapw 0
33: #endif
34: #ifdef u3b5
35: #define swapb 0
36: #define swapw 0
37: #endif
38: #ifdef mc68000
39: #define swapb 0
40: #define swapw 0
41: #endif
42:
43: #include <sgtty.h>
44: #include "a.out.h"
45: #include "aouthdr.h"
46: #include "filehdr.h"
47: #include "scnhdr.h"
48: #include <stdio.h>
49: #include <errno.h>
50: #include <jioctl.h>
51: #include "proto.h"
52: #include <sys/types.h>
53: #include <sys/stat.h>
54:
55: #define MAXRETRIES 10
56: #define SLEEPTIME 7
57: #define DATASIZE 512
58:
59: #define NSECTS 12
60:
61: #define MPX_VER 0x5620
62: #define FBOMAGIC 0560
63: #define SENDTERMID "\033[c"
64: #define TERM_1_0 "\033[?8;7;1c"
65: #define TERMB_1_0 "\033[?8;7;2c"
66: #define TERM_DMD "\033[?8;"
67: #define TERMIDSIZE 9
68: #define STR_EQUAL 0
69:
70: struct filehdr fileheader;
71: struct aouthdr aoutheader;
72: struct scnhdr secthdrs[NSECTS];
73: char *errname; /* name of error file for m32ld */
74:
75: #if vax | u3b | u3b2 | mc68000
76: struct sgttyb ttysave, /* save the state of tty */
77: ttyraw;
78: struct ttydevb ttydsave, ttydraw;
79: #else
80: struct termio ttysave, /* save the state of tty */
81: ttyraw;
82: #endif
83: int obj; /* File descriptor for object file */
84: int mpx; /* Running under mpx */
85: long location;
86: char file[128]; /* Name of file */
87: char m32ld[128]; /* path name to m32ld command */
88: int nargchars; /* Number of characters, including nulls, in args */
89: long longbuf[3];
90: int debug; /* Show sizes etc. */
91: int psflag; /* Print error detection statistics */
92: short maxpktdsize;
93: int rflag; /* relocate? */
94: int zflag; /* Do a JZOMBOOT */
95: int booted;
96: int errfile;
97: int retries;
98: int open();
99: int access();
100: char *malloc();
101:
102: char Load_str[] = "\033[0;0v"; /* default download (binary & standalone*/
103: int Layerflag = 0;
104: struct stat Statbuf, *Statptr;
105:
106: short speeds[16]={
107: 1, 5, 7, 10, 13, 15, 20, 30,
108: 60, 120, 180, 240, 480, 960, 1920, 1
109: };
110:
111: unsigned char sizes[16]={
112: 16, 16, 16, 16, 16, 16, 16, 16,
113: 16, 32, 32, 56, 56, 120, 60, 16
114: };
115:
116: void Psend();
117: void Precv();
118: void Write();
119:
120: extern int errno;
121: extern char *getenv();
122:
123: timeout_id()
124: {
125: error(0, "Error: can't identify terminal:\n\t not a 5620 terminal or 5620 failed to respond",
126: (char *) 0);
127: }
128:
129: main(argc, argv)
130: int argc;
131: register char *argv[];
132: {
133: char *dwnldflag;
134:
135: #ifndef M32LD
136: M32LD; /* force a compile time error if undefined */
137: #endif
138: /* Start out by checking that download is going */
139: /* to a DMD with at least 1.1 firmware (not 1.0) */
140: char termid[TERMIDSIZE+1];
141: int lpindex;
142: int count;
143: char *strcpy(), *strcat();
144:
145: for (lpindex=0; lpindex<=TERMIDSIZE; lpindex++)
146: termid[lpindex] = 0;
147:
148: (void)strcpy(m32ld, getenv("DMDSGS")? getenv("DMDSGS") : "/usr/jerq");
149: (void)strcat(m32ld, M32LD); /* attach tail of path to head */
150:
151: #if vax | u3b | u3b2 | mc68000
152: (void)ioctl(1, TIOCGETP, &ttysave); /* get the current state */
153: if (ioctl(1, TIOCGDEV, &ttydsave) < 0) {
154: ttydsave.ospeed = ttysave.sg_ospeed;
155: ttydsave.ispeed = ttysave.sg_ispeed;
156: }
157: #else
158: (void)ioctl(1, TCGETA, &ttysave); /* get the current state */
159: #endif
160:
161: name = *argv;
162:
163: while(argc>1 && argv[1][0]=='-'){
164: switch(argv[1][1]){
165: case 'd':
166: debug++;
167: break;
168: case 'e':
169: printf("-e flag no longer used: always assumed\n");
170: break;
171: case 'p':
172: psflag++;
173: break;
174: case 'z':
175: zflag++;
176: break;
177: case 'l':
178: Layerflag++;
179: break;
180: case '\0':
181: break;
182: default:
183: error(0, Usage, (char *)0);
184: return 1;
185: }
186: argv++; argc--;
187: }
188: if(argc<2){
189: error(0, Usage, (char *)0);
190: return 2;
191: }
192:
193: /*
194: * see what type of download is expected
195: */
196: if(((dwnldflag = getenv("DMDLOAD")) != NULL) && (dwnldflag[0] != NULL)) {
197: if(strcmp(dwnldflag, "hex") == 0)
198: Loadtype = HEX_LOAD;
199: else
200: Loadtype = BINARY_LOAD;
201: }
202: Load_str[4] = Loadtype + '0';
203:
204:
205: #if vax | u3b | u3b2 | mc68000
206: ttyraw = ttysave;
207: ttydraw = ttydsave;
208: ttyraw.sg_flags |= RAW;
209: ttydraw.flags |= F8BIT;
210: (void)ioctl(1, TIOCSETP, &ttyraw);
211: (void)ioctl(1, TIOCSDEV, &ttydraw);
212: #else
213: ttyraw.c_iflag = IGNBRK;
214: ttyraw.c_cflag = (ttysave.c_cflag & CBAUD) | (ttysave.c_cflag & CLOCAL) | CS8 | CREAD;
215: ttyraw.c_cc[VMIN] = 1;
216: (void)ioctl(1, TCSETAW, &ttyraw);
217: #endif
218: mpx = (ioctl(1, JMUX, 0) > -1);
219: if ( !mpx )
220: {
221:
222: /* make sure we've got the correct rom */
223: write(1,SENDTERMID,strlen(SENDTERMID));
224: count = 0;
225: while(count < TERMIDSIZE){
226: lpindex = read(0,&termid[count],TERMIDSIZE);
227: if(lpindex <= 0)
228: error(1, "read error", (char *)0);
229: count += lpindex;
230: }
231: if ((strcmp(termid,TERM_1_0) == STR_EQUAL) || /* equal strings */
232: (strcmp(termid,TERMB_1_0) == STR_EQUAL))
233: error(0,"Error: Firmware not updated to 1.1 or greater\n",
234: (char *) 0);
235: if (strncmp(termid,TERM_DMD,strlen(TERM_DMD)) != STR_EQUAL)
236: error(0, "Error: 32ld must be run on a 5620 terminal\n",
237: (char *) 0);
238: } else {
239:
240: /* load sequence for mux is shorter */
241: Load_str[3] = '\0';
242: }
243:
244: if(jpath(argv[1], access, 4)!=0)
245: error(1, "no such file '%s'", argv[1]);
246:
247: Statptr= &Statbuf;
248: stat(argv[1], Statptr);
249: if(Layerflag && (Statbuf.st_size == 0)) {
250: Load_str[2] = '2';
251: realwrite(Load_str, 6);
252: goto cleanup;
253: }
254:
255: obj=jpath(argv[1], open, 0);
256: if(obj<0)
257: error(1, "cannot open '%s'", file);
258:
259: Read (&fileheader, sizeof(struct filehdr));
260: if(fileheader.f_magic!=FBOMAGIC) /* FBOMAGIC is 0560 */
261: error(0, "'%s' is not a MAC-32 a.out", file);
262: Read (&aoutheader, fileheader.f_opthdr);
263:
264: if (fileheader.f_nscns > NSECTS)
265: error(0,"32ld: exceeded max number of sections -- see system administrator");
266: if((aoutheader.vstamp==MPX_VER) ^ mpx) /* MPX_VER is 0x5620 */
267: error(0, mpx? "'%s' compiled stand-alone": "'%s' compiled for mpx", file);
268:
269: if(((aoutheader.tsize + aoutheader.dsize + aoutheader.bsize) == 0) && Layerflag) {
270: Load_str[2] = '2';
271: realwrite(Load_str, mpx ? 3 : 6);
272: goto cleanup;
273: }
274: if(Layerflag) {
275: /*
276: * if it got here then we want to download layers with a patch
277: */
278: Load_str[2] = '1';
279: }
280:
281: if(boot() && rflag==0)
282: rflag++;
283: if(!mpx){
284: #if vax | u3b | u3b2 | mc68000
285: maxpktdsize = min(sizes[ttydsave.ospeed & 017], (long)MAXPKTDSIZE);
286: pinit(speeds[ttydsave.ospeed & 017], maxpktdsize, ACKON);
287: #else
288: maxpktdsize = min(sizes[ttysave.c_cflag&CBAUD], (long)MAXPKTDSIZE);
289: pinit(speeds[ttysave.c_cflag&CBAUD], maxpktdsize, ACKON);
290: #endif
291: }
292:
293: load(argv[1], argc-1, argv+1);
294: if(!mpx){ /* ACKON is always true */
295: buzz();
296: (void)ioctl(0, TIOCFLUSH, (struct termio *)0);
297: }
298: (void)ioctl(1, TIOCNXCL, 0);
299: cleanup:
300: #if vax | u3b | u3b2 | mc68000
301: (void)ioctl(1, TIOCSETP, &ttysave);
302: (void)ioctl(1, TIOCSDEV, &ttydsave);
303: #else
304: (void)ioctl(1, TCSETAW, &ttysave);
305: #endif
306:
307: if(psflag)
308: pstats(stderr);
309: return(0);
310: }
311:
312:
313: char *
314: bldargs(argc, argv)
315: char *argv[];
316: {
317: register i;
318: register char *argp, *p, *q;
319: for(nargchars=0, i=0; i<argc; i++)
320: nargchars+=strlen(argv[i])+1;
321: if((argp=malloc(nargchars))==0)
322: error("can't allocate argument chars", "");
323: /* this loop is probably not necessary, but it's safe */
324: for(i=0, q=argp; i<argc; i++){
325: p=argv[i];
326: do; while(*q++ = *p++);
327: }
328: return argp;
329: }
330:
331:
332: load(f, argc, argv)
333: char *f;
334: char *argv[];
335: {
336: char *argp;
337: long largc;
338: int i;
339: if(mpx){
340: argp=bldargs(argc, argv);
341: largc=argc;
342: writeswap((char *)&largc, 4); /* number of arguments */
343: largc=nargchars;
344: writeswap((char *)&largc, 4); /* number of chars in arguments */
345: writeswap((char *)&aoutheader.tsize, 12);
346: }
347:
348: if(rflag)
349: relocate();
350: else
351: location = aoutheader.entry;
352: if(mpx)
353: Write(argp, nargchars);
354: for (i = 0; i < fileheader.f_nscns; ++i) /* read section header array */
355: Read (§hdrs[i], sizeof(struct scnhdr));
356:
357: if(debug){
358: fprintf(stderr, "%s:\nSection:\taddr:\tsize:\n", file);
359: for ( i = 0; i < fileheader.f_nscns; ++i)
360: fprintf(stderr,"%s\t\t0x%lx\t0x%lx\n",
361: secthdrs[i].s_name,secthdrs[i].s_paddr,secthdrs[i].s_size);
362: buzz();
363: }
364: sendfile();
365: if(!mpx){
366: long startaddr;
367:
368: retries = 0;
369: while(freepkts != NPBUFS)
370: Precv();
371: location = aoutheader.entry;
372: swaw(&location, &startaddr, PKTASIZE);
373: psend((char *)&startaddr, PKTASIZE);
374: retries = 0;
375: while(freepkts != NPBUFS)
376: Precv();
377: }
378: }
379:
380: jpath(f, fn, a)
381: register char *f;
382: register int (*fn)();
383: {
384: char *getenv(), *strcpy();
385: register char *jp, *p;
386: register o;
387: if (*f != '/' && strncmp(f, "./", 2) && strncmp(f, "../", 3) &&
388: (jp=getenv("JPATH"))!=0){
389: while(*jp){
390: for(p=file; *jp && *jp!=':'; p++,jp++)
391: *p= *jp;
392: if(p!=file)
393: *p++='/';
394: if(*jp)
395: jp++;
396: (void)strcpy(p, f);
397: if((o=(*fn)(file, a))!=-1)
398: return o;
399: }
400: }
401: return((*fn)(strcpy(file, f), a));
402: }
403:
404: error(pflag, s1, s2)
405: char *s1, *s2;
406: {
407: long flushval = 0L;
408: register int n;
409: register int saverrno;
410: char buf[BUFSIZ];
411: extern int errno;
412:
413: saverrno = errno;
414: if(booted){
415: if (mpx) /* tell dmd side to give up */
416: (void)ioctl(1, JTERM, 0);
417: else
418: {
419: psend((char *)(&flushval),sizeof(long));
420: }
421: if(errfile>0){
422: buzz();
423: while((n=read(errfile, buf, sizeof buf))>0)
424: write(2, buf, n);
425: unlink(errname);
426: }
427: }
428: (void)ioctl(1, TIOCNXCL, 0);
429: #if vax | u3b | u3b2 | mc68000
430: (void)ioctl(1, TIOCSETP, &ttysave);
431: (void)ioctl(1, TIOCSDEV, &ttydsave);
432: #else
433: (void)ioctl(1, TCSETAW, &ttysave);
434: #endif
435: if(pflag){
436: errno=saverrno;
437: perror(s2);
438: }
439: fprintf(stderr, "%s: ", name);
440: fprintf(stderr, s1, s2);
441: fprintf(stderr, "\n");
442: if(psflag)
443: pstats(stderr);
444: exit(1);
445: }
446: int
447: Read(a, n)
448: char *a;
449: {
450: register i;
451: i=read(obj, a, n);
452: if(i<0)
453: error(1, "read error on '%s'", file);
454: return(i);
455: }
456: void
457: Write(a, n)
458: char *a;
459: {
460: if(realwrite(a, n)!=n)
461: error(1, "write error to jerq", (char *)0);
462: if(psflag && !mpx)
463: trace(a);
464: }
465: writeswap(a, n)
466: char *a;
467: {
468: char buf1[DATASIZE+PKTASIZE], buf2[DATASIZE+PKTASIZE];
469: swaw(a, buf1, n);
470: swab(buf1, buf2, n);
471: Write(buf2, n);
472: }
473: trace(a)
474: char *a;
475: {
476: register int i;
477:
478: for(i=0; i<(PKTHDRSIZE+PKTASIZE); i++)
479: fprintf(stderr, "<%o>", a[i]&0xff);
480: fprintf(stderr, "\n");
481: }
482:
483: sendfile()
484: {
485: register int i;
486: for ( i = 0; i<fileheader.f_nscns; ++i) {
487: if(secthdrs[i].s_scnptr > 0) {
488: if ((secthdrs[i].s_flags & STYP_NOLOAD) ||
489: (secthdrs[i].s_flags & STYP_DSECT))
490: continue;
491: lseek(obj,secthdrs[i].s_scnptr,0);
492: sendseg(secthdrs[i].s_paddr,secthdrs[i].s_paddr+secthdrs[i].s_size);
493: }
494: }
495: }
496:
497: sendseg(strloc,endloc)
498: long strloc;
499: long endloc;
500: {
501: char buf[DATASIZE+PKTASIZE], buf2[DATASIZE];
502: char tmpbuf[DATASIZE+PKTASIZE];
503: register n;
504: while((n=Read(&buf[PKTASIZE], min(!mpx?maxpktdsize:DATASIZE, endloc-strloc)))>0){
505: if(mpx){
506: /* swab(&buf[PKTASIZE], buf2, n); NOT RITE with m32 sgs*/
507: Write(&buf[PKTASIZE], n);
508: }else{
509: swab(&buf[PKTASIZE], &tmpbuf[PKTASIZE], n);
510: swaw((short *)&strloc, (short *)&tmpbuf[0], PKTASIZE);
511: Psend(tmpbuf, n+PKTASIZE);
512: }
513: strloc+=n;
514: }
515: }
516: void
517: Psend(bufp, count)
518: char *bufp;
519: int count;
520: {
521: retries = 0;
522: while(freepkts == 0)
523: Precv();
524: psend(bufp, count);
525: }
526: void
527: Precv()
528: {
529: char c;
530:
531: alarm(3); /* sleep at least 2 seconds */
532: if(realread(&c, 1) == 1){
533: alarm(0);
534: if(psflag)
535: fprintf(stderr, "recv <%o>\n", c&0xff);
536: precv(c);
537: }else if(errno != EINTR )
538: error(1, "read error", (char *)0);
539: else if(++retries >= MAXRETRIES)
540: error(0, "load protocol failed", (char *)0);
541: else if(psflag)
542: fprintf(stderr, "recv timeout.. retries=%d\n",retries);
543: }
544:
545: min(a, b)
546: long b; /* not your average min() */
547: {
548: return(a<b? a : (int)b);
549: }
550:
551: swab(a, b, n)
552: register char *a, *b;
553: register n;
554: {
555: # if(swapb)
556: register char *s, *t;
557: n/=2; /* n in bytes */
558: s=b+1;
559: t=b;
560: while(n--){
561: *s= *a++;
562: *t= *a++;
563: s+=2;
564: t+=2;
565: }
566: # else
567: while(n--)
568: *b++= *a++;
569: # endif
570: }
571:
572: swaw(a, b, n)
573: register short *a, *b;
574: register n;
575: {
576: # if(swapw)
577: register short *s, *t;
578: n/=4; /* n in bytes */
579: s=b+1;
580: t=b;
581: while(n--){
582: *s= *a++;
583: *t= *a++;
584: s+=2;
585: t+=2;
586: }
587: # else
588: n>>=1;
589: while(n--)
590: *b++= *a++;
591: # endif
592: }
593: relocate(){
594: long address;
595: char buf[200];
596: char *mktemp();
597: long caddress;
598: register i;
599: register char *p=(char *)&address;
600: char *tmpname; /* name of temporary file for reloc */
601: for(i=0; i<4; i++)
602: read(0, p++, 1);
603: (void)ioctl(1, TIOCEXCL, 0); /* must be here so PUSHLD can work in mux */
604: swab(&address, &caddress, 4);
605: swaw(&caddress, &address, 4);
606: location=address;
607: if(location==0)
608: error(0, "no memory in terminal", (char *)0);
609: sprintf(buf, "%s -b %lx %s >%s 2>%s", m32ld, location, file,
610: tmpname=mktemp("/tmp/32XXXXXX"),
611: errname=mktemp("/tmp/32EXXXXXX"));
612: if(system(buf)){
613: errfile=open(errname, 0);
614: if (!debug)
615: unlink(tmpname);
616: unlink(errname);
617: error(0, "reloc errors", (char *)0);
618: }
619: close(obj);
620: unlink(errname);
621: obj=open(tmpname, 0);
622: if(obj<0) /* HELP!! */
623: error(1, "tmp file vanished! (%s)", tmpname);
624: if (!debug)
625: unlink (tmpname);
626: Read (&fileheader, sizeof(struct filehdr));
627: Read (&aoutheader, fileheader.f_opthdr);
628: }
629:
630: boot(){
631: char c = 0;
632:
633: if(mpx){
634: (void)ioctl(0, TIOCFLUSH, 0); /* throw away type-ahead! */
635: (void)ioctl(1, zflag?JZOMBOOT:JBOOT, 0);
636: }else{
637: write(1, Load_str,6); /* esc sequence for download */
638: while(c != 'a' && c != 1)
639: read(0, &c, 1); /* wait for terminal to be ready */
640: }
641: booted++;
642: return mpx;
643: }
644:
645: buzz(){
646: /* sleep for a time >~0.5 sec; nice if we had nap! */
647: sleep(2); /* sleep(1) not necessarily long enough */
648: }
649:
650: /*
651: * This routine is the lowest level write routine to the dmd. It provides a
652: * simple way to implement a safer download protocol through networks.
653: * This requires that a shell varariable will be set if this extra precaution
654: * is to be taken.
655: */
656:
657: realwrite(a,n)
658: char *a;
659: {
660: char cbuf[(MAXPKTSIZE + PKTASIZE) * 2], c;
661: int i, j, maxsize;
662:
663: if((Loadtype == BINARY_LOAD) || mpx){
664: return(write(1,a,n));
665: }
666: else {
667: /*
668: * do a hex load
669: */
670: j = n;
671: maxsize = ((MAXPKTSIZE + PKTASIZE) / 2);
672: for(i = 0;i < n*2; i++){
673: c = *a++;
674: cbuf[i]=(c & 0xf) | 0x40;
675: cbuf[++i]=((c >> 4) & 0xf) | 0x40;
676: }
677: i = 0;
678: while(n > 0) {
679: if(n > maxsize) {
680: if(write(1, &cbuf[i*maxsize*2], maxsize*2) != maxsize*2)
681: return(-1);
682: n -= maxsize;
683: i++;
684: }
685: else {
686: if(write(1, &cbuf[i*maxsize*2], n*2) != n*2)
687: return(-1);
688: n=0; /* last buffer so don't loop anymore */
689: }
690: }
691: return(j); /* all correct so return number of actual characters sent */
692: }
693: }
694:
695: realread(a, n)
696: char *a;
697: {
698: char cbuf[2];
699: int i;
700:
701: if((Loadtype == BINARY_LOAD) || mpx){
702: return(read(0, a, n));
703: }
704: else {
705: for(i = 0; i < n ; i++) {
706: if(read(0, cbuf, 2) != 2)
707: return(-1);
708: *a++ = (cbuf[0] & 0xf) | ((cbuf[1] & 0xf) << 4);
709: }
710: return(n);
711: }
712: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.