|
|
1.1 ! root 1: # ! 2: # device-independent boot block ! 3: # uses the rom device driver ! 4: # reads an already-de-headered, small file with predetermined name ! 5: # into the beginning of memory ! 6: # and executes it ! 7: # ! 8: # buffering: ! 9: # the ROM driver will only write into the bottom 64K of memory ! 10: # to make things simple, we always read to a fixed place, ! 11: # then copy to the desired place. ! 12: # if we would have read to the fixed place, ! 13: # we copy to a safe buffer, and copy back when we're all done. ! 14: # the same subterfuge is needed to avoid overwriting the in-RAM copy ! 15: # of the boot ROMs, where our device driver lives, ! 16: # so we use the memory just below the ROM copy for the buffer ! 17: # ! 18: .set BSIZE,512 # size of a disk block, according to rom driver ! 19: .set BSHIFT,9 ! 20: .set BUFADDR,0xfa00-BSIZE # where to read stuff ! 21: .set BUFSIZE,1024+BSIZE # sizeof(buffer) + sizeof(roms) ! 22: ! 23: .set NAMELEN,14 # number of chars in name; one element for now ! 24: .set HIADDR,0x70000 # high address at which we run ! 25: ! 26: .set REGMASK,0xef # registers to save for second boot ! 27: .set SVSIZE,7*4 ! 28: .set SADR,0 # r0 -- overwritten with start addr ! 29: .set SR1,(1*4) # offsets in save area ! 30: .set SR3,(3*4) ! 31: .set SFLGS,(4*4) # boot flags -- r5 ! 32: .set DRIVER,(5*4) # where device driver addr gets saved -- r6 ! 33: ! 34: .set A_MAGIC,0 # offset in exec hdr: magic number ! 35: .set A_TEXT,4 # text size ! 36: .set A_DATA,8 # data size ! 37: .set A_ENTRY,20 # start address ! 38: ! 39: .set ISIZE,64 # size of an i-node ! 40: .set ISHIFT,6 # same as a shift ! 41: .set INOPB,BSIZE/ISIZE ! 42: .set ROOTINO,2 # i-number of the root ! 43: .set ILBLK,2 # first block of i-list ! 44: .set NDIREC,10 # number of direct blocks ! 45: .set NINDIR,256 # number of (interesting) indirect blocks ! 46: .set NINDBLK,NDIREC+NINDIR ! 47: ! 48: # ! 49: # MAXBLK is the max number of blocks to read; ! 50: # must be the lesser of NINDBLK (number of blocks available) ! 51: # and (HIADDR-NINDBLK*4-some slop)/FSBSIZE (space available without overwriting us) ! 52: # ! 53: .set MAXBLK,(HIADDR-NINDBLK*4-FSBSIZE)/FSBSIZE ! 54: .set I_ADDR,12 # offset to addresses in inode ! 55: .set DIRSIZ,14 # chars in filename ! 56: ! 57: .set PGSIZE,1024 # ld's idea of page size -- for 0410 a.out ! 58: .set PGSHIFT,10 ! 59: ! 60: .set RXCS,32 # console rcv csr ! 61: .set RXDB,33 # console rcv data buffer ! 62: .set RRDY_B,7 # bit number of ready bit in RXCS ! 63: .set TXCS,34 # console xmt csr ! 64: .set TXDB,35 # console xmt data buffer ! 65: .set TRDY_B,7 # bit number of ready bit in TXCS ! 66: ! 67: # ! 68: # main code ! 69: # relocate ourselves to high memory ! 70: # read the root directory, and search it for ! 71: # the desired file ! 72: # read that file in ! 73: # ! 74: # start must be at addr 0xc ! 75: # ! 76: ! 77: beg: ! 78: brb start;brb start # 0, 2 valid start addresses ! 79: hiaddr: .long HIADDR ! 80: .set didsave,hiaddr+3 # a byte which is 0 when we start ! 81: bufaddr: .long BUFADDR # handy constant reference ! 82: start: ! 83: movl hiaddr,sp # set up new stack ! 84: pushr $REGMASK # save important boot registers ! 85: movl sp,r11 # remember where they are ! 86: movc3 $end,beg,SVSIZE(sp) # copy us up ! 87: jmp strel+SVSIZE(sp) ! 88: ! 89: bootname: ! 90: .byte 'u,'n,'i,'x,0,0,0,0,0,0,0,0,0,0 ! 91: ! 92: ! 93: # ! 94: # print a character on the console from r1 ! 95: # ! 96: ! 97: putc: ! 98: mfpr $TXCS,r2 ! 99: bbc $TRDY_B,r2,putc ! 100: mtpr r1,$TXDB ! 101: rsb ! 102: ! 103: # ! 104: # jump here after relocation ! 105: # ! 106: ! 107: strel: ! 108: blbs SFLGS(r11),stask # boot flag 1 == prompt for filename ! 109: movab bootname,r0 ! 110: 0: movzbl (r0)+,r1 ! 111: beql prnl ! 112: bsbb putc ! 113: brb 0b ! 114: ! 115: stask: ! 116: movl r11,sp # in case we loop back ! 117: ! 118: # ! 119: # read a string from the console into bootname ! 120: # terminated by newline ! 121: # ! 122: ! 123: getpr: ! 124: movzbl $'*,r1 # prompt ! 125: bsbb putc ! 126: ! 127: getname: ! 128: movab bootname,r3 ! 129: movzbl $NAMELEN-1,r0 ! 130: 0: mfpr $RXCS,r1 ! 131: bbc $RRDY_B,r1,0b ! 132: mfpr $RXDB,r1 ! 133: bicb2 $0200,r1 ! 134: bsbb putc ! 135: cmpb $015,r1 ! 136: beql 8f ! 137: cmpb $040,r1 # ignore control chars; thanks, nautilus ! 138: bgtr 0b ! 139: decl r0 ! 140: blss 0b ! 141: movb r1,(r3)+ ! 142: brb 0b ! 143: 8: clrb (r3)+ ! 144: sobgtr r0,8b ! 145: prnl: movzbl $015,r1 ! 146: bsbb putc ! 147: movzbl $012,r1 ! 148: bsbb putc # and return ! 149: 2: ! 150: # ! 151: # get the root i-node ! 152: # ! 153: movl $ROOTINO,r0 ! 154: bsbb iget ! 155: #### check is directory? ! 156: movab -NINDBLK*4(sp),sp ! 157: movl sp,r10 ! 158: bsbb addrcpy ! 159: # ! 160: # search the root directory ! 161: # ! 162: ! 163: clrl r12 # init block pointer ! 164: dirblk: ! 165: clrl r5 # use beginning of mem as buffer ! 166: bsbw lread ! 167: bneq stask # eof, try another file ! 168: clrl r9 ! 169: 0: ! 170: movzwl (r9)+,r0 # empty entry? ! 171: beql 2f # yes, skip it ! 172: clrl r1 ! 173: 1: cmpb (r9)[r1],bootname[r1] # MicroVAX II doesn't have cmpc ! 174: bneq 2f ! 175: aoblss $DIRSIZ,r1,1b ! 176: brb diryes # the name we want ! 177: ! 178: 2: acbw $FSBSIZE-1,$DIRSIZ,r9,0b ! 179: incl r12 # get next block ! 180: brb dirblk ! 181: ! 182: berr: brb stask ! 183: ! 184: # ! 185: # subroutines placed here, out of sequence, to save space ! 186: # ! 187: # copy/convert block numbers ! 188: # out of an i-node ! 189: # r10 points to where we want them ! 190: # r0 points to the i-node ! 191: # for now, only the direct blocks ! 192: # ! 193: # r0 is destroyed ! 194: # ! 195: ! 196: addrcpy: ! 197: movl r10,r1 # make a volatile copy ! 198: addl2 $I_ADDR,r0 # point to addresses ! 199: clrl r2 ! 200: 0: ! 201: movw (r0)+,(r1)+ ! 202: movzbw (r0)+,(r1)+ ! 203: aoblss $NDIREC+1,r2,0b ! 204: rsb ! 205: ! 206: # ! 207: # fetch an i-node ! 208: # r0 has the i-number ! 209: # on exit, r0 points to the i-node in core ! 210: # address 0 is used as a buffer ! 211: # ! 212: ! 213: iget: ! 214: decl r0 # i-numbers are 1 based ! 215: clrl r1 # make a quadword ! 216: ediv $INOPB,r0,r8,-(sp) # r8 == block; (sp) == offset ! 217: addl2 $ILBLK*FSBSIZE/BSIZE,r8 ! 218: clrl r5 # into address 0 ! 219: bsbb bread ! 220: ashl $ISHIFT,(sp)+,r0 # point to i-node ! 221: rsb ! 222: ! 223: # ! 224: # read a BSIZE block from the disk ! 225: # using the rom subroutine ! 226: # block number in r8; ! 227: # buffer address in r5 ! 228: # no return if it failed ! 229: # ! 230: # hack: if we would read atop the boot roms, don't; ! 231: # read into a safe place instead, and remember ! 232: # for the purposes of the hack, it's assumed that ! 233: # reads are aligned in memory conveniently ! 234: # ! 235: ! 236: bread: ! 237: subl3 bufaddr,r5,r0 ! 238: blss 0f ! 239: cmpl r0,$BUFSIZE ! 240: bgeq 0f ! 241: movab savedata,r5 ! 242: addl2 r0,r5 ! 243: movb $1,didsave ! 244: 0: ! 245: pushl r5 # save real addr ! 246: movl bufaddr,r5 # get buffer loc ! 247: movq SR1(r11),r1 # device address stuff ! 248: movl SR3(r11),r3 # unit number ! 249: pushl r5 # duplicate address for driver routine ! 250: jsb *DRIVER(r11) # and call driver ! 251: blbc r0,berr # disk error, start over ! 252: tstl (sp)+ # fixup stack ! 253: movc3 $BSIZE,*bufaddr,*(sp)+ # copy data to final resting place ! 254: rsb ! 255: ! 256: # ! 257: # back to the main path: ! 258: # found the file ! 259: # fetch its i-node and read it in ! 260: # i-number left in r0 for us ! 261: # ! 262: ! 263: diryes: ! 264: bsbb iget ! 265: ##### check i-node? ! 266: bsbb addrcpy ! 267: # ! 268: # indirect blocks ! 269: # only the first 1024 bytes of the first indirect block examined ! 270: # ! 271: mull3 NDIREC*4(r10),$FSBSIZE/BSIZE,r12 # pick up one indirect block ! 272: beql noind ! 273: movl r12,r8 ! 274: moval NDIREC*4(r10),r5 ! 275: bsbb bread ! 276: addl3 r12,$1,r8 # 2 sectors == 256 indirections ! 277: moval NDIREC*4+BSIZE(r10),r5 ! 278: bsbb bread ! 279: noind: ! 280: clrl r5 ! 281: clrl r12 ! 282: rdloop: ! 283: ashl $FSSHIFT,r12,r5 ! 284: bsbb lread ! 285: bneq eof ! 286: incl r12 ! 287: brb rdloop ! 288: # ! 289: # whole file read in ! 290: # check for a.out header and relocate ! 291: # ! 292: eof: ! 293: blbc didsave,1f ! 294: movc3 $BUFSIZE,savedata,*bufaddr ! 295: 1: clrl r12 ! 296: movq A_TEXT(r12),r7 # r7 = text size; r8 = data size ! 297: movl A_ENTRY(r12),SADR(r11) # starting address ! 298: 2: casel A_MAGIC(r12),$0407,$1 ! 299: 0: .word m0407-0b ! 300: .word m0410-0b ! 301: clrl SADR(r11) # no a.out, start at the top ! 302: brb done ! 303: m0407: ! 304: addl2 r8,r7 # text = text + data; no data ! 305: clrl r8 ! 306: # ! 307: # do copies by longword: simpler and smaller than movc3, ! 308: # which would need to loop anyway ! 309: # longword not quadword because ld rounds sizes to long ! 310: # ! 311: # really should beql after the second div, else when there's no data ! 312: # we copy one extra word to a nonsense place. ! 313: # too bad; we can't spare the code space ! 314: # ! 315: m0410: ! 316: clrl r0 ! 317: movzbl $32,r1 ! 318: addl3 r7,r8,r2 ! 319: divl2 $4,r2 ! 320: 1: movl (r1)+,(r0)+ # copy down over a.out header ! 321: sobgtr r2,1b ! 322: # ! 323: # assertion: r0 == t + d ! 324: # ! 325: extzv $0,$PGSHIFT,r7,r1 # r1 = t & pagemask ! 326: beql 3f # no offset, no work ! 327: subw3 r1,$PGSIZE,r1 ! 328: addl3 r1,r0,r1 # r1 = (t + d) + alignment offset ! 329: divl3 $4,r8,r2 ! 330: 2: movl -(r0),-(r1) # copy data to start at page boundary ! 331: sobgtr r2,2b ! 332: 3: ! 333: # ! 334: # reset registers and start ! 335: # ! 336: ! 337: done: ! 338: movl r11,sp ! 339: popr $REGMASK ! 340: movl r5,r11 # put boot flags in stupid bky place ! 341: jmp 2(r0) # skip register mask & start it ! 342: ! 343: # ! 344: # read a (filesystem) block from a file ! 345: # (filesystem) block number in r12 ! 346: # buffer address in r5 ! 347: # r10 points to the addresses ! 348: # returns status in psw: ! 349: # zero flag set if read a block ! 350: # clear if error or block doesn't exist ! 351: # ! 352: ! 353: lread: ! 354: cmpw r12,$MAXBLK ! 355: blss 0f ! 356: lerr: ! 357: bicpsw $4 # clear zero flag ! 358: rsb ! 359: 0: ! 360: movl (r10)[r12],r8 ! 361: beql lerr ! 362: pushl $FSBSIZE/BSIZE # count of disk blocks within fs block ! 363: mull3 $FSBSIZE/BSIZE,r8,-(sp) # fs block to disk block ! 364: 1: ! 365: movl (sp),r8 ! 366: movl r5,r6 # safe place ! 367: bsbw bread ! 368: movab BSIZE(r6),r5 ! 369: incl (sp) ! 370: sobgtr 4(sp),1b ! 371: clrq (sp)+ # addl2 $8,sp; set zero bit ! 372: rsb ! 373: # ! 374: # last address that needs saving ! 375: # ! 376: .globl end ! 377: end: ! 378: ! 379: # ! 380: # put uninitialized (not 0) data here ! 381: # ! 382: .align 2 ! 383: savedata: ! 384: # .space ROMSIZE
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.