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