123153Smckusick /* 229328Smckusick * Copyright (c) 1980, 1986 Regents of the University of California. 323153Smckusick * All rights reserved. The Berkeley software License Agreement 423153Smckusick * specifies the terms and conditions for redistribution. 523153Smckusick */ 611099Ssam 7*29801Skarels /* "@(#)tuboot.c 7.2 (Berkeley) 08/28/86" */ 823153Smckusick 911099Ssam /* 1011099Ssam * VAX tu58 console cassette boot block 1111099Ssam * 1213210Shelge * Helge Skrivervik CSRG/UCB 18jun83 1311099Ssam * 1413210Shelge * Reads a program from a rt-11 directory on tape 1513210Shelge * and executes it. Programs must be stripped of 1611099Ssam * the header and is loaded ``bits as is''. 1711099Ssam * You can return to this loader via ``ret'' as 1811099Ssam * you are called ``calls $0,ent''. 1913210Shelge * Error checking and recovery is almost nonexistant 2013210Shelge * due to the severe space constraints. 2113210Shelge * 2213210Shelge * NOTE: Any changes to this program are likely to 2313210Shelge * bring the size over 512 bytes .... 2413210Shelge * 2513210Shelge * Based on tp format bootstrap originally written by Thomas Ferrin. 2613210Shelge * 2711099Ssam */ 2813210Shelge .set CTABLE,0x400 /* where to load the rad50 cnv table */ 2911099Ssam .set RELOC,0x70000 3013194Shelge /* rt-11 directory definitions */ 3113194Shelge .set DIRBLK,6 /* rt-11 directory starts at block 6 */ 3213194Shelge .set FILSIZ,8 /* rt-11 direc entry offset for file size */ 3313194Shelge .set ENTSIZ,14 /* size of 1 rt-11 dir entry, bytes */ 3411099Ssam .set BLKSIZ,512 /* tape block size, bytes */ 3513194Shelge .set NUMDIR,2 /* no. of dir blocks on tape */ 3613210Shelge .set FNSIZ,8 /* size of rad50 filename + 2 */ 3713194Shelge .set NAME,2 /* direc entry offset for filename */ 3813210Shelge .set STATUS,1 /* direc entry offset for entry status */ 3913194Shelge /* rt-11 directory entry status */ 4013194Shelge .set RT_ESEG,8 /* end of directory segment */ 4113194Shelge .set RT_NULL,2 /* empty entry */ 4213194Shelge .set RT_FILE,4 /* valid file entry */ 4311099Ssam /* processor registers and bits */ 4411099Ssam .set RXCS,32 4511099Ssam .set RXDB,33 4611099Ssam .set TXCS,34 4711099Ssam .set TXDB,35 4811099Ssam .set RXCS_DONE,0x80 4911099Ssam .set TXCS_RDY,0x80 5011099Ssam .set TXCS_pr,7 /* bit position of TXCS ready bit */ 5111099Ssam .set RXCS_pd,7 /* bit position of RXCS done bit */ 5211099Ssam /* console storage registers and bits */ 5311099Ssam .set CSRS,0x1c 5411099Ssam .set CSRD,0x1d 5511099Ssam .set CSTS,0x1e 5611099Ssam .set CSTD,0x1f 5711099Ssam /* TU commands and bits */ 5811099Ssam .set TU_BREAK,1 5911099Ssam .set TU_INIT,4 6011099Ssam .set TU_CONTINUE,16 6111099Ssam .set TU_READY,7 /* bit position of CSRS ready bit */ 6211099Ssam .set TU_PACKETLEN,8 /* length of readcom block */ 6311099Ssam /* local stack variables */ 6414312Ssam .set ext,-4 /* file ext. */ 6514312Ssam .set name,-20 /* 12 bytes for full name */ 6614312Ssam .set rt_name,-20-FNSIZ /* rad50 file name */ 6714312Ssam /* reboot flags for boot */ 6814312Ssam .set RB_ASK,3 /* ask name and come up single user */ 6911099Ssam 7013194Shelge /* 7113194Shelge * Initialization. 7213194Shelge */ 7311099Ssam init: 7411099Ssam .word 0 /* entry mask for dec monitor */ 7511099Ssam nop;nop;nop;nop;nop /* some no-ops for 750 boot rom to skip */ 7611099Ssam nop;nop;nop;nop;nop 7711099Ssam movl $RELOC,fp /* core loc to which to move this program */ 7813210Shelge addl3 $rt_name,fp,sp /* set stack pointer; leave room for locals */ 7911099Ssam clrl r0 8011099Ssam 1: 8111099Ssam movc3 $end,(r0),(fp) /* move boot up to relocated position */ 8211099Ssam jmp start+RELOC 8311099Ssam 8411099Ssam start: 8511099Ssam mtpr $TU_BREAK,$CSTS /* set break condition */ 8613194Shelge clrl r2 /* nulls */ 8713194Shelge bsbw xmit2 /* wait 2 character times */ 8813194Shelge mfpr $CSRD,r2 /* clear receive buffer */ 8911099Ssam movzwl $TU_INIT|(TU_INIT<<8),r2 /* load 2 INIT opcodes */ 9013194Shelge bsbw xmit2 /* xmit 'em */ 9111099Ssam 1: 9213194Shelge mfpr $CSRD,r7 /* get recv data */ 9311099Ssam cmpb r7,$TU_CONTINUE /* is it a continue flag? */ 9413194Shelge bneq 1b /* nope, look more */ 9511099Ssam 9613210Shelge movab name(fp),r4 /* start of filename storage */ 9713210Shelge clrq (r4) /* init name field */ 9813210Shelge clrq name+8(fp) 9913194Shelge clrq rt_name(fp) /* init rad50 filename */ 10011099Ssam movzbl $'=,r0 /* prompt character */ 10111099Ssam bsbw putc /* output char to main console */ 10211099Ssam 10313210Shelge /* 10413210Shelge * Read in a file name from console. 10513210Shelge */ 10611099Ssam movl r4,r1 /* loc at which to store file name */ 10711099Ssam nxtc: 10811099Ssam bsbw getc /* get input char's in file name */ 10911099Ssam cmpb r0,$012 /* terminator ? */ 11011099Ssam beql nullc 11111099Ssam movb r0,(r1)+ 11211099Ssam brb nxtc 11311099Ssam nullc: 11413210Shelge cmpl r4,r1 11513194Shelge beql start /* restart if empty string */ 11613194Shelge clrb (r1) /* add null byte at end */ 11711099Ssam 11813194Shelge /* 11913210Shelge * User-specified filename has been stored at name(fp), 12013210Shelge * read the entire directory contents into low core. 12113194Shelge */ 12211099Ssam dirred: 12313194Shelge movl $DIRBLK,r10 /* directory starts at block DIRBLK */ 12411099Ssam movl $(NUMDIR*BLKSIZ),r6 /* no. bytes in total dir */ 12513194Shelge clrl r11 /* start address */ 12611099Ssam bsbw taper /* read no. bytes indicated */ 12713194Shelge /* 12813194Shelge * Read in the character conversion table which reside in block 1 12913210Shelge * (the second block) on the cassette. Place it after the directory 13013210Shelge * on low core (from 0x400). 13113194Shelge */ 13213210Shelge movl $1,r10 /* block number */ 13313194Shelge movl $BLKSIZ,r6 /* read one block */ 13413194Shelge bsbw taper 13511099Ssam 13613194Shelge /* 13713194Shelge * Convert the ascii filename to rad50. 13813210Shelge * R4 still points to name(fp) 13913194Shelge */ 14013194Shelge movl $6,r3 /* max length of filename */ 14113194Shelge 1: 14213194Shelge cmpb $'.,(r4)+ /* look for '.' */ 14313210Shelge beql 1f 14413194Shelge sobgtr r3,1b 14513210Shelge incl r4 /* point past '.' if ext is present */ 14613210Shelge 1: 14713194Shelge clrb -1(r4) /* end name with null */ 14813194Shelge movl $3,r3 /* max length of extension */ 14913194Shelge movab ext(fp),r5 /* place extension here */ 15013194Shelge 1: 15113194Shelge movb (r4)+,(r5)+ 15213194Shelge beql 1f /* the string is null terminated */ 15313194Shelge sobgtr r3,1b 15413194Shelge 1: 15513194Shelge movab name(fp),r4 15613194Shelge movab rt_name(fp),r5 /* ptr to rad50 name */ 15713194Shelge bsbw rad50 /* convert filename */ 15813194Shelge movab ext(fp),r4 15913194Shelge movab rt_name+4(fp),r5 16013194Shelge bsbw rad50 /* convert extension */ 16113194Shelge 16213194Shelge /* 16313194Shelge * Search entire directory for user-specified file name. 16413194Shelge */ 16513194Shelge 16613194Shelge movab rt_name(fp),r4 /* search for this file */ 16713210Shelge movl $10,r5 /* point to first file entry */ 16813210Shelge movzwl -2(r5),r10 /* r10 = block # where files begin */ 16913194Shelge 2: 17013194Shelge cmpc3 $6,NAME(r5),(r4) /* see if dir entry matches filename */ 17111099Ssam beql fndfil /* found match */ 17213194Shelge 1: 17313210Shelge addw2 FILSIZ(r5),r10 /* add file length to block pointer */ 17413194Shelge addl2 $ENTSIZ,r5 /* move to next entry */ 175*29801Skarels /* cpmb STATUS(r5),$RT_NULL /* check if deleted file */ 176*29801Skarels /* beql 1b /* not really necessary since deleted entries will fail */ 17713210Shelge /* to compare anyway */ 17813210Shelge cmpb STATUS(r5),$RT_ESEG /* check if end of segment */ 17913194Shelge bneq 2b 18011099Ssam brw start /* entry not in directory; start over */ 18111099Ssam 18213194Shelge /* 18313194Shelge * Found desired directory entry 18413194Shelge */ 18511099Ssam fndfil: 18613210Shelge /* start block no., 2 bytes in r10 */ 18713194Shelge movzwl FILSIZ(r5),r6 /* file size (blocks) */ 18813194Shelge mull2 $BLKSIZ,r6 /* file size (bytes) */ 18913210Shelge cmpl r6,$RELOC-512 /* check if file fits below stack */ 19013210Shelge blss filok 19113210Shelge brw start /* file too large */ 19211099Ssam 19313194Shelge /* 19413194Shelge * Read in desired file from tape. 19513194Shelge */ 19611099Ssam filok: 19711099Ssam movl r6,r5 /* start of bss space */ 19813194Shelge clrl r11 /* start address */ 19911099Ssam bsbb taper 20011099Ssam 20113194Shelge /* 20213194Shelge * Clear core. 20313194Shelge */ 20411099Ssam subl3 r5,$RELOC-4,r0 /* no. bytes to clear */ 20511099Ssam 1: 20611099Ssam clrb (r5)+ 20711099Ssam sobgtr r0,1b 20811099Ssam 20913194Shelge /* 21013194Shelge * Jump to start of file & execute. 21113194Shelge */ 21213210Shelge addl3 $20,fp,ap /* ?? */ 21311099Ssam clrl r5 21414312Ssam movl $RB_ASK,r11 21511099Ssam calls $0,(r5) 21611099Ssam bad: 21711099Ssam brw start 21811099Ssam 21913210Shelge /* 22013210Shelge * Read (r6) bytes from block (r10) 22113210Shelge * into loc (r11). 22213210Shelge */ 22311099Ssam taper: 22413194Shelge clrl r8 /* initialize checksum */ 22513194Shelge movab readcom,r0 /* read command packet addr */ 22611099Ssam movzbl $TU_PACKETLEN/2,r1 /* size of readcom block */ 22711099Ssam 1: 22813194Shelge movzwl (r0)+,r2 /* get 2 chars from block */ 22913194Shelge bsbb xmit /* xmit and update ckecksum */ 23013194Shelge sobgtr r1,1b /* loop if more */ 23111099Ssam 23213210Shelge /* 23313210Shelge * Now do variable part of packet. 23413210Shelge */ 23513194Shelge movl r6,r2 /* byte count */ 23611099Ssam bsbb xmit 23713194Shelge movl r10,r2 /* starting block number */ 23811099Ssam bsbb xmit 23913194Shelge movzwl r8,r2 /* accumulated ckecksum */ 24011099Ssam bsbb xmit 24111099Ssam 24213210Shelge /* 24313210Shelge * Collect read packet from device. 24413210Shelge */ 24511099Ssam 1: 24613194Shelge bsbb recv2 /* get 2 packet characters */ 24713194Shelge decb r2 /* data packet? */ 24813194Shelge bneq 1f /* branch on end of data */ 24913194Shelge movzbl r1,r8 /* get byte count of packet */ 25011099Ssam 25113210Shelge /* 25213210Shelge * Read data into memory. 25313210Shelge */ 25411099Ssam 2: 25513194Shelge bsbb recv1 /* get a char */ 25613210Shelge movb r1,(r11)+ /* stuff into memory */ 25713194Shelge sobgtr r8,2b /* loop if more */ 25813194Shelge bsbb recv2 /* skip checksum */ 25913194Shelge brb 1b /* read next packet */ 26011099Ssam 26113210Shelge /* 26213210Shelge * End of data xfer; check for errors. 26313210Shelge */ 26411099Ssam 1: 26513194Shelge bsbb recv2 /* get success code */ 26613194Shelge tstl r1 /* error in read? */ 26713194Shelge blss 9f /* branch if status error */ 26811099Ssam movl $5,r0 26911099Ssam 1: 27013194Shelge bsbb recv2 /* discard 10 bytes */ 27111099Ssam sobgtr r0,1b 27211099Ssam rsb 27311099Ssam 27413210Shelge /* Fatal error */ 27511099Ssam 9: 27611099Ssam movab ermsg,r1 27711099Ssam 1: 27811099Ssam movb (r1)+,r0 27911099Ssam beql bad 28011099Ssam bsbb putc 28111099Ssam brb 1b 28211099Ssam 28313210Shelge /* 28413210Shelge * Update checksum in r8 and xmit 2 characters. 28513210Shelge */ 28611099Ssam xmit: 28713194Shelge addw2 r2,r8 /* update checksum */ 28813210Shelge adwc $0,r8 /* add in carry */ 28911099Ssam 29013210Shelge /* send the 2 characters contained in r2 */ 29111099Ssam xmit2: 29213194Shelge bsbb 1f /* xmit one of 'em */ 29313194Shelge ashl $-8,r2,r2 /* get next char */ 29413194Shelge /* fall into... */ 29511099Ssam 1: 29613194Shelge mfpr $CSTS,r7 /* get xmit status */ 29713194Shelge bbc $TU_READY,r7,1b /* loop until ready */ 29813194Shelge mtpr r2,$CSTD /* send char */ 29911099Ssam rsb 30011099Ssam 30113210Shelge /* 30213210Shelge * Receive 2 characters, return in r2 and r1. 30313210Shelge */ 30411099Ssam recv2: 30513194Shelge bsbb recv1 /* recv one of 'em */ 30613194Shelge /* fall into... */ 30711099Ssam 30813210Shelge /* 30913210Shelge * Receive 1 character. 31013210Shelge */ 31111099Ssam recv1: 31213194Shelge movzbl r1,r2 /* save previous byte */ 31311099Ssam 1: 31413194Shelge mfpr $CSRS,r7 /* get recv status */ 31513194Shelge bbc $TU_READY,r7,1b /* loop until ready */ 31613194Shelge mfpr $CSRD,r1 /* get char */ 31713237Shelge blss 9b /* branch on recv error */ 31811099Ssam rsb 31911099Ssam 32011099Ssam getc: 32111099Ssam mfpr $RXCS,r0 32211099Ssam bbc $RXCS_pd,r0,getc /* receiver ready ? */ 32311099Ssam mfpr $RXDB,r0 32413439Ssam extzv $0,$7,r0,r0 32511099Ssam cmpb r0,$015 32611099Ssam bneq putc /* echo and return */ 32711099Ssam bsbb putc /* carriage return */ 328*29801Skarels /* movb $0,r0 */ 329*29801Skarels /* bsbb putc */ /* delay */ 33011099Ssam movb $012,r0 /* send line feed and return */ 33111099Ssam putc: 33211099Ssam mfpr $TXCS,r2 33311099Ssam bbc $TXCS_pr,r2,putc /* transmitter ready ? */ 33411099Ssam mtpr r0,$TXDB 33511099Ssam rsb 33611099Ssam 33713194Shelge /* 33813194Shelge * Convert the filename given from the console 33913194Shelge * to radix 50 (rt-11) format. 34013194Shelge */ 34113194Shelge rad50: 34213210Shelge clrw r1 34313194Shelge bsbb getb50 /* get next ascii byte, exit if null */ 34413194Shelge mull3 $03100,r0,r1 34513194Shelge bsbb getb50 34613194Shelge mull3 $050,r0,r2 34713194Shelge addl2 r2,r1 34813194Shelge bsbb getb50 34913194Shelge addl2 r0,r1 /* last byte, just add it in */ 35013194Shelge movw r1,(r5)+ /* save result */ 35113210Shelge brb rad50 35213194Shelge 35313194Shelge getb50: 35413194Shelge movzbl (r4)+,r0 /* get next ascii byte */ 35513194Shelge beql 1f /* if zero: end of string */ 35613210Shelge movzbl CTABLE(r0),r0 /* and get the r50 byte from the table*/ 35713194Shelge rsb 35813194Shelge 1: 35913194Shelge tstl (sp)+ /* we're through, get back to where */ 36013194Shelge /* rad50 was called */ 36113194Shelge movw r1,(r5) /* but first save the result */ 36213194Shelge rsb 36313194Shelge 36411099Ssam .align 2 36511099Ssam readcom: 36613194Shelge .byte 2 /* command packet flag */ 36713194Shelge .byte 10 /* number of bytes in message */ 36813194Shelge .byte 2 /* tu read opcode */ 36913194Shelge .byte 0 /* modifier */ 37013194Shelge .byte 0 /* unit number */ 37113194Shelge .byte 0 /* switches */ 37213194Shelge .word 0 /* sequence number */ 37313194Shelge /* byte count and block number follow */ 37411099Ssam 37511099Ssam ermsg: 37614312Ssam .asciz "tuerr\r\n" 37711099Ssam end: 37813237Shelge 37913237Shelge /* 38013237Shelge * Ascii to rad 50 conversion table, 38113237Shelge * stored on the second block on the cassette 38213237Shelge * 38313237Shelge * NOTE: Always make sure this table ends up 38413237Shelge * starting at byte 512!!!! 38513237Shelge */ 38613237Shelge .align 2 38713237Shelge .data 2 38813237Shelge .long 0x1d1d1d1d 38913237Shelge .long 0x1d1d1d1d 39013237Shelge .long 0x1d1d1d1d 39113237Shelge .long 0x1d1d1d1d 39213237Shelge .long 0x1d1d1d1d 39313237Shelge .long 0x1d1d1d1d 39413237Shelge .long 0x1d1d1d1d 39513237Shelge .long 0x1d1d1d1d 39613237Shelge .long 0x1d1d1d00 39713237Shelge .long 0x1d1d1d1b 39813237Shelge .long 0x1d1d1d1d 39913237Shelge .long 0x1d1c1d1d 40013237Shelge .long 0x21201f1e 40113237Shelge .long 0x25242322 40213237Shelge .long 0x1d1d2726 40313237Shelge .long 0x1d1d1d1d 40413237Shelge .long 0x302011d 40513237Shelge .long 0x7060504 40613237Shelge .long 0xb0a0908 40713237Shelge .long 0xf0e0d0c 40813237Shelge .long 0x13121110 40913237Shelge .long 0x17161514 41013237Shelge .long 0x1d1a1918 41113237Shelge .long 0x1d1d1d1d 41213237Shelge .long 0x302011d 41313237Shelge .long 0x7060504 41413237Shelge .long 0xb0a0908 41513237Shelge .long 0xf0e0d0c 41613237Shelge .long 0x13121110 41713237Shelge .long 0x17161514 41813237Shelge .long 0x1d1a1918 41913237Shelge .long 0x1d1d1d1d 42013237Shelge .long 0x1d1d1d1d 42113237Shelge .long 0x1d1d1d1d 42213237Shelge .long 0x1d1d1d1d 42313237Shelge .long 0x1d1d1d1d 42413237Shelge .long 0x1d1d1d1d 42513237Shelge .long 0x1d1d1d1d 42613237Shelge .long 0x1d1d1d1d 42713237Shelge .long 0x1d1d1d1d 42813237Shelge .long 0x1d1d1d00 42913237Shelge .long 0x1d1d1d1b 43013237Shelge .long 0x1d1d1d1d 43113237Shelge .long 0x1d1c1d1d 43213237Shelge .long 0x21201f1e 43313237Shelge .long 0x25242322 43413237Shelge .long 0x1d1d2726 43513237Shelge .long 0x1d1d1d1d 43613237Shelge .long 0x302011d 43713237Shelge .long 0x7060504 43813237Shelge .long 0xb0a0908 43913237Shelge .long 0xf0e0d0c 44013237Shelge .long 0x13121110 44113237Shelge .long 0x17161514 44213237Shelge .long 0x1d1a1918 44313237Shelge .long 0x1d1d1d1d 44413237Shelge .long 0x302011d 44513237Shelge .long 0x7060504 44613237Shelge .long 0xb0a0908 44713237Shelge .long 0xf0e0d0c 44813237Shelge .long 0x13121110 44913237Shelge .long 0x17161514 45013237Shelge .long 0x1d1a1918 45113237Shelge .long 0x1d1d1d 45213237Shelge .data 453