xref: /original-bsd/sys/vax/mdec/tuboot.c (revision 8f26171a)
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.c	7.2 (Berkeley) 08/28/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
453