1*23153Smckusick /* 2*23153Smckusick * Copyright (c) 1980 Regents of the University of California. 3*23153Smckusick * All rights reserved. The Berkeley software License Agreement 4*23153Smckusick * specifies the terms and conditions for redistribution. 5*23153Smckusick */ 611099Ssam 7*23153Smckusick #ifndef lint 8*23153Smckusick _sccsid:.asciz "@(#)tuboot.c 6.2 (Berkeley) 06/08/85" 9*23153Smckusick #endif not lint 10*23153Smckusick 1111099Ssam /* 1211099Ssam * VAX tu58 console cassette boot block 1311099Ssam * 1413210Shelge * Helge Skrivervik CSRG/UCB 18jun83 1511099Ssam * 1613210Shelge * Reads a program from a rt-11 directory on tape 1713210Shelge * and executes it. Programs must be stripped of 1811099Ssam * the header and is loaded ``bits as is''. 1911099Ssam * You can return to this loader via ``ret'' as 2011099Ssam * you are called ``calls $0,ent''. 2113210Shelge * Error checking and recovery is almost nonexistant 2213210Shelge * due to the severe space constraints. 2313210Shelge * 2413210Shelge * NOTE: Any changes to this program are likely to 2513210Shelge * bring the size over 512 bytes .... 2613210Shelge * 2713210Shelge * Based on tp format bootstrap originally written by Thomas Ferrin. 2813210Shelge * 2911099Ssam */ 3013210Shelge .set CTABLE,0x400 /* where to load the rad50 cnv table */ 3111099Ssam .set RELOC,0x70000 3213194Shelge /* rt-11 directory definitions */ 3313194Shelge .set DIRBLK,6 /* rt-11 directory starts at block 6 */ 3413194Shelge .set FILSIZ,8 /* rt-11 direc entry offset for file size */ 3513194Shelge .set ENTSIZ,14 /* size of 1 rt-11 dir entry, bytes */ 3611099Ssam .set BLKSIZ,512 /* tape block size, bytes */ 3713194Shelge .set NUMDIR,2 /* no. of dir blocks on tape */ 3813210Shelge .set FNSIZ,8 /* size of rad50 filename + 2 */ 3913194Shelge .set NAME,2 /* direc entry offset for filename */ 4013210Shelge .set STATUS,1 /* direc entry offset for entry status */ 4113194Shelge /* rt-11 directory entry status */ 4213194Shelge .set RT_ESEG,8 /* end of directory segment */ 4313194Shelge .set RT_NULL,2 /* empty entry */ 4413194Shelge .set RT_FILE,4 /* valid file entry */ 4511099Ssam /* processor registers and bits */ 4611099Ssam .set RXCS,32 4711099Ssam .set RXDB,33 4811099Ssam .set TXCS,34 4911099Ssam .set TXDB,35 5011099Ssam .set RXCS_DONE,0x80 5111099Ssam .set TXCS_RDY,0x80 5211099Ssam .set TXCS_pr,7 /* bit position of TXCS ready bit */ 5311099Ssam .set RXCS_pd,7 /* bit position of RXCS done bit */ 5411099Ssam /* console storage registers and bits */ 5511099Ssam .set CSRS,0x1c 5611099Ssam .set CSRD,0x1d 5711099Ssam .set CSTS,0x1e 5811099Ssam .set CSTD,0x1f 5911099Ssam /* TU commands and bits */ 6011099Ssam .set TU_BREAK,1 6111099Ssam .set TU_INIT,4 6211099Ssam .set TU_CONTINUE,16 6311099Ssam .set TU_READY,7 /* bit position of CSRS ready bit */ 6411099Ssam .set TU_PACKETLEN,8 /* length of readcom block */ 6511099Ssam /* local stack variables */ 6614312Ssam .set ext,-4 /* file ext. */ 6714312Ssam .set name,-20 /* 12 bytes for full name */ 6814312Ssam .set rt_name,-20-FNSIZ /* rad50 file name */ 6914312Ssam /* reboot flags for boot */ 7014312Ssam .set RB_ASK,3 /* ask name and come up single user */ 7111099Ssam 7213194Shelge /* 7313194Shelge * Initialization. 7413194Shelge */ 7511099Ssam init: 7611099Ssam .word 0 /* entry mask for dec monitor */ 7711099Ssam nop;nop;nop;nop;nop /* some no-ops for 750 boot rom to skip */ 7811099Ssam nop;nop;nop;nop;nop 7911099Ssam movl $RELOC,fp /* core loc to which to move this program */ 8013210Shelge addl3 $rt_name,fp,sp /* set stack pointer; leave room for locals */ 8111099Ssam clrl r0 8211099Ssam 1: 8311099Ssam movc3 $end,(r0),(fp) /* move boot up to relocated position */ 8411099Ssam jmp start+RELOC 8511099Ssam 8611099Ssam start: 8711099Ssam mtpr $TU_BREAK,$CSTS /* set break condition */ 8813194Shelge clrl r2 /* nulls */ 8913194Shelge bsbw xmit2 /* wait 2 character times */ 9013194Shelge mfpr $CSRD,r2 /* clear receive buffer */ 9111099Ssam movzwl $TU_INIT|(TU_INIT<<8),r2 /* load 2 INIT opcodes */ 9213194Shelge bsbw xmit2 /* xmit 'em */ 9311099Ssam 1: 9413194Shelge mfpr $CSRD,r7 /* get recv data */ 9511099Ssam cmpb r7,$TU_CONTINUE /* is it a continue flag? */ 9613194Shelge bneq 1b /* nope, look more */ 9711099Ssam 9813210Shelge movab name(fp),r4 /* start of filename storage */ 9913210Shelge clrq (r4) /* init name field */ 10013210Shelge clrq name+8(fp) 10113194Shelge clrq rt_name(fp) /* init rad50 filename */ 10211099Ssam movzbl $'=,r0 /* prompt character */ 10311099Ssam bsbw putc /* output char to main console */ 10411099Ssam 10513210Shelge /* 10613210Shelge * Read in a file name from console. 10713210Shelge */ 10811099Ssam movl r4,r1 /* loc at which to store file name */ 10911099Ssam nxtc: 11011099Ssam bsbw getc /* get input char's in file name */ 11111099Ssam cmpb r0,$012 /* terminator ? */ 11211099Ssam beql nullc 11311099Ssam movb r0,(r1)+ 11411099Ssam brb nxtc 11511099Ssam nullc: 11613210Shelge cmpl r4,r1 11713194Shelge beql start /* restart if empty string */ 11813194Shelge clrb (r1) /* add null byte at end */ 11911099Ssam 12013194Shelge /* 12113210Shelge * User-specified filename has been stored at name(fp), 12213210Shelge * read the entire directory contents into low core. 12313194Shelge */ 12411099Ssam dirred: 12513194Shelge movl $DIRBLK,r10 /* directory starts at block DIRBLK */ 12611099Ssam movl $(NUMDIR*BLKSIZ),r6 /* no. bytes in total dir */ 12713194Shelge clrl r11 /* start address */ 12811099Ssam bsbw taper /* read no. bytes indicated */ 12913194Shelge /* 13013194Shelge * Read in the character conversion table which reside in block 1 13113210Shelge * (the second block) on the cassette. Place it after the directory 13213210Shelge * on low core (from 0x400). 13313194Shelge */ 13413210Shelge movl $1,r10 /* block number */ 13513194Shelge movl $BLKSIZ,r6 /* read one block */ 13613194Shelge bsbw taper 13711099Ssam 13813194Shelge /* 13913194Shelge * Convert the ascii filename to rad50. 14013210Shelge * R4 still points to name(fp) 14113194Shelge */ 14213194Shelge movl $6,r3 /* max length of filename */ 14313194Shelge 1: 14413194Shelge cmpb $'.,(r4)+ /* look for '.' */ 14513210Shelge beql 1f 14613194Shelge sobgtr r3,1b 14713210Shelge incl r4 /* point past '.' if ext is present */ 14813210Shelge 1: 14913194Shelge clrb -1(r4) /* end name with null */ 15013194Shelge movl $3,r3 /* max length of extension */ 15113194Shelge movab ext(fp),r5 /* place extension here */ 15213194Shelge 1: 15313194Shelge movb (r4)+,(r5)+ 15413194Shelge beql 1f /* the string is null terminated */ 15513194Shelge sobgtr r3,1b 15613194Shelge 1: 15713194Shelge movab name(fp),r4 15813194Shelge movab rt_name(fp),r5 /* ptr to rad50 name */ 15913194Shelge bsbw rad50 /* convert filename */ 16013194Shelge movab ext(fp),r4 16113194Shelge movab rt_name+4(fp),r5 16213194Shelge bsbw rad50 /* convert extension */ 16313194Shelge 16413194Shelge /* 16513194Shelge * Search entire directory for user-specified file name. 16613194Shelge */ 16713194Shelge 16813194Shelge movab rt_name(fp),r4 /* search for this file */ 16913210Shelge movl $10,r5 /* point to first file entry */ 17013210Shelge movzwl -2(r5),r10 /* r10 = block # where files begin */ 17113194Shelge 2: 17213194Shelge cmpc3 $6,NAME(r5),(r4) /* see if dir entry matches filename */ 17311099Ssam beql fndfil /* found match */ 17413194Shelge 1: 17513210Shelge addw2 FILSIZ(r5),r10 /* add file length to block pointer */ 17613194Shelge addl2 $ENTSIZ,r5 /* move to next entry */ 17713210Shelge # cpmb STATUS(r5),$RT_NULL /* check if deleted file */ 17813210Shelge # beql 1b /* not really necessary since deleted entries will fail */ 17913210Shelge /* to compare anyway */ 18013210Shelge cmpb STATUS(r5),$RT_ESEG /* check if end of segment */ 18113194Shelge bneq 2b 18211099Ssam brw start /* entry not in directory; start over */ 18311099Ssam 18413194Shelge /* 18513194Shelge * Found desired directory entry 18613194Shelge */ 18711099Ssam fndfil: 18813210Shelge /* start block no., 2 bytes in r10 */ 18913194Shelge movzwl FILSIZ(r5),r6 /* file size (blocks) */ 19013194Shelge mull2 $BLKSIZ,r6 /* file size (bytes) */ 19113210Shelge cmpl r6,$RELOC-512 /* check if file fits below stack */ 19213210Shelge blss filok 19313210Shelge brw start /* file too large */ 19411099Ssam 19513194Shelge /* 19613194Shelge * Read in desired file from tape. 19713194Shelge */ 19811099Ssam filok: 19911099Ssam movl r6,r5 /* start of bss space */ 20013194Shelge clrl r11 /* start address */ 20111099Ssam bsbb taper 20211099Ssam 20313194Shelge /* 20413194Shelge * Clear core. 20513194Shelge */ 20611099Ssam subl3 r5,$RELOC-4,r0 /* no. bytes to clear */ 20711099Ssam 1: 20811099Ssam clrb (r5)+ 20911099Ssam sobgtr r0,1b 21011099Ssam 21113194Shelge /* 21213194Shelge * Jump to start of file & execute. 21313194Shelge */ 21413210Shelge addl3 $20,fp,ap /* ?? */ 21511099Ssam clrl r5 21614312Ssam movl $RB_ASK,r11 21711099Ssam calls $0,(r5) 21811099Ssam bad: 21911099Ssam brw start 22011099Ssam 22113210Shelge /* 22213210Shelge * Read (r6) bytes from block (r10) 22313210Shelge * into loc (r11). 22413210Shelge */ 22511099Ssam taper: 22613194Shelge clrl r8 /* initialize checksum */ 22713194Shelge movab readcom,r0 /* read command packet addr */ 22811099Ssam movzbl $TU_PACKETLEN/2,r1 /* size of readcom block */ 22911099Ssam 1: 23013194Shelge movzwl (r0)+,r2 /* get 2 chars from block */ 23113194Shelge bsbb xmit /* xmit and update ckecksum */ 23213194Shelge sobgtr r1,1b /* loop if more */ 23311099Ssam 23413210Shelge /* 23513210Shelge * Now do variable part of packet. 23613210Shelge */ 23713194Shelge movl r6,r2 /* byte count */ 23811099Ssam bsbb xmit 23913194Shelge movl r10,r2 /* starting block number */ 24011099Ssam bsbb xmit 24113194Shelge movzwl r8,r2 /* accumulated ckecksum */ 24211099Ssam bsbb xmit 24311099Ssam 24413210Shelge /* 24513210Shelge * Collect read packet from device. 24613210Shelge */ 24711099Ssam 1: 24813194Shelge bsbb recv2 /* get 2 packet characters */ 24913194Shelge decb r2 /* data packet? */ 25013194Shelge bneq 1f /* branch on end of data */ 25113194Shelge movzbl r1,r8 /* get byte count of packet */ 25211099Ssam 25313210Shelge /* 25413210Shelge * Read data into memory. 25513210Shelge */ 25611099Ssam 2: 25713194Shelge bsbb recv1 /* get a char */ 25813210Shelge movb r1,(r11)+ /* stuff into memory */ 25913194Shelge sobgtr r8,2b /* loop if more */ 26013194Shelge bsbb recv2 /* skip checksum */ 26113194Shelge brb 1b /* read next packet */ 26211099Ssam 26313210Shelge /* 26413210Shelge * End of data xfer; check for errors. 26513210Shelge */ 26611099Ssam 1: 26713194Shelge bsbb recv2 /* get success code */ 26813194Shelge tstl r1 /* error in read? */ 26913194Shelge blss 9f /* branch if status error */ 27011099Ssam movl $5,r0 27111099Ssam 1: 27213194Shelge bsbb recv2 /* discard 10 bytes */ 27311099Ssam sobgtr r0,1b 27411099Ssam rsb 27511099Ssam 27613210Shelge /* Fatal error */ 27711099Ssam 9: 27811099Ssam movab ermsg,r1 27911099Ssam 1: 28011099Ssam movb (r1)+,r0 28111099Ssam beql bad 28211099Ssam bsbb putc 28311099Ssam brb 1b 28411099Ssam 28513210Shelge /* 28613210Shelge * Update checksum in r8 and xmit 2 characters. 28713210Shelge */ 28811099Ssam xmit: 28913194Shelge addw2 r2,r8 /* update checksum */ 29013210Shelge adwc $0,r8 /* add in carry */ 29111099Ssam 29213210Shelge /* send the 2 characters contained in r2 */ 29311099Ssam xmit2: 29413194Shelge bsbb 1f /* xmit one of 'em */ 29513194Shelge ashl $-8,r2,r2 /* get next char */ 29613194Shelge /* fall into... */ 29711099Ssam 1: 29813194Shelge mfpr $CSTS,r7 /* get xmit status */ 29913194Shelge bbc $TU_READY,r7,1b /* loop until ready */ 30013194Shelge mtpr r2,$CSTD /* send char */ 30111099Ssam rsb 30211099Ssam 30313210Shelge /* 30413210Shelge * Receive 2 characters, return in r2 and r1. 30513210Shelge */ 30611099Ssam recv2: 30713194Shelge bsbb recv1 /* recv one of 'em */ 30813194Shelge /* fall into... */ 30911099Ssam 31013210Shelge /* 31113210Shelge * Receive 1 character. 31213210Shelge */ 31311099Ssam recv1: 31413194Shelge movzbl r1,r2 /* save previous byte */ 31511099Ssam 1: 31613194Shelge mfpr $CSRS,r7 /* get recv status */ 31713194Shelge bbc $TU_READY,r7,1b /* loop until ready */ 31813194Shelge mfpr $CSRD,r1 /* get char */ 31913237Shelge blss 9b /* branch on recv error */ 32011099Ssam rsb 32111099Ssam 32211099Ssam getc: 32311099Ssam mfpr $RXCS,r0 32411099Ssam bbc $RXCS_pd,r0,getc /* receiver ready ? */ 32511099Ssam mfpr $RXDB,r0 32613439Ssam extzv $0,$7,r0,r0 32711099Ssam cmpb r0,$015 32811099Ssam bneq putc /* echo and return */ 32911099Ssam bsbb putc /* carriage return */ 33013194Shelge # movb $0,r0 33113194Shelge # bsbb putc /* delay */ 33211099Ssam movb $012,r0 /* send line feed and return */ 33311099Ssam putc: 33411099Ssam mfpr $TXCS,r2 33511099Ssam bbc $TXCS_pr,r2,putc /* transmitter ready ? */ 33611099Ssam mtpr r0,$TXDB 33711099Ssam rsb 33811099Ssam 33913194Shelge /* 34013194Shelge * Convert the filename given from the console 34113194Shelge * to radix 50 (rt-11) format. 34213194Shelge */ 34313194Shelge rad50: 34413210Shelge clrw r1 34513194Shelge bsbb getb50 /* get next ascii byte, exit if null */ 34613194Shelge mull3 $03100,r0,r1 34713194Shelge bsbb getb50 34813194Shelge mull3 $050,r0,r2 34913194Shelge addl2 r2,r1 35013194Shelge bsbb getb50 35113194Shelge addl2 r0,r1 /* last byte, just add it in */ 35213194Shelge movw r1,(r5)+ /* save result */ 35313210Shelge brb rad50 35413194Shelge 35513194Shelge getb50: 35613194Shelge movzbl (r4)+,r0 /* get next ascii byte */ 35713194Shelge beql 1f /* if zero: end of string */ 35813210Shelge movzbl CTABLE(r0),r0 /* and get the r50 byte from the table*/ 35913194Shelge rsb 36013194Shelge 1: 36113194Shelge tstl (sp)+ /* we're through, get back to where */ 36213194Shelge /* rad50 was called */ 36313194Shelge movw r1,(r5) /* but first save the result */ 36413194Shelge rsb 36513194Shelge 36611099Ssam .align 2 36711099Ssam readcom: 36813194Shelge .byte 2 /* command packet flag */ 36913194Shelge .byte 10 /* number of bytes in message */ 37013194Shelge .byte 2 /* tu read opcode */ 37113194Shelge .byte 0 /* modifier */ 37213194Shelge .byte 0 /* unit number */ 37313194Shelge .byte 0 /* switches */ 37413194Shelge .word 0 /* sequence number */ 37513194Shelge /* byte count and block number follow */ 37611099Ssam 37711099Ssam ermsg: 37814312Ssam .asciz "tuerr\r\n" 37911099Ssam end: 38013237Shelge 38113237Shelge /* 38213237Shelge * Ascii to rad 50 conversion table, 38313237Shelge * stored on the second block on the cassette 38413237Shelge * 38513237Shelge * NOTE: Always make sure this table ends up 38613237Shelge * starting at byte 512!!!! 38713237Shelge */ 38813237Shelge .align 2 38913237Shelge .data 2 39013237Shelge .long 0x1d1d1d1d 39113237Shelge .long 0x1d1d1d1d 39213237Shelge .long 0x1d1d1d1d 39313237Shelge .long 0x1d1d1d1d 39413237Shelge .long 0x1d1d1d1d 39513237Shelge .long 0x1d1d1d1d 39613237Shelge .long 0x1d1d1d1d 39713237Shelge .long 0x1d1d1d1d 39813237Shelge .long 0x1d1d1d00 39913237Shelge .long 0x1d1d1d1b 40013237Shelge .long 0x1d1d1d1d 40113237Shelge .long 0x1d1c1d1d 40213237Shelge .long 0x21201f1e 40313237Shelge .long 0x25242322 40413237Shelge .long 0x1d1d2726 40513237Shelge .long 0x1d1d1d1d 40613237Shelge .long 0x302011d 40713237Shelge .long 0x7060504 40813237Shelge .long 0xb0a0908 40913237Shelge .long 0xf0e0d0c 41013237Shelge .long 0x13121110 41113237Shelge .long 0x17161514 41213237Shelge .long 0x1d1a1918 41313237Shelge .long 0x1d1d1d1d 41413237Shelge .long 0x302011d 41513237Shelge .long 0x7060504 41613237Shelge .long 0xb0a0908 41713237Shelge .long 0xf0e0d0c 41813237Shelge .long 0x13121110 41913237Shelge .long 0x17161514 42013237Shelge .long 0x1d1a1918 42113237Shelge .long 0x1d1d1d1d 42213237Shelge .long 0x1d1d1d1d 42313237Shelge .long 0x1d1d1d1d 42413237Shelge .long 0x1d1d1d1d 42513237Shelge .long 0x1d1d1d1d 42613237Shelge .long 0x1d1d1d1d 42713237Shelge .long 0x1d1d1d1d 42813237Shelge .long 0x1d1d1d1d 42913237Shelge .long 0x1d1d1d1d 43013237Shelge .long 0x1d1d1d00 43113237Shelge .long 0x1d1d1d1b 43213237Shelge .long 0x1d1d1d1d 43313237Shelge .long 0x1d1c1d1d 43413237Shelge .long 0x21201f1e 43513237Shelge .long 0x25242322 43613237Shelge .long 0x1d1d2726 43713237Shelge .long 0x1d1d1d1d 43813237Shelge .long 0x302011d 43913237Shelge .long 0x7060504 44013237Shelge .long 0xb0a0908 44113237Shelge .long 0xf0e0d0c 44213237Shelge .long 0x13121110 44313237Shelge .long 0x17161514 44413237Shelge .long 0x1d1a1918 44513237Shelge .long 0x1d1d1d1d 44613237Shelge .long 0x302011d 44713237Shelge .long 0x7060504 44813237Shelge .long 0xb0a0908 44913237Shelge .long 0xf0e0d0c 45013237Shelge .long 0x13121110 45113237Shelge .long 0x17161514 45213237Shelge .long 0x1d1a1918 45313237Shelge .long 0x1d1d1d 45413237Shelge .data 455