; file : sboot.40.2.text ; last modified: 12/08/83 ; ; this section of code contains the main boot code that asks for the user name and ; password, and then loads the o.s. page ; ; print the CORVUS CONSTELLATION II banner ; c2main0 tst.b CPextcrt.w ;*4.0 if external crt then bne.s c2main0a ;*4.0 don't init drivers move.w #$2500, sr ;turn on keyboard *4.0 c2main0a ; interrupts *4.0 bsr c2greet ;dump greeting msg lea homesrv,a4 ;save the responding boot server move.b bootsrv,(a4) ; ; get corvus volume information for primary drive ; C2restr lea bootsrv,a4 ;reinitialize boot server (needed for errors) move.b homesrv,(a4) clr.l $780.w ;clear password save area to zeros *3.6 clr.l $784.w ; indicates no password, ie device *3.6 moveq #1,d0 ;lets read the corvus volume info from drive 1 move.b bootsrv,d1 ;get disk server station address lea c2DUlen,a1 ;ptr to corvus volume control block bsr c2CVinf ;get corvus volume info from DRIVE.INFO block beq.s c2main1 ;got it, continue *3.6 tst.w d7 ;if d7=$FFFFFFFF then invalid table *3.6 bpl start ;else read error, restart boot sequence moveq #er24,d0 ;d0 <= contains error code invalid tbl *4.0 bsr c2erprt ;write error message *4.0 moveq #-1,d0 ;wait a little in case competing *4.0 c2r10a dbra d0, c2r10a ; for disk and using 0.6 boot roms *4.0 bra.s c2restr ;restart *4.0 ; ; check for a device boot instead of a user boot ; c2main1 bsr c2devboot ;will find user and server name if device *4.0 beq.s c2mn1a1 ;no error *4.0 moveq #er25,d0 ;d0 <= contains error code *4.0 bsr c2erprt ;write error message *4.0 bra.s c2restr ;restart *4.0 c2mn1a1 tst.w d0 ;is this a user or device boot? *4.0 bne.s c2m1 ;device boot *4.0 ; ; prompt operator for user name ; c2mn1a lea c2nmbuf,a0 ;get address of user name buffer bsr c2getnm ;prompt oerator for user name ; lea c2nmbuf,a1 ;get address of user name buffer lea mtchitm,a0 ;a0 <= address to store matched Network.User entry clr.l d7 ; bsr c2vernm ;search network.user table for entry match tst.w d7 ;does the user exist on this network beq.s c2main2 ;YES - Continue moveq #er11,d0 ;d0 <= contains error code (User not found) bsr c2erprt ;write error message bra.s c2main1 ;reprompt user for user name ; ; prompt operator for user password ; c2main2 lea c2pwbuf,a0 ;a0 <= address of user password buffer bsr c2getpw ;get user password (encrypts it) lea mtchitm+NUusrpw,a0 ;a0 <= address of password from tables lea c2pwbuf,a1 ;a1 <= address of password entered bsr c2verpw ;check for password match tst.w d7 ;passwords match beq.s c2m0 ;password match move.l d7,d0 ;d0 <= contains error code for c2erptr bsr c2erprt ;write error message bra c2main1 ;reprompt user for user name c2m0 moveq #pswlen-1, d0 ;length of password - 1 *3.6 lea $780.w, a0 ;where to save password *3.6 lea c2pwbuf,a1 ;encrypted password from C2getpw *3.6 c2m0a move.b (a1)+, (a0)+ ;move it *3.6 dbra d0, c2m0a ; *3.6 ; ; determine if booting from omninet or booting from the flat ; cable. If booting from the flat cable, the boot slot must not ; be slot 5. ; C2m1 move.b bootslt,d0 cmpi.b #5,d0 ;is the omninet the boot slot bne C2main3 ;branch if the flat cable is used ; ; For Omninet boot, once we have the user name and password, we have to find ; the user's boot system. This is done by broadcasting a "Where are you?" ; message, asking for the designated server. If one is not found, an error ; is generated, and the user is reprompted for the user name. ; C2m11 lea Data_area,a1 ;initialize pointer to data area moveq #4,D1 ;set loop count for number of tries *3.6 bsr EndRecv ;make sure socket is clear tst.w D0 ;check for errors bne.s omnierror bsr SetupRecv ;set up receive for My Id is ... tst.w D0 ;check for errors bne.s omnierror C2m12 bsr Sendit ;send the Where are you? tst.w D0 ; check for errors bne.s omnierror C2m12a move.w #32000,d3 ;*3.6 C2m13 tst.b RHdr(A1) ;check if result is received beq.s C2mOk ;yes... dbra D3,C2m13 ;wait some more dbra D1,C2m12 ;timeout ... try again bra c2main3 ;no reply, so just boot from the responding disk server C2mOK cmpi.w #$1FE,C2x_proto(A1);correct PID? *4.0 bne.s C2wrong ;no, setup recv again and wait *4.0 cmpi.w #$1000,C2x_msgtype(A1) ;right msg type? *3.6 bne.s C2wrong ;no, setup recv again and wait *3.6 cmpi.w #1,C2x_devtype(A1);from right device? *3.6 beq.s C2mOK10 ;yes, get drive.info from drive*3.6 cmpi.w #6,C2x_devtype(A1);from omnidrive? *3.8 beq.s C2mOK10 ;yes, get drive.info from drive*3.8 C2wrong bsr SetupRecv ;wrong msg, setup recv again *3.6 tst.w d0 ;get error? *3.6 bne.s omnierror ;yes *3.6 bra.s C2m12a ;no, wait for right msg *3.6 C2mOK10 lea bootsrv,A0 ;get ready to store new bootsrv number move.b Source(A1),(A0) ;store it ; reinitialize C2CVinfo moveq #1,d0 ;drive is 1 move.b bootsrv,d1 ;set server number lea c2DUlen,a1 ;ptr to corvus volume control block bsr c2CVinf ;get corvus volume info from DRIVE.INFO block beq.s c2main3 ;got it, so continue with boot ;drive.info error moveq #er24,d0 ;assume invalid drive.info *3.6 tst.w D7 ; *3.6 bmi.s c2wrermsg ;invalid drive.info table *3.6 moveq #er15,d0 ;report error code -- *3.6 bra.s c2wrermsg ; disk server not responding *3.6 omnierror moveq #er16,d0 ;any omninet error (timeout, no transporter, etc.) c2wrermsg bsr c2erprt ;write error message *3.6 bra c2restr ;reprompt for user name *3.6 ; ; determine no. of drives on current cluster ; c2main3 moveq #Drmax,d0 ;d0 <= maximum no. of drives to look for lea bootsrv,a0 ;d1 <= boot server station number move.b (a0),d1 ; bsr c2chkdr ;check the number of drives on network lea c2totdr,a1 ; move.w d0,(a1) ;store maximum drive count ; ; determine if user boot volume is on this drive ; c2main4 move.l d0,d5 ;d5 <= maximum no. of drives subq.l #1,d5 ;substract one because of DBRA instruction moveq #1,d0 ;start with drive 1 c2main5 lea bootsrv,a1 move.b (a1),d1 lea c2nmbuf,a1 ;get address of user name buffer lea mtchitm,a0 ;a0 <= address to store matched Drive.User entry bsr c2verdu ;search Drive.User table for entry match tst.w d7 ;does user have access to volumes on this drive bne.s c2main7 ;no, try again ; ; found drive for which user has access ; determine if user has any volumes mounted on drive ; determine if this is the user boot volume ; c2main6 lea mtchitm,a5 ; tst.w DUmtcnt(a5) ;test no. of volumes user has mounted on drive beq c2main7 ;if equal zero, user has no volumes tst.w DUbtflg(a5) ;test boot flag in DRIVE.USER entry beq c2main7 ;this is not the BOOT volume drive ; ; ; the DRIVE.USER entry indicates that this drive contains ; the user's boot volume.... ; ; move.w DUusrid(a5),CpUserid.w ;save user DRIVE.USER id lea c2curdr,a0 ; move.w d0,(a0) ;store current boot drive ; ; find the DRIVE.ACCESS table entry for this user's ; boot volume. This entry will indicate the starting disk ; block address of the boot volume... ; lea bootsrv,a0 move.b (a0),d1 ;D1 <= pass disk server station no. move.w DUusrId(a5),a1 ;A1 <= pass drive.user id lea mtchitm,a0 ;A0 <= pass address of DRIVE.ACCESS ;entry located as boot volume entry ;D0 <= pass drive number bsr c2verDa ;find starting block of volume tst.w d7 ;test find boot volume return code beq.s C2main8 ;boot volume found ; ; ; loop through each drive on this network until the ; no. of drives is exhausted. when this number is ; exhausted, print error message, and reprompt user. ; ; c2main7 addq #1,d0 ;increment current drive number dbra d5,c2m7 ;no more drives??? moveq #er14,d0 ;write no user boot volume error message bsr c2erprt ; bra c2restr ;reprompt user for user name c2m7 move.b bootsrv,d1 ;read DRIVE.INFO from next drive lea c2DUlen,a1 bsr C2CVinf ;*3.6 checks for invaild drive.info bne.s C2main7 ;uninitialized drive, go on to next 1 bra C2main5 ;look for boot volume on new drive ; ; ; YES WE HAVE BANANAS. The boot volume has been located. ; ; c2main8 lea bootdrv,a1 ;store computer boot drive no. in local storage move.b d0,(a1) ;boot drive is in register D0 lea mtchitm,a1 ;get address of DRIVE.ACCESS entry lea bootblk,a2 ; move.l DAvolad(a1),(a2);store boot volume lea bootdev,a2 ; move.b DAmtdev(a1),(a2);store boot volume unit number ; ; ; copy user logon name ; ; move.l #CPusernm,a0 ;get address of location of user name lea c2nmbuf,a1 ;get address of user name entered by operator c2main9 move.l (a1)+,(a0)+ ;copy buffer from boot area to OS area move.l (a1)+,(a0)+ ; move.w (a1),(a0) ; ; ; ; read the operating system into memory. ; ; c2mainA lea DirBuf,a0 ;Get pointer to buffer move.l bootblk,d0 ;Get directory block number addq #2,d0 ;* move.w #2048,d2 ;Get directory length bsr DskRd ;Read directory beq.s c2mainB ;good read move.w #er20,d0 ;err, output error message bsr c2erprt ; bra c2restr ;get new user name ; c2mainB lea DirBuf,a3 ;Get pointer to buffer move.w 2(a3),d4 ;Set flipped directory flag lsr.w #8,d4 ;* moveq #0, d0 ;zero out d0 move.w 16(a3),d0 ;d0 = number of files tst.w d4 ;Is directory flipped? beq.s c2mainD ;No, check first file rol.w #8,d0 ;Unflip number of files bra.s c2mainD ;Check first file ; c2mainC adda.w #26,a3 ;Advance a3 to next entry lea 6(a3),a0 ;(a0) = file name cmpi.l #$0943432E,(a0)+;'\09CC.' bne.s c2mainD ; cmpi.l #$4B45524E,(a0)+;'KERN' bne.s c2mainD ; cmpi.w #$454C,(a0)+ ;'EL' beq.s c2mainE ; ; c2mainD dbra d0,c2mainC ;More files? move.w #er21,d0 ;no, can't find bsr c2erprt ; cc.kernel bra c2restr ; ; Found the file CC.KERNEL. Read the first block to see if it is ; a quick-load file, and if so, how big it is. ; c2mainE lea OSBuf,a0 ;Get pointer to buffer move.w (a3),d0 ;Get block number tst.w d4 ;Is directory flipped? beq.s c2mainI ;No, read first part of file rol.w #8,d0 ;Unflip block number ; c2mainI add.l bootblk,d0 ;Get absolute block number moveq #16,d2 ;Get number of bytes to read bsr DskRd ;Read first part of file beq.s c2mainF ;read was successful ; move.w #er22,d0 ;error reading CC.KERNEL file bsr c2erprt ; bra c2restr ;new new user name ; c2mainF lea OSBuf,a4 ;Get pointer to buffer cmpi.b #$8e,(a4)+ ;Is it a quick-file? beq.s c2mainH ;YES move.w #er23,d0 ;print not a quick file error message bsr c2erprt ; bra c2restr ;get a new user name c2mainH clr.l d2 ;d2 = size *4.0 move.b (a4)+, d2 ;size is next 3 bytes (hi) *4.0 swap d2 ;put hi byte in hi word *4.0 move.w (a4)+,d2 ;(mid,lo) in low word *4.0 move.l (a4)+,d6 ;d6 = relative starting address move.l (a4)+,d5 ;d5 = unit global data size move.l HICODE,d1 ;d1 = top of memory sub.l d2,d1 ;d1 = location to load CC.KERNEL move.l d1,a0 ; move.l d1,-(sp) ;Save highest free memory add.l d1,d6 ; add.l #12,d6 ;d6 = absolute starting address moveq #0, d0 ;zero out upper bits move.w (a3),d0 ;Get block number tst.w d4 ;Is directory flipped? beq.s c2mainJ ;No, read OS into memory rol.w #8,d0 ;Unflip block number ; c2mainJ add.l bootblk,d0 ;Get absolute block number bsr DskRd ;Read CC.KERNEL into memory beq.s c2mainK ;YES read successful? move.w #er22,d0 ;NO, output message bsr c2erprt ; bra c2restr ;get new user name page ; ;everything is set -- issue the logon command ; -- if this is omninet boot ; c2mainK move.b bootslt,d0 ; *4.0 cmpi.b #5,d0 ;is the omninet the boot slot *4.0 bne.s C2mainL ;branch if local drive boot *4.0 lea Data_area,a1 ;set up for call bsr Logon ;broadcasts a hello message c2mainL move.l d6,a0 ;Get CC.KERNEL starting address move.l LODATA,d0 ;D0 - Low data address move.l HIDATA,d1 ;D1 - High data address move.l LOCODE,d2 ;D2 - Low code address move.l (sp)+,d3 ;D3 - Highest free code address move.b ORB.l,d4 ;D4 - VIA ORB lsl.w #8,d4 ; move.b bootdev,d4 ;D4 - Boot device swap d4 ; move.b bootslt,d4 ;D4 - Boot slot lsl.w #8,d4 ; move.b bootsrv,d4 ;D4 - Boot server clr.l d5 move.b extcrt,d5 ;D5 - External CRT flag lsl.w #8,d5 ; move.b bootdrv,d5 ;D5 - OS system volume drive swap d5 ; move.l bootblk,d6 ;D6 - OS system volume block *3.6 cmpi.l #65536,d6 ;if greater than 64K use d6 *3.6 bge.s c2mainM ;is so continue *3.6 move.w d6,d5 ;if less than 64K use low word *3.6 clr.l d6 ; of d5 and d6 = 0 *3.6 c2mainM clr.l d7 ;No unit globals allowed move.l d1,sp ;Set up initial stack pointer addq.l #4,sp ;to be correct after LINK inst. jmp (a0) ;Start the sucker up!