BSD 3 development
[unix-history] / usr / mdec / uboot.s
#
# RP06/RM03 disk boot program to load "/boot" 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,1024 # disc block size
.set RELOC,0x50000
.set HDRSIZ,040
.set INOSIZ,64 # no. bytes/inode entry
.set INOBLK,BLKSIZ/INOSIZ # no. inodes/disc block
.set INOMSK,0xfffffff0 # 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 SLASH,057 # '/'
# 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
#
.set RM3SEC,32
.set RM3TRK,5
.set RP6typ,022
.set RM3typ,024
#
.set RP6TRK,19
.set RP6SEC,22
.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 :
mull2 $BLKSIZ/512,r4
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.
incl r0
bisl3 $0x80000000,r0,*$(M_map+4)
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 'b,'o,'o,'t,0,0,0,0,0,0,0,0,0,0
.byte 0
#
end:
#
.set buf,RELOC-1536
.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