|
|
1.1 root 1: /*
2: * Copyright (c) 1980, 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: /* "@(#)tuboot.s 7.1 (Berkeley) 6/5/86" */
8:
9: /*
10: * VAX tu58 console cassette boot block
11: *
12: * Helge Skrivervik CSRG/UCB 18jun83
13: *
14: * Reads a program from a rt-11 directory on tape
15: * and executes it. Programs must be stripped of
16: * the header and is loaded ``bits as is''.
17: * You can return to this loader via ``ret'' as
18: * you are called ``calls $0,ent''.
19: * Error checking and recovery is almost nonexistant
20: * due to the severe space constraints.
21: *
22: * NOTE: Any changes to this program are likely to
23: * bring the size over 512 bytes ....
24: *
25: * Based on tp format bootstrap originally written by Thomas Ferrin.
26: *
27: */
28: .set CTABLE,0x400 /* where to load the rad50 cnv table */
29: .set RELOC,0x70000
30: /* rt-11 directory definitions */
31: .set DIRBLK,6 /* rt-11 directory starts at block 6 */
32: .set FILSIZ,8 /* rt-11 direc entry offset for file size */
33: .set ENTSIZ,14 /* size of 1 rt-11 dir entry, bytes */
34: .set BLKSIZ,512 /* tape block size, bytes */
35: .set NUMDIR,2 /* no. of dir blocks on tape */
36: .set FNSIZ,8 /* size of rad50 filename + 2 */
37: .set NAME,2 /* direc entry offset for filename */
38: .set STATUS,1 /* direc entry offset for entry status */
39: /* rt-11 directory entry status */
40: .set RT_ESEG,8 /* end of directory segment */
41: .set RT_NULL,2 /* empty entry */
42: .set RT_FILE,4 /* valid file entry */
43: /* processor registers and bits */
44: .set RXCS,32
45: .set RXDB,33
46: .set TXCS,34
47: .set TXDB,35
48: .set RXCS_DONE,0x80
49: .set TXCS_RDY,0x80
50: .set TXCS_pr,7 /* bit position of TXCS ready bit */
51: .set RXCS_pd,7 /* bit position of RXCS done bit */
52: /* console storage registers and bits */
53: .set CSRS,0x1c
54: .set CSRD,0x1d
55: .set CSTS,0x1e
56: .set CSTD,0x1f
57: /* TU commands and bits */
58: .set TU_BREAK,1
59: .set TU_INIT,4
60: .set TU_CONTINUE,16
61: .set TU_READY,7 /* bit position of CSRS ready bit */
62: .set TU_PACKETLEN,8 /* length of readcom block */
63: /* local stack variables */
64: .set ext,-4 /* file ext. */
65: .set name,-20 /* 12 bytes for full name */
66: .set rt_name,-20-FNSIZ /* rad50 file name */
67: /* reboot flags for boot */
68: .set RB_ASK,3 /* ask name and come up single user */
69:
70: /*
71: * Initialization.
72: */
73: init:
74: .word 0 /* entry mask for dec monitor */
75: nop;nop;nop;nop;nop /* some no-ops for 750 boot rom to skip */
76: nop;nop;nop;nop;nop
77: movl $RELOC,fp /* core loc to which to move this program */
78: addl3 $rt_name,fp,sp /* set stack pointer; leave room for locals */
79: clrl r0
80: 1:
81: movc3 $end,(r0),(fp) /* move boot up to relocated position */
82: jmp start+RELOC
83:
84: start:
85: mtpr $TU_BREAK,$CSTS /* set break condition */
86: clrl r2 /* nulls */
87: bsbw xmit2 /* wait 2 character times */
88: mfpr $CSRD,r2 /* clear receive buffer */
89: movzwl $TU_INIT|(TU_INIT<<8),r2 /* load 2 INIT opcodes */
90: bsbw xmit2 /* xmit 'em */
91: 1:
92: mfpr $CSRD,r7 /* get recv data */
93: cmpb r7,$TU_CONTINUE /* is it a continue flag? */
94: bneq 1b /* nope, look more */
95:
96: movab name(fp),r4 /* start of filename storage */
97: clrq (r4) /* init name field */
98: clrq name+8(fp)
99: clrq rt_name(fp) /* init rad50 filename */
100: movzbl $'=,r0 /* prompt character */
101: bsbw putc /* output char to main console */
102:
103: /*
104: * Read in a file name from console.
105: */
106: movl r4,r1 /* loc at which to store file name */
107: nxtc:
108: bsbw getc /* get input char's in file name */
109: cmpb r0,$012 /* terminator ? */
110: beql nullc
111: movb r0,(r1)+
112: brb nxtc
113: nullc:
114: cmpl r4,r1
115: beql start /* restart if empty string */
116: clrb (r1) /* add null byte at end */
117:
118: /*
119: * User-specified filename has been stored at name(fp),
120: * read the entire directory contents into low core.
121: */
122: dirred:
123: movl $DIRBLK,r10 /* directory starts at block DIRBLK */
124: movl $(NUMDIR*BLKSIZ),r6 /* no. bytes in total dir */
125: clrl r11 /* start address */
126: bsbw taper /* read no. bytes indicated */
127: /*
128: * Read in the character conversion table which reside in block 1
129: * (the second block) on the cassette. Place it after the directory
130: * on low core (from 0x400).
131: */
132: movl $1,r10 /* block number */
133: movl $BLKSIZ,r6 /* read one block */
134: bsbw taper
135:
136: /*
137: * Convert the ascii filename to rad50.
138: * R4 still points to name(fp)
139: */
140: movl $6,r3 /* max length of filename */
141: 1:
142: cmpb $'.,(r4)+ /* look for '.' */
143: beql 1f
144: sobgtr r3,1b
145: incl r4 /* point past '.' if ext is present */
146: 1:
147: clrb -1(r4) /* end name with null */
148: movl $3,r3 /* max length of extension */
149: movab ext(fp),r5 /* place extension here */
150: 1:
151: movb (r4)+,(r5)+
152: beql 1f /* the string is null terminated */
153: sobgtr r3,1b
154: 1:
155: movab name(fp),r4
156: movab rt_name(fp),r5 /* ptr to rad50 name */
157: bsbw rad50 /* convert filename */
158: movab ext(fp),r4
159: movab rt_name+4(fp),r5
160: bsbw rad50 /* convert extension */
161:
162: /*
163: * Search entire directory for user-specified file name.
164: */
165:
166: movab rt_name(fp),r4 /* search for this file */
167: movl $10,r5 /* point to first file entry */
168: movzwl -2(r5),r10 /* r10 = block # where files begin */
169: 2:
170: cmpc3 $6,NAME(r5),(r4) /* see if dir entry matches filename */
171: beql fndfil /* found match */
172: 1:
173: addw2 FILSIZ(r5),r10 /* add file length to block pointer */
174: addl2 $ENTSIZ,r5 /* move to next entry */
175: # cpmb STATUS(r5),$RT_NULL /* check if deleted file */
176: # beql 1b /* not really necessary since deleted entries will fail */
177: /* to compare anyway */
178: cmpb STATUS(r5),$RT_ESEG /* check if end of segment */
179: bneq 2b
180: brw start /* entry not in directory; start over */
181:
182: /*
183: * Found desired directory entry
184: */
185: fndfil:
186: /* start block no., 2 bytes in r10 */
187: movzwl FILSIZ(r5),r6 /* file size (blocks) */
188: mull2 $BLKSIZ,r6 /* file size (bytes) */
189: cmpl r6,$RELOC-512 /* check if file fits below stack */
190: blss filok
191: brw start /* file too large */
192:
193: /*
194: * Read in desired file from tape.
195: */
196: filok:
197: movl r6,r5 /* start of bss space */
198: clrl r11 /* start address */
199: bsbb taper
200:
201: /*
202: * Clear core.
203: */
204: subl3 r5,$RELOC-4,r0 /* no. bytes to clear */
205: 1:
206: clrb (r5)+
207: sobgtr r0,1b
208:
209: /*
210: * Jump to start of file & execute.
211: */
212: addl3 $20,fp,ap /* ?? */
213: clrl r5
214: movl $RB_ASK,r11
215: calls $0,(r5)
216: bad:
217: brw start
218:
219: /*
220: * Read (r6) bytes from block (r10)
221: * into loc (r11).
222: */
223: taper:
224: clrl r8 /* initialize checksum */
225: movab readcom,r0 /* read command packet addr */
226: movzbl $TU_PACKETLEN/2,r1 /* size of readcom block */
227: 1:
228: movzwl (r0)+,r2 /* get 2 chars from block */
229: bsbb xmit /* xmit and update ckecksum */
230: sobgtr r1,1b /* loop if more */
231:
232: /*
233: * Now do variable part of packet.
234: */
235: movl r6,r2 /* byte count */
236: bsbb xmit
237: movl r10,r2 /* starting block number */
238: bsbb xmit
239: movzwl r8,r2 /* accumulated ckecksum */
240: bsbb xmit
241:
242: /*
243: * Collect read packet from device.
244: */
245: 1:
246: bsbb recv2 /* get 2 packet characters */
247: decb r2 /* data packet? */
248: bneq 1f /* branch on end of data */
249: movzbl r1,r8 /* get byte count of packet */
250:
251: /*
252: * Read data into memory.
253: */
254: 2:
255: bsbb recv1 /* get a char */
256: movb r1,(r11)+ /* stuff into memory */
257: sobgtr r8,2b /* loop if more */
258: bsbb recv2 /* skip checksum */
259: brb 1b /* read next packet */
260:
261: /*
262: * End of data xfer; check for errors.
263: */
264: 1:
265: bsbb recv2 /* get success code */
266: tstl r1 /* error in read? */
267: blss 9f /* branch if status error */
268: movl $5,r0
269: 1:
270: bsbb recv2 /* discard 10 bytes */
271: sobgtr r0,1b
272: rsb
273:
274: /* Fatal error */
275: 9:
276: movab ermsg,r1
277: 1:
278: movb (r1)+,r0
279: beql bad
280: bsbb putc
281: brb 1b
282:
283: /*
284: * Update checksum in r8 and xmit 2 characters.
285: */
286: xmit:
287: addw2 r2,r8 /* update checksum */
288: adwc $0,r8 /* add in carry */
289:
290: /* send the 2 characters contained in r2 */
291: xmit2:
292: bsbb 1f /* xmit one of 'em */
293: ashl $-8,r2,r2 /* get next char */
294: /* fall into... */
295: 1:
296: mfpr $CSTS,r7 /* get xmit status */
297: bbc $TU_READY,r7,1b /* loop until ready */
298: mtpr r2,$CSTD /* send char */
299: rsb
300:
301: /*
302: * Receive 2 characters, return in r2 and r1.
303: */
304: recv2:
305: bsbb recv1 /* recv one of 'em */
306: /* fall into... */
307:
308: /*
309: * Receive 1 character.
310: */
311: recv1:
312: movzbl r1,r2 /* save previous byte */
313: 1:
314: mfpr $CSRS,r7 /* get recv status */
315: bbc $TU_READY,r7,1b /* loop until ready */
316: mfpr $CSRD,r1 /* get char */
317: blss 9b /* branch on recv error */
318: rsb
319:
320: getc:
321: mfpr $RXCS,r0
322: bbc $RXCS_pd,r0,getc /* receiver ready ? */
323: mfpr $RXDB,r0
324: extzv $0,$7,r0,r0
325: cmpb r0,$015
326: bneq putc /* echo and return */
327: bsbb putc /* carriage return */
328: # movb $0,r0
329: # bsbb putc /* delay */
330: movb $012,r0 /* send line feed and return */
331: putc:
332: mfpr $TXCS,r2
333: bbc $TXCS_pr,r2,putc /* transmitter ready ? */
334: mtpr r0,$TXDB
335: rsb
336:
337: /*
338: * Convert the filename given from the console
339: * to radix 50 (rt-11) format.
340: */
341: rad50:
342: clrw r1
343: bsbb getb50 /* get next ascii byte, exit if null */
344: mull3 $03100,r0,r1
345: bsbb getb50
346: mull3 $050,r0,r2
347: addl2 r2,r1
348: bsbb getb50
349: addl2 r0,r1 /* last byte, just add it in */
350: movw r1,(r5)+ /* save result */
351: brb rad50
352:
353: getb50:
354: movzbl (r4)+,r0 /* get next ascii byte */
355: beql 1f /* if zero: end of string */
356: movzbl CTABLE(r0),r0 /* and get the r50 byte from the table*/
357: rsb
358: 1:
359: tstl (sp)+ /* we're through, get back to where */
360: /* rad50 was called */
361: movw r1,(r5) /* but first save the result */
362: rsb
363:
364: .align 2
365: readcom:
366: .byte 2 /* command packet flag */
367: .byte 10 /* number of bytes in message */
368: .byte 2 /* tu read opcode */
369: .byte 0 /* modifier */
370: .byte 0 /* unit number */
371: .byte 0 /* switches */
372: .word 0 /* sequence number */
373: /* byte count and block number follow */
374:
375: ermsg:
376: .asciz "tuerr\r\n"
377: end:
378:
379: /*
380: * Ascii to rad 50 conversion table,
381: * stored on the second block on the cassette
382: *
383: * NOTE: Always make sure this table ends up
384: * starting at byte 512!!!!
385: */
386: .align 2
387: .data 2
388: .long 0x1d1d1d1d
389: .long 0x1d1d1d1d
390: .long 0x1d1d1d1d
391: .long 0x1d1d1d1d
392: .long 0x1d1d1d1d
393: .long 0x1d1d1d1d
394: .long 0x1d1d1d1d
395: .long 0x1d1d1d1d
396: .long 0x1d1d1d00
397: .long 0x1d1d1d1b
398: .long 0x1d1d1d1d
399: .long 0x1d1c1d1d
400: .long 0x21201f1e
401: .long 0x25242322
402: .long 0x1d1d2726
403: .long 0x1d1d1d1d
404: .long 0x302011d
405: .long 0x7060504
406: .long 0xb0a0908
407: .long 0xf0e0d0c
408: .long 0x13121110
409: .long 0x17161514
410: .long 0x1d1a1918
411: .long 0x1d1d1d1d
412: .long 0x302011d
413: .long 0x7060504
414: .long 0xb0a0908
415: .long 0xf0e0d0c
416: .long 0x13121110
417: .long 0x17161514
418: .long 0x1d1a1918
419: .long 0x1d1d1d1d
420: .long 0x1d1d1d1d
421: .long 0x1d1d1d1d
422: .long 0x1d1d1d1d
423: .long 0x1d1d1d1d
424: .long 0x1d1d1d1d
425: .long 0x1d1d1d1d
426: .long 0x1d1d1d1d
427: .long 0x1d1d1d1d
428: .long 0x1d1d1d00
429: .long 0x1d1d1d1b
430: .long 0x1d1d1d1d
431: .long 0x1d1c1d1d
432: .long 0x21201f1e
433: .long 0x25242322
434: .long 0x1d1d2726
435: .long 0x1d1d1d1d
436: .long 0x302011d
437: .long 0x7060504
438: .long 0xb0a0908
439: .long 0xf0e0d0c
440: .long 0x13121110
441: .long 0x17161514
442: .long 0x1d1a1918
443: .long 0x1d1d1d1d
444: .long 0x302011d
445: .long 0x7060504
446: .long 0xb0a0908
447: .long 0xf0e0d0c
448: .long 0x13121110
449: .long 0x17161514
450: .long 0x1d1a1918
451: .long 0x1d1d1d
452: .data
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.