|
|
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 SADR,0 # r0 -- overwritten with start addr ! 28: .set SR1,1*4 # offsets in save area ! 29: .set SR3,3*4 ! 30: .set SFLGS,4*4 # boot flags -- r5 ! 31: .set DRIVER,5*4 # where device driver addr gets saved -- r6 ! 32: .set SVSIZE,7*4 ! 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 'k,0,0,0,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: tstw (r9) # empty entry? ! 164: beql 1f # yes, skip it ! 165: cmpc3 $DIRSIZ,2(r9),bootname # desired name? ! 166: beql diryes # yep ! 167: 1: acbw $FSBSIZE-1,$DIRSIZ+2,r9,0b ! 168: incl r12 # get next block ! 169: brb dirblk ! 170: ! 171: berr: brb stask ! 172: ! 173: # ! 174: # subroutines placed here, out of sequence, to save space ! 175: # ! 176: # copy/convert block numbers ! 177: # out of an i-node ! 178: # r10 points to where we want them ! 179: # r0 points to the i-node ! 180: # for now, only the direct blocks ! 181: # ! 182: # r0 is destroyed ! 183: # ! 184: ! 185: addrcpy: ! 186: movl r10,r1 # make a volatile copy ! 187: addl2 $I_ADDR,r0 # point to addresses ! 188: clrl r2 ! 189: 0: ! 190: movw (r0)+,(r1)+ ! 191: movb (r0)+,(r1)+ ! 192: clrb (r1)+ ! 193: aoblss $NDIREC+1,r2,0b ! 194: rsb ! 195: ! 196: # ! 197: # fetch an i-node ! 198: # r0 has the i-number ! 199: # on exit, r0 points to the i-node in core ! 200: # address 0 is used as a buffer ! 201: # ! 202: ! 203: iget: ! 204: decl r0 # i-numbers are 1 based ! 205: clrl r1 # make a quadword ! 206: ediv $INOPB,r0,r8,-(sp) # r8 == block; (sp) == offset ! 207: addl2 $ILBLK*FSBSIZE/BSIZE,r8 ! 208: clrl r5 # into address 0 ! 209: bsbb bread ! 210: ashl $ISHIFT,(sp)+,r0 # point to i-node ! 211: rsb ! 212: ! 213: # ! 214: # read a BSIZE block from the disk ! 215: # using the rom subroutine ! 216: # block number in r8; ! 217: # buffer address in r5 ! 218: # no return if it failed ! 219: # ! 220: # hack: if we would read atop the boot roms, don't; ! 221: # read into a safe place instead, and remember ! 222: # for the purposes of the hack, it's assumed that ! 223: # reads are aligned in memory conveniently ! 224: # ! 225: ! 226: bread: ! 227: subl3 bufaddr,r5,r0 ! 228: blss 0f ! 229: cmpl r0,$BUFSIZE ! 230: bgeq 0f ! 231: movab savedata,r5 ! 232: addl2 r0,r5 ! 233: movb $1,didsave ! 234: 0: ! 235: pushl r5 # save real addr ! 236: movl bufaddr,r5 # get buffer loc ! 237: movq SR1(r11),r1 # device address stuff ! 238: movl SR3(r11),r3 # unit number ! 239: pushl r5 # duplicate address for driver routine ! 240: jsb *DRIVER(r11) # and call driver ! 241: blbc r0,berr # disk error, start over ! 242: tstl (sp)+ # fixup stack ! 243: movc3 $BSIZE,*bufaddr,*(sp)+ # copy data to final resting place ! 244: rsb ! 245: ! 246: # ! 247: # back to the main path: ! 248: # found the file ! 249: # fetch its i-node and read it in ! 250: # ! 251: ! 252: diryes: ! 253: movzwl (r9),r0 # i-number ! 254: bsbb iget ! 255: ##### check i-node? ! 256: bsbb addrcpy ! 257: # ! 258: # indirect blocks ! 259: # only the first 1024 bytes of the first indirect block examined ! 260: # ! 261: mull3 NDIREC*4(r10),$FSBSIZE/BSIZE,r12 # pick up one indirect block ! 262: beql noind ! 263: movl r12,r8 ! 264: moval NDIREC*4(r10),r5 ! 265: bsbb bread ! 266: addl3 r12,$1,r8 # 2 sectors == 256 indirections ! 267: moval NDIREC*4+BSIZE(r10),r5 ! 268: bsbb bread ! 269: noind: ! 270: clrl r5 ! 271: clrl r12 ! 272: rdloop: ! 273: ashl $FSSHIFT,r12,r5 ! 274: bsbb lread ! 275: bneq eof ! 276: incl r12 ! 277: brb rdloop ! 278: # ! 279: # whole file read in ! 280: # check for a.out header and relocate ! 281: # ! 282: eof: ! 283: blbc didsave,1f ! 284: movc3 $BUFSIZE,savedata,*bufaddr ! 285: 1: clrl r12 ! 286: movq A_TEXT(r12),r7 # r7 = text size; r8 = data size ! 287: extzv $0,$30,A_ENTRY(r12),SADR(r11) # starting address ! 288: 2: casel A_MAGIC(r12),$0407,$1 ! 289: 0: .word m0407-0b ! 290: .word m0410-0b ! 291: clrl SADR(r11) # no a.out, start at the top ! 292: brb done ! 293: m0407: ! 294: addl2 r8,r7 # text = text + data; no data ! 295: clrl r8 ! 296: # ! 297: # do copies by longword: simpler and smaller than movc3, ! 298: # which would need to loop anyway ! 299: # longword not quadword because ld rounds sizes to long ! 300: # ! 301: # really should beql after the second div, else when there's no data ! 302: # we copy one extra word to a nonsense place. ! 303: # too bad; we can't spare the code space ! 304: # ! 305: m0410: ! 306: clrl r0 ! 307: movzbl $32,r1 ! 308: addl3 r7,r8,r2 ! 309: divl2 $4,r2 ! 310: 1: movl (r1)+,(r0)+ # copy down over a.out header ! 311: sobgtr r2,1b ! 312: divl3 $4,r8,r2 ! 313: addl3 r8,r7,r1 # from t + d ! 314: extzv $0,$PGSHIFT,r7,r0 ! 315: beql 0f # don't overround ! 316: subw3 r0,$PGSIZE,r0 ! 317: 0: addl2 r1,r0 # to t + d + round ! 318: 2: movl -(r1),-(r0) # copy data to start at page boundary ! 319: sobgtr r2,2b ! 320: # ! 321: # reset registers and start ! 322: # ! 323: ! 324: done: ! 325: movl r11,sp ! 326: popr $REGMASK ! 327: movl r5,r11 # put boot flags in stupid bky place ! 328: jmp 2(r0) # skip register mask & start it ! 329: ! 330: # ! 331: # read a (filesystem) block from a file ! 332: # (filesystem) block number in r12 ! 333: # buffer address in r5 ! 334: # r10 points to the addresses ! 335: # returns status in psw: ! 336: # zero flag set if read a block ! 337: # clear if error or block doesn't exist ! 338: # ! 339: ! 340: lread: ! 341: cmpl r12,$NINDBLK ! 342: blss 0f ! 343: lerr: ! 344: bicpsw $4 # clear zero flag ! 345: rsb ! 346: 0: ! 347: movl (r10)[r12],r8 ! 348: beql lerr ! 349: pushl $FSBSIZE/BSIZE # count of disk blocks within fs block ! 350: mull3 $FSBSIZE/BSIZE,r8,-(sp) # fs block to disk block ! 351: 1: ! 352: movl (sp),r8 ! 353: movl r5,r6 # safe place ! 354: bsbw bread ! 355: movab BSIZE(r6),r5 ! 356: incl (sp) ! 357: sobgtr 4(sp),1b ! 358: clrq (sp)+ # addl2 $8,sp; set zero bit ! 359: rsb ! 360: # ! 361: # last address that needs saving ! 362: # ! 363: .globl end ! 364: end: ! 365: ! 366: # ! 367: # put uninitialized (not 0) data here ! 368: # ! 369: .align 2 ! 370: savedata: ! 371: # .space ROMSIZE
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.