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