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