| 1 | # |
| 2 | # RP06/RM03 disk boot program to load "/boot" from |
| 3 | # a UNIX filesystem (starting at block 1 on pack on |
| 4 | # drive 0) into low core and to execute that file. |
| 5 | # This program can only read regular small version 7 files |
| 6 | # from the root of a UNIX filesystem. |
| 7 | # |
| 8 | # |
| 9 | .set BLKSIZ,1024 # disc block size |
| 10 | .set RELOC,0x50000 |
| 11 | .set HDRSIZ,040 |
| 12 | .set INOSIZ,64 # no. bytes/inode entry |
| 13 | .set INOBLK,BLKSIZ/INOSIZ # no. inodes/disc block |
| 14 | .set INOMSK,0xfffffff0 # changes with inode size |
| 15 | .set NAMSIZ,14 # no. bytes in name field of dir entry |
| 16 | .set ENTADR,024 # offset to entry addr in task header |
| 17 | .set DIRSIZ,16 # size of directory entry, bytes |
| 18 | .set ROOTINO,2 # root dir inode no. |
| 19 | .set NBOO,1 |
| 20 | .set NSUP,1 |
| 21 | .set SLASH,057 # '/' |
| 22 | # MBA registers |
| 23 | .set MBA0,0x20010000 # MBA 0 device reg's |
| 24 | .set M_cr,MBA0+4 # MBA control reg |
| 25 | .set M_var,MBA0+12 # MBA virt addr reg |
| 26 | .set M_bc,MBA0+16 # MBA byte count reg |
| 27 | .set M_map,MBA0+0x800 # start of MBA map reg's |
| 28 | .set MBAinit,1 # MBA init bit in MBA control reg |
| 29 | # |
| 30 | .set RM3SEC,32 |
| 31 | .set RM3TRK,5 |
| 32 | .set RP6typ,022 |
| 33 | .set RM3typ,024 |
| 34 | # |
| 35 | .set RP6TRK,19 |
| 36 | .set RP6SEC,22 |
| 37 | .set RP,MBA0+0x400 # start of RP06 drive 0 reg's |
| 38 | .set RP_cr,RP+0 # RP06 control reg, drive 0 |
| 39 | .set RP_sr,RP+4 # status reg |
| 40 | .set RP_stk,RP+0x14 # desired track/sector reg |
| 41 | .set RP_dt,RP+0x18 # drive type reg |
| 42 | .set RP_off,RP+0x24 # RP offset reg |
| 43 | .set RP_cyl,RP+0x28 # desired cyl reg |
| 44 | # RP06 function codes, status bits |
| 45 | .set RP_GO,1 # GO bit |
| 46 | .set RP_RED,070 # read data |
| 47 | .set RP_DC,010 # drive clear function code |
| 48 | .set RP_RIP,020 # Read-In Preset function code |
| 49 | .set RP_FMT,0x1000 # format bit for offset reg |
| 50 | .set RP_MOL,0x1000 # medium online in status reg |
| 51 | .set RP_DRY,0200 # drive ready, staus reg |
| 52 | .set RP_ERR,040000 # composite error, staus reg |
| 53 | .set RP_pDRY,7 # bit position of RP_DRY |
| 54 | .set RP_pERR,14 # bit position of RP_ERR |
| 55 | # |
| 56 | # |
| 57 | init : |
| 58 | # system initialization - executed once per boot load |
| 59 | halt # entry mask required by DEC monitor software |
| 60 | halt |
| 61 | movl $MBAinit,*$M_cr # MBA initialize |
| 62 | movl $RP_RIP+RP_GO,*$RP_cr # read-in preset |
| 63 | movl $RP_FMT,*$RP_off # format bit in RP offset reg |
| 64 | # |
| 65 | movl *$RP_dt,r0 |
| 66 | cmpb $RP6typ,r0 |
| 67 | bneq rm3 |
| 68 | movl $RP6SEC,*$rpsec |
| 69 | movl $RP6TRK,*$rptrk |
| 70 | brb domul |
| 71 | rm3: |
| 72 | movl $RM3SEC,*$rpsec |
| 73 | movl $RM3TRK,*$rptrk |
| 74 | domul: |
| 75 | mull3 *$rpsec,*$rptrk,*$rpst |
| 76 | # move boot image up to higher core |
| 77 | start : |
| 78 | movl $RELOC,sp |
| 79 | # 'uboot' must have no header |
| 80 | movc3 $end,*$0,(sp) # move boot to relocated position |
| 81 | # |
| 82 | # jump to re-located code at 'start2' - done once per boot load |
| 83 | jmp *$RELOC+start2 |
| 84 | # |
| 85 | # execution starts here only after boot has been re-located |
| 86 | start2 : |
| 87 | # |
| 88 | # search inodes for pathname specified in 'names' |
| 89 | # |
| 90 | # Must preserve r6 & r7 |
| 91 | # 'cmpc[35]' instruction uses reg's 0 - 3 |
| 92 | # 'movc[35]' instruction uses reg's 0-5 |
| 93 | movl $names+RELOC,r6 # start of input filename |
| 94 | movzbl $ROOTINO,r0 # start at root inode for search |
| 95 | nxti : |
| 96 | clrw *$bno # 'bno' is index into 'iaddr[]' in inode entry |
| 97 | bsbw iget # get inode into core |
| 98 | tstb (r6) # r6 -> empty pathname component if end of pathname |
| 99 | beql getfil |
| 100 | get1b : |
| 101 | bsbw rmblk # read in 1 of blocks in 'addr[]' in inode entry |
| 102 | beql start2 # file not found if zero cc set |
| 103 | # |
| 104 | movl $buf,r7 # buffer holds directory block |
| 105 | nxtent : |
| 106 | tstw (r7) # null dir entry (inode # field = 0) |
| 107 | beql dirchk |
| 108 | cmpc3 $NAMSIZ,(r6),2(r7) # compare 'names' against |
| 109 | # dir entry - both null-filled |
| 110 | bneq dirchk # branch if dir entry is not the one |
| 111 | # found component in a dir entry |
| 112 | movzwl (r7),r0 # 2-byte inode no. from 1st 2 bytes of dir entry |
| 113 | addl2 $NAMSIZ,r6 # point to next pathname component in 'names[]' |
| 114 | brb nxti # now go get inode whose no. is in r0 |
| 115 | # |
| 116 | dirchk : # no pathname match |
| 117 | acbl $buf+BLKSIZ-1,$DIRSIZ,r7,nxtent # loop if |
| 118 | # more dir entries in this buffer |
| 119 | brb get1b # get another dir block into buffer |
| 120 | # |
| 121 | # here if inode for desired file has been read in |
| 122 | getfil : |
| 123 | clrl bufptr # new buffer ptr is low core |
| 124 | getlop : |
| 125 | bsbb rmblk # get a block in the file |
| 126 | beql clear # branch if no more file blocks to read |
| 127 | # skip above branch if more file blocks to read in |
| 128 | addl2 $BLKSIZ,bufptr # next page in low core |
| 129 | brb getlop # go get next block of input file |
| 130 | # |
| 131 | # clear core |
| 132 | # |
| 133 | clear : |
| 134 | movl *$size,r3 |
| 135 | clrcor : |
| 136 | clrq (r3) |
| 137 | acbl $RELOC,$8,r3,clrcor |
| 138 | # |
| 139 | # go execute file |
| 140 | # |
| 141 | calls $0,*$0 |
| 142 | brw start2 |
| 143 | # |
| 144 | # |
| 145 | # subroutine to get the inode whose no. is in r0 |
| 146 | # |
| 147 | iget : |
| 148 | addl3 $(INOBLK*(NBOO+NSUP))-1,r0,r8 # have to add in 2 blocks (boot and super) |
| 149 | # worth of dummy inodes to calculate proper inode block |
| 150 | divl3 $INOBLK,r8,r4 # calculate inode block , put in r4 |
| 151 | bsbw rblk # read in block containing desired inode |
| 152 | bicl2 $INOMSK,r8 |
| 153 | mull2 $INOSIZ,r8 # x inode size = offset in block |
| 154 | addl2 $buf,r8 # buffer loc of inode entry |
| 155 | # move inode entry to separate buffer |
| 156 | movc3 $time-inode,(r8),*$inode |
| 157 | rsb |
| 158 | # |
| 159 | # subr to read in 1 of blocks (bno) in 'addr[]' |
| 160 | # |
| 161 | rmblk : |
| 162 | movzwl *$bno,r0 |
| 163 | addw2 $3,*$bno # index into 'addr[]' array in inode entry |
| 164 | addl2 $addr,r0 |
| 165 | # this boot assumes only small files(<11 blocks) |
| 166 | extzv $0,$24,(r0),r4 # get low 2 bytes of block no. -> r4 |
| 167 | bneq rblk # read in block if non-zero |
| 168 | # zero cc is set on return |
| 169 | rsb |
| 170 | # |
| 171 | # subr to read disc block no. specified in r4 from RP06, drive 0 |
| 172 | # |
| 173 | rblk : |
| 174 | mull2 $BLKSIZ/512,r4 |
| 175 | clrl r5 |
| 176 | ediv *$rpst,r4,*$RP_cyl,r1 |
| 177 | # (r4 = block no.)/(no. blocks per cyl) -> cyl no. |
| 178 | # r1 = remainder = block offset with in cylinder |
| 179 | clrl r2 |
| 180 | ediv *$rpsec,r1,r1,r0 |
| 181 | # r1 = track no. ; ; sector no. in low part RP_stk |
| 182 | insv r1,$8,$5,r0 # move track no. into RP_stk |
| 183 | movl r0,*$RP_stk # track-sector |
| 184 | movl $-BLKSIZ,*$M_bc # byte count |
| 185 | ashl $-9,bufptr,r0 # start page no. of buffer |
| 186 | bisl3 $0x80000000,r0,*$M_map # MBA map reg = |
| 187 | # valid bit + phys page no. |
| 188 | incl r0 |
| 189 | bisl3 $0x80000000,r0,*$(M_map+4) |
| 190 | clrl *$M_var # buffer has been 512-byte aligned + map reg 0 |
| 191 | movl $RP_RED+RP_GO,*$RP_cr # disc read function code |
| 192 | rprdy : |
| 193 | movl *$RP_sr,r0 |
| 194 | bbc $RP_pDRY,r0,rprdy # loop unitl ready |
| 195 | bbs $RP_pERR,r0,rperr # branch if error |
| 196 | bicpsw $2 # set zero cc for caller success |
| 197 | rsb # normal return |
| 198 | rperr : # disc i/o error |
| 199 | halt # halt on error |
| 200 | # |
| 201 | # |
| 202 | bufptr : .long buf |
| 203 | names : |
| 204 | .byte 'b,'o,'o,'t,0,0,0,0,0,0,0,0,0,0 |
| 205 | .byte 0 |
| 206 | # |
| 207 | end: |
| 208 | # |
| 209 | .set buf,RELOC-1536 |
| 210 | .set inode,RELOC-512 |
| 211 | .set mode,inode |
| 212 | .set nlink,mode+2 |
| 213 | .set uid,nlink+2 |
| 214 | .set gid,uid+2 |
| 215 | .set size,gid+2 |
| 216 | .set addr,size+4 |
| 217 | .set time,addr+40 |
| 218 | .set bno,time+12 |
| 219 | .set rptrk,bno+4 |
| 220 | .set rpsec,rptrk+4 |
| 221 | .set rpst,rpsec+4 |