+#
+# RP06/RM03 disk boot program to load "/fboot" from
+# a UNIX filesystem (starting at block 1 on pack on
+# drive 0) into low core and to execute that file.
+# This program can only read regular small version 7 files
+# from the root of a UNIX filesystem.
+#
+#
+ .set BLKSIZ,512 # disc block size
+ .set RELOC,0x50000
+ .set HDRSIZ,040 # size of file header for VAX
+ .set MAGIC,0410 # file type id in header
+ .set INOSIZ,64 # no. bytes/inode entry
+ .set INOBLK,BLKSIZ/INOSIZ # no. inodes/disc block
+ .set INOMSK,0xfffffff8 # changes with inode size
+ .set NAMSIZ,14 # no. bytes in name field of dir entry
+ .set ENTADR,024 # offset to entry addr in task header
+ .set DIRSIZ,16 # size of directory entry, bytes
+ .set ROOTINO,2 # root dir inode no.
+ .set NBOO,1
+ .set NSUP,1
+ .set NL,012 # new-line char
+ .set CR,015 # carriage-return char
+ .set SLASH,057 # '/'
+ .set NMASK,0177
+ .set NNMASK,037777777600 # ~NMASK
+# MBA registers
+ .set MBA0,0x20010000 # MBA 0 device reg's
+ .set M_cr,MBA0+4 # MBA control reg
+ .set M_var,MBA0+12 # MBA virt addr reg
+ .set M_bc,MBA0+16 # MBA byte count reg
+ .set M_map,MBA0+0x800 # start of MBA map reg's
+ .set MBAinit,1 # MBA init bit in MBA control reg
+#
+# RM03
+ .set RM3SEC,32
+ .set RM3TRK,5
+#
+ .set RP6typ,022
+ .set RM3typ,024
+#
+# RP06 registers
+ .set RP6TRK,19 # no. tracks/cylinder
+ .set RP6SEC,22 # no. sectors/track
+ .set RP,MBA0+0x400 # start of RP06 drive 0 reg's
+ .set RP_cr,RP+0 # RP06 control reg, drive 0
+ .set RP_sr,RP+4 # status reg
+ .set RP_stk,RP+0x14 # desired track/sector reg
+ .set RP_dt,RP+0x18 # drive type reg
+ .set RP_off,RP+0x24 # RP offset reg
+ .set RP_cyl,RP+0x28 # desired cyl reg
+# RP06 function codes, status bits
+ .set RP_GO,1 # GO bit
+ .set RP_RED,070 # read data
+ .set RP_DC,010 # drive clear function code
+ .set RP_RIP,020 # Read-In Preset function code
+ .set RP_FMT,0x1000 # format bit for offset reg
+ .set RP_MOL,0x1000 # medium online in status reg
+ .set RP_DRY,0200 # drive ready, staus reg
+ .set RP_ERR,040000 # composite error, staus reg
+ .set RP_pDRY,7 # bit position of RP_DRY
+ .set RP_pERR,14 # bit position of RP_ERR
+#
+#
+init :
+# system initialization - executed once per boot load
+ halt # entry mask required by DEC monitor software
+ halt
+ movl $MBAinit,*$M_cr # MBA initialize
+ movl $RP_RIP+RP_GO,*$RP_cr # read-in preset
+ movl $RP_FMT,*$RP_off # format bit in RP offset reg
+#
+ movl *$RP_dt,r0
+ cmpb $RP6typ,r0
+ bneq rm3
+ movl $RP6SEC,*$rpsec
+ movl $RP6TRK,*$rptrk
+ brb domul
+rm3:
+ movl $RM3SEC,*$rpsec
+ movl $RM3TRK,*$rptrk
+domul:
+ mull3 *$rpsec,*$rptrk,*$rpst
+# move boot image up to higher core
+start :
+ movl $RELOC,sp
+# 'uboot' must have no header
+ movc3 $end,*$0,(sp) # move boot to relocated position
+#
+# jump to re-located code at 'start2' - done once per boot load
+ jmp *$RELOC+start2
+#
+# execution starts here only after boot has been re-located
+start2 :
+#
+# search inodes for pathname specified in 'names'
+#
+# Must preserve r6 & r7
+# 'cmpc[35]' instruction uses reg's 0 - 3
+# 'movc[35]' instruction uses reg's 0-5
+ movl $names+RELOC,r6 # start of input filename
+ movzbl $ROOTINO,r0 # start at root inode for search
+nxti :
+ clrw *$bno # 'bno' is index into 'iaddr[]' in inode entry
+ bsbw iget # get inode into core
+ tstb (r6) # r6 -> empty pathname component if end of pathname
+ beql getfil
+get1b :
+ bsbw rmblk # read in 1 of blocks in 'addr[]' in inode entry
+ beql start2 # file not found if zero cc set
+#
+ movl $buf,r7 # buffer holds directory block
+nxtent :
+ tstw (r7) # null dir entry (inode # field = 0)
+ beql dirchk
+ cmpc3 $NAMSIZ,(r6),2(r7) # compare 'names' against
+# dir entry - both null-filled
+ bneq dirchk # branch if dir entry is not the one
+# found component in a dir entry
+ movzwl (r7),r0 # 2-byte inode no. from 1st 2 bytes of dir entry
+ addl2 $NAMSIZ,r6 # point to next pathname component in 'names[]'
+ brb nxti # now go get inode whose no. is in r0
+#
+dirchk : # no pathname match
+ acbl $buf+BLKSIZ-1,$DIRSIZ,r7,nxtent # loop if
+# more dir entries in this buffer
+ brb get1b # get another dir block into buffer
+#
+# here if inode for desired file has been read in
+getfil :
+ clrl bufptr # new buffer ptr is low core
+getlop :
+ bsbb rmblk # get a block in the file
+ beql clear # branch if no more file blocks to read
+# skip above branch if more file blocks to read in
+ addl2 $BLKSIZ,bufptr # next page in low core
+ brb getlop # go get next block of input file
+#
+# clear core
+#
+clear :
+ movl *$size,r3
+clrcor :
+ clrq (r3)
+ acbl $RELOC,$8,r3,clrcor
+#
+# go execute file
+#
+ calls $0,*$0
+ brw start2
+#
+#
+# subroutine to get the inode whose no. is in r0
+#
+iget :
+ addl3 $(INOBLK*(NBOO+NSUP))-1,r0,r8 # have to add in 2 blocks (boot and super)
+# worth of dummy inodes to calculate proper inode block
+ divl3 $INOBLK,r8,r4 # calculate inode block , put in r4
+ bsbw rblk # read in block containing desired inode
+ bicl2 $INOMSK,r8
+ mull2 $INOSIZ,r8 # x inode size = offset in block
+ addl2 $buf,r8 # buffer loc of inode entry
+# move inode entry to separate buffer
+ movc3 $time-inode,(r8),*$inode
+ rsb
+#
+# subr to read in 1 of blocks (bno) in 'addr[]'
+#
+rmblk :
+ movzwl *$bno,r0
+ addw2 $3,*$bno # index into 'addr[]' array in inode entry
+ addl2 $addr,r0
+# this boot assumes only small files(<11 blocks)
+ extzv $0,$24,(r0),r4 # get low 2 bytes of block no. -> r4
+ bneq rblk # read in block if non-zero
+# zero cc is set on return
+ rsb
+#
+# subr to read disc block no. specified in r4 from RP06, drive 0
+#
+rblk :
+ clrl r5
+ ediv *$rpst,r4,*$RP_cyl,r1
+# (r4 = block no.)/(no. blocks per cyl) -> cyl no.
+# r1 = remainder = block offset with in cylinder
+ clrl r2
+ ediv *$rpsec,r1,r1,r0
+# r1 = track no. ; ; sector no. in low part RP_stk
+ insv r1,$8,$5,r0 # move track no. into RP_stk
+ movl r0,*$RP_stk # track-sector
+ movl $-BLKSIZ,*$M_bc # byte count
+ ashl $-9,bufptr,r0 # start page no. of buffer
+ bisl3 $0x80000000,r0,*$M_map # MBA map reg =
+# valid bit + phys page no.
+ clrl *$M_var # buffer has been 512-byte aligned + map reg 0
+ movl $RP_RED+RP_GO,*$RP_cr # disc read function code
+rprdy :
+ movl *$RP_sr,r0
+ bbc $RP_pDRY,r0,rprdy # loop unitl ready
+ bbs $RP_pERR,r0,rperr # branch if error
+ bicpsw $2 # set zero cc for caller success
+ rsb # normal return
+ rperr : # disc i/o error
+ halt # halt on error
+#
+#
+bufptr : .long buf
+names :
+ .byte 'f,'b,'o,'o,'t,0,0,0,0,0,0,0,0,0
+ .byte 0
+#
+end:
+#
+ .set buf,RELOC-1024
+ .set inode,RELOC-512
+ .set mode,inode
+ .set nlink,mode+2
+ .set uid,nlink+2
+ .set gid,uid+2
+ .set size,gid+2
+ .set addr,size+4
+ .set time,addr+40
+ .set bno,time+12
+ .set rptrk,bno+4
+ .set rpsec,rptrk+4
+ .set rpst,rpsec+4