|
|
1.1 ! root 1: //////// ! 2: / ! 3: / Patched bootstrap block for the IBM PC. ! 4: / This code, which lives in sector 1, ! 5: / track 0 of the floppy (or sector 1 of a hard disk partition) ! 6: / gets read into location 0x7C00 by the ROM. ! 7: / The code relocates itself to location 0x2060:0x0000 ! 8: / (128K above the fixed memory used by the ROM). The system image is read ! 9: / in beginning at paragraph 0x0060. ! 10: / ! 11: / $Log: /newbits/conf/boot/RCS/pboot.m,v $ ! 12: * Revision 1.2 91/05/29 09:42:16 bin ! 13: * bob h modified due to commented lines screwing the makefile ! 14: * ! 15: / * Revision 1.1 91/05/29 08:30:45 bin ! 16: / * Initial revision ! 17: / * ! 18: / Revision 1.1 88/03/24 16:44:09 src ! 19: / Initial revision ! 20: / ! 21: / 87/10/04 Allan Cornish /usr/src/sys/i8086/boot/boot.s ! 22: / Number of heads now defined by NHD macro. Should be 1 for f*d*, 2 for f*a*. ! 23: / ! 24: / 85/10/04 Allan Cornish /usr/src/sys/i8086/boot/boot.s ! 25: / Bootstrap extended to increase max file size from 64 Kbytes to 128 Kbytes. ! 26: / The private code segment is now loaded, where previously it had to be empty. ! 27: / File name editing enhanced to help cursor stay in the 14 char entry field, ! 28: / and to provide a destructive backspace. ! 29: / ! 30: / 85/01/04 Allan Cornish ! 31: / Added backspace editing of file name. ! 32: / ! 33: //////// ! 34: ! 35: //////// ! 36: / This is a patched version for machines with incorrect CMOS disk parameters. ! 37: / The values in traks, sects, heads, cntrl and wpcc are assumed correct. ! 38: / This BIOS is not interrogated to find the disk parameters. ! 39: / The controller is reset with the appropriate values. ! 40: //////// ! 41: ! 42: #ifndef NHD ! 43: #define NHD 1 / heads per drive [1 for f9d0]. ! 44: #endif ! 45: ! 46: #ifndef NSPT ! 47: #define NSPT 9 / sectors per track on floppy. ! 48: #define NTRK 40 / tracks on floppy. ! 49: #endif ! 50: ! 51: #ifndef CNTRL ! 52: #define CNTRL 8 ! 53: #endif ! 54: ! 55: #ifndef WPCC ! 56: #define WPCC 0xFFFF ! 57: #endif ! 58: ! 59: NSTK = 256 / bytes of stack. ! 60: BS = 0x08 / BS character. ! 61: CR = 0x0D / CR character. ! 62: LF = 0x0A / LF character. ! 63: SP = 0x20 / Backspace character. ! 64: BOOTLC = 0x7C00 / Boot location (ROM). ! 65: BOOTS = 0 / boot segment (ROM). ! 66: RBOOTS = 0x2060 / Relocated boot segment. ! 67: BSHIFT = 9 / Shift, bytes to blocks. ! 68: ROOTINO = 2 / Root inode # ! 69: INOORG = 2 / First inode block. ! 70: IBSHIFT = 3 / Shift, inode to blocks ! 71: IOSHIFT = 6 / Shift, inode to bytes ! 72: INOMASK = 0x0007 / Mask, inode to offset ! 73: DIRSIZE = 14 / Directory size. ! 74: DIRSIZ2 = 7 / Directory size / 2. ! 75: BUFSIZE = 512 / Block size. ! 76: HDRSIZE = 44 / L.out header size. ! 77: HDRSIZ2 = 22 / L.out header size / 2. ! 78: BUFMSK2 = 0x00FF / Block [word] mask, for reads. ! 79: DISK = 0x13 / Disk Interrupt ! 80: KEYBD = 0x16 / Keyboard Interrupt ! 81: READ1 = 0x0201 / read one sector ! 82: ND = 10 / # of direct blocks. ! 83: NIND = 128 / # of blocks in indirect block. ! 84: ISIZE = 8 / Offset of "di_size". ! 85: IADDR = 12 / Offset of "di_addr". ! 86: JMPF = 0xEA / Jump far, direct. ! 87: LMAGIC = 0 / Offset of "l_magic" ! 88: LFLAG = 2 / Offset of "l_flag" ! 89: LSHRI = 10 / Offset of "l_ssize[SHRI]" ! 90: LPRVI = 14 / Offset of "l_ssize[PRVI]" ! 91: LSHRD = 22 / Offset of "l_ssize[SHRD]" ! 92: LPRVD = 26 / Offset of "l_ssize[PRVD]" ! 93: LBSSD = 30 / Offset of "l_ssize[BSSD]" ! 94: LFMAG = 0x0107 / Magic number. ! 95: LFSEP = 0x02 / Sep I/D flag bit. ! 96: SYSBASE = 0x0060 / System load base paragraph. ! 97: FIRST = 8 / relative start of partition ! 98: ! 99: / Hard disk controller port addresses. ! 100: HF_REG = 0x3F6 ! 101: NSEC_REG= 0x1F2 ! 102: SEC_REG = 0x1F3 ! 103: HDRV_REG= 0x1F6 ! 104: CSR_REG = 0x1F7 ! 105: BSY_ST = 0x80 ! 106: SETPARM_CMD= 0x91 ! 107: ! 108: //////// ! 109: / ! 110: / Bootstrap mainline. Relocate the ! 111: / boot to high memory, so it wont be written ! 112: / over by the system. Read in a file name. Look up ! 113: / the file name by following out the directory ! 114: / structure. Read in the image and jump to it. ! 115: / ! 116: //////// ! 117: ! 118: boot: xor di, di ! 119: mov ds, di ! 120: mov si, $BOOTLC / Make DS:SI point at the code ! 121: mov es, 1f(si) / Make ES:DI point at where it goes ! 122: mov cx, $512 / cx = # of bytes to move ! 123: cld ! 124: rep / Move the bootstrap ! 125: movsb / to high memory. ! 126: ! 127: mov si, bp / set si to partition ! 128: mov di, $drive / point to drive ! 129: movsb / set drive ! 130: add si, $FIRST-1 / point to first block ! 131: movsw ! 132: movsw / fetch first block ! 133: ! 134: / Bang on disk controller. ! 135: / See at.c/atreset(). ! 136: #if 1 ! 137: movb al, $4 ! 138: mov dx, $HF_REG ! 139: outb dx, al / outb (HF_REG, 4); ! 140: mov cx, $-1 ! 141: 0: loop 0b / delay ! 142: movb al, cntrl ! 143: andb al, $0x0F ! 144: outb dx, al / outb (HF_REG, ctrl & 0xF); ! 145: / call atbsyw ! 146: ! 147: / Wait for AT controller to become not busy. ! 148: / From atas.s. ! 149: / atbsyw: ! 150: mov cx, $-1 ! 151: mov dx, $CSR_REG ! 152: 0: inb al, dx ! 153: testb al, $BSY_ST ! 154: loopne 0b ! 155: mov ax, cx ! 156: / ret ! 157: #endif ! 158: movb al, cntrl ! 159: mov dx, $HF_REG ! 160: outb dx, al / outb(HF_REG, cntrl); ! 161: movb al, sects ! 162: mov dx, $NSEC_REG ! 163: outb dx, al / outb(NSEC_REG, sects); ! 164: / The following should have drive << 4 added in, this assumes drive 0. ! 165: / Out of space to do it right now. ! 166: movb al, drive ! 167: sal ax, $4 ! 168: addb al, $0x9F ! 169: addb al, heads ! 170: mov dx, $HDRV_REG ! 171: outb dx, al / outb(HDRV_REG, 0xA0+(drive<<4)+heads-1); ! 172: movb al, $SETPARM_CMD ! 173: mov dx, $CSR_REG ! 174: outb dx, al / outb(CSR_REG, SETPARM_CMD) ! 175: nop ! 176: nop / filler to make 512 byte bootstrap ! 177: ! 178: / Set registers. ! 179: ! 180: 0: mov bp, $stack+NSTK / stack pointer value ! 181: mov ax, es ! 182: mov ds, ax ! 183: mov ss, ax ! 184: mov sp, bp ! 185: ! 186: / call login / print signon message ! 187: ! 188: / Jump to (relocated) boot. ! 189: ! 190: .byte JMPF ! 191: .word entry ! 192: 1: .word RBOOTS ! 193: ! 194: //////// ! 195: / ! 196: / Read the inode specified by "ax" ! 197: / into the external variable "iaddr". ! 198: / No checking is done to make sure that ! 199: / the inumber is in range on the filesystem. ! 200: / Sets dx and cx to 0. ! 201: / Mungs si, di, ax. ! 202: / ! 203: //////// ! 204: ! 205: igrab: dec ax / Make origin 0 and ! 206: push ax / remember for later use. ! 207: ! 208: movb cl, $IBSHIFT / Convert to ! 209: shr ax, cl / inode block number, ! 210: inc ax / then to physical block number, ! 211: inc ax ! 212: call bread / and read in the data. ! 213: ! 214: pop ax / Get i-number back. ! 215: and ax, $INOMASK / Get inode within block ! 216: movb cl, $IOSHIFT / and convert to ! 217: shl ax, cl / a byte offset in the block. ! 218: add si, ax / si = inode pointer. ! 219: ! 220: add si, $IADDR / Point at address field. ! 221: mov di, $iaddr / Copy out area. ! 222: ! 223: movb cl, $ND / cx = # of direct blocks. ! 224: 0: inc si / Skip 0th byte. ! 225: movsw / Move 1st (lsb) and 2nd (msb) ! 226: loop 0b / Do them all. ! 227: ! 228: inc si / Skip 0th byte and ! 229: lodsw / grab block # of (first) indirect. ! 230: ! 231: inc si / Skip 0th byte and ! 232: push (si) / remember block # of double indirect. ! 233: ! 234: call bread / Read (first) indirect block. ! 235: ! 236: movb cl, $NIND / cx = # of indirect maps (ch=0) ! 237: 1: lodsw / Skip hi half (canon long) ! 238: movsw / and move low half. ! 239: loop 1b / Do them all. ! 240: ! 241: pop ax ! 242: call bread / Read double indirect block. ! 243: lodsw ! 244: lodsw ! 245: call bread / Read (second) indirect block. ! 246: ! 247: movb cl, $NIND / cx = # of indirect maps (ch=0) ! 248: 2: lodsw / Skip hi half (canon long) ! 249: movsw / and move low half. ! 250: loop 2b / Do them all. ! 251: ! 252: sub dx, dx / sets dx to first word ! 253: / jmp iread / Done return through iread. ! 254: ! 255: //////// ! 256: / ! 257: / This routine reads the virtual ! 258: / block described by the ofs in "dx" into the ! 259: / buffer "bbuf". It uses the mapping data that ! 260: / has been provided by a previous call to igrab ! 261: / On return "si" points at "bbuf". ! 262: / Holes in files are correctly done. ! 263: / mungs ax, bx, si. ! 264: / clears cx. ! 265: / ! 266: /////// ! 267: ! 268: iread: ! 269: sub bx, bx / Convert from words to blocks. ! 270: movb bl, dh / ! 271: shl bx, $1 / Get 2 * block number into ! 272: mov ax, iaddr(bx) / physical block from the table. ! 273: / jmp bread / Yes, return through "bread". ! 274: ! 275: //////// ! 276: / ! 277: / Read a block from the floppy disk, ! 278: / drive A:, using the code in the IBM firmware. ! 279: / The physical block # is in "ax". ! 280: / ! 281: //////// ! 282: ! 283: bread: push es / Save registers ! 284: push di ! 285: push dx ! 286: ! 287: push ds ! 288: pop es / set ES to the address of the buffer ! 289: ! 290: mov di, bp / if block 0, clear buffer ! 291: mov cx, $BUFSIZE ! 292: rep ! 293: stosb ! 294: ! 295: test ax, ax / if block 0, return zeroed buffer ! 296: jz 2f ! 297: ! 298: xor dx, dx / extend block number ! 299: add ax, first / add first block ! 300: adc dx, first+2 / add rest ! 301: ! 302: mov bx, ax / save block number ! 303: movb al, heads / get number of heads ! 304: movb cl, sects / get number of sectors ! 305: mulb cl / calculate sectors per cylinder ! 306: xchg bx,ax / swap block/sectors ! 307: div bx / calculate track ! 308: xchg dx, ax / put track in DX ! 309: divb cl / calculate head/sector ! 310: ! 311: movb cl, ah / set sector ! 312: inc cx / sectors start at 1 [incb cl] ! 313: ! 314: cmp dx, traks / check for second side ! 315: jb 0f ! 316: sub dx, traks / fold track ! 317: inc ax / next head [incb al] ! 318: ! 319: 0: rorb dh, $1 / rotate track(low) into ! 320: rorb dh, $1 / msbits of DX ! 321: orb cl, dh / set track(high) ! 322: movb ch, dl / set track(low) ! 323: movb dh, al / set head ! 324: movb dl, drive / set drive ! 325: mov bx, bp / set offset [bbuf] ! 326: ! 327: mov ax, $READ1 / Read, 1 sector. ! 328: int DISK / Disk I/O. ! 329: jnc 2f / Jump if no error. ! 330: mov ax, $READ1 / try again ! 331: int DISK ! 332: jc error ! 333: ! 334: 2: mov si, bp / set SI to point to buffer for return ! 335: sub cx, cx / clear CX here to save space ! 336: pop dx / restore registers. ! 337: pop di ! 338: pop es ! 339: ret / return. ! 340: ! 341: //////// ! 342: / ! 343: / Print signon message ! 344: / ! 345: //////// ! 346: ! 347: / login: mov si, $msg00 / point si to message ! 348: ! 349: print: lodsb / al=byte ! 350: cmpb al, $LF / check for end of message ! 351: call putc / Type it and ! 352: jne print / go back for more. ! 353: ret ! 354: ! 355: / Prompt with a "?" and read the file name ! 356: / into the "nbuf". No character editing facilities ! 357: / are provided. ! 358: ! 359: error: mov sp, bp / Reset stack ! 360: / call login / print boot message ! 361: ! 362: input: mov di, $nbuf / di=name buffer pointer ! 363: mov cx, $DIRSIZE / cx=size of ! 364: movb al, $0x3F / set prompt to ? ! 365: 0: call putc ! 366: ! 367: 1: movb ah, $0 / Get ASCII opcode. ! 368: int KEYBD / Read keyboard ROM call. ! 369: ! 370: #if 0 ! 371: / Conditionalized out to make more space ! 372: cmpb al, $BS / BS ? ! 373: jne 2f / ! 374: cmpb cl, $DIRSIZE / At start of buffer? ! 375: je 1b / Yup, ignore BS ! 376: call putc / Output destructive backspace ! 377: movb al, $SP ! 378: call putc ! 379: movb al, $BS ! 380: dec di / Adjust pointer ! 381: inc cx / and char count ! 382: jmp 0b / and continue. ! 383: #endif ! 384: ! 385: 2: cmpb al, $CR / CR ? ! 386: je 3f / Yup, do next thing ! 387: ! 388: jcxz 1b / skip over too big name ! 389: stosb / put it into the buffer, ! 390: dec cx / adjust char count ! 391: jmp 0b / and continue. ! 392: ! 393: 3: mov si, $crlf / Echo LF followed by CR. ! 394: call print ! 395: ! 396: movb al, $0 / zero out ! 397: rep ! 398: stosb / rest of name ! 399: ! 400: entry: mov ax, $ROOTINO / ax = current inode ! 401: call igrab / Read in inode and set dx ! 402: ! 403: / Search directory. ! 404: / Assume directory size < 64 Kbytes. ! 405: ! 406: search: orb dl, dl / On block boundry ? ! 407: jnz 0f / Nope. ! 408: call iread / Read block, set si. ! 409: ! 410: 0: movb cl, $DIRSIZE / cx = count left ! 411: mov di, $nbuf / Point at name buffer and ! 412: lodsw / ax = inumber, this entry. ! 413: or ax, ax / Empty directory slot ? ! 414: je 1f / Yes, skip. ! 415: repe / compare the ! 416: cmpsb / two file names. ! 417: je found / If eq, go and get inode. ! 418: ! 419: 1: add si, cx / Advance by count remaining. ! 420: add dx, $DIRSIZ2+1 / Bump [word] seek pointer ! 421: jg search / Scan up to 64 Kbytes of directory. ! 422: ! 423: jmp input / File not found. ! 424: ! 425: //////// ! 426: / ! 427: / Found the file so read it in. ! 428: / ax = inode number of file ! 429: / ! 430: //////// ! 431: ! 432: found: call igrab / read in inode and first block ! 433: cmp LMAGIC(si),$LFMAG / Check the magic number. ! 434: jne error / not Ok. ! 435: ! 436: / push LBSSD(si) / Push the uninitialized data size. ! 437: mov ax, LSHRD(si) / Push the sum ! 438: add ax, LPRVD(si) / of the shared and private ! 439: push ax / [initialized] data sizes. ! 440: andb LFLAG(si), $LFSEP / check image flags. ! 441: pushf / Push result of test. ! 442: mov ax, LSHRI(si) / Get the sum of the ! 443: add ax, LPRVI(si) / shared and private code sizes. ! 444: ! 445: mov dx, $HDRSIZ2 / Seek after header and ! 446: add si, $HDRSIZE / set buffer pointer appropriately. ! 447: mov es, 1f / Set ES:DI to point to the load ! 448: sub di, di / base of the new system. ! 449: ! 450: call load / Load code. ! 451: ! 452: popf / Pop sep I/D flag test ! 453: jz 0f / Not sep. ! 454: ! 455: add di, $15 / Round up the system code ! 456: movb cl, $4 / size to 16 byte ! 457: shr di, cl / paragraphs. ! 458: mov ax, es / fetch program base ! 459: add ax, di / Compute the data base and ! 460: mov es, ax / set up ES:DI to point ! 461: sub di, di / at it. ! 462: ! 463: 0: pop ax / Pop off initialized data size and ! 464: call load / load the image. ! 465: ! 466: / pop cx / Pop off uninitialized data size and ! 467: / rep / clear it. ! 468: / stosb ! 469: ! 470: .byte JMPF / Jump to offset ! 471: .word 0x0100 / 0x0100 (after base) in system ! 472: 1: .word SYSBASE / code segment. ! 473: ! 474: //////// ! 475: / ! 476: / Load a segment. The "dx" holds the ! 477: / seek pointer into the file. The "si" holds ! 478: / a pointer into the "bbuf". The "es:di" pair ! 479: / holds the target address. The "ax" holds ! 480: / the number of bytes to load. On return the ! 481: / "ax" must equal 0 (the caller assumes this ! 482: / and uses "al" to clear the BSS). ! 483: / ! 484: //////// ! 485: ! 486: load: or ax, ax / Any left ? ! 487: jz return / Jump if all loaded. ! 488: ! 489: mov cx, $bbuf+BUFSIZE / Compute the number of bytes ! 490: sub cx, si / remaining in the block. ! 491: jnz 0f / Jump if some. ! 492: ! 493: push ax / Save count registers, then ! 494: call iread / read the next block ! 495: pop ax / of the file. ! 496: mov cx, $BUFSIZE / We now have a full block. ! 497: ! 498: 0: cmp cx, ax / More than we need ? ! 499: jbe 1f / Nope. ! 500: mov cx, ax / Only take what we need. ! 501: ! 502: 1: sub ax, cx / Fix up the count ! 503: shr cx, $1 / ! 504: add dx, cx / Fix up the seek [word] address, then ! 505: rep / copy the words from the block ! 506: movsw / buffer to the load point and ! 507: jmp load / loop until done. ! 508: ! 509: //////// ! 510: / ! 511: / Write the character in "al" out to ! 512: / the display, using routines in the ROM. ! 513: / Like most calls to the ROM, this routine spends ! 514: / most of its time saving and restoring the ! 515: / registers. ! 516: / ! 517: / Note: The ZF in the PSW word must be preserved. ! 518: / ! 519: //////// ! 520: ! 521: putc: push si / Save registers. ! 522: push di ! 523: push bp ! 524: ! 525: mov bx, $0x0007 / Page 0, white on black ! 526: movb ah, $0x0E / Write TTY. ! 527: int 0x10 / Call video I/O in ROM. ! 528: ! 529: pop bp / Restore registers. ! 530: pop di ! 531: pop si ! 532: return: ret / Return ! 533: ! 534: //////// ! 535: / ! 536: / Data. There is some pure data in ! 537: / the "prvd" segment. This data is moved to the ! 538: / new memory when the boot is relocated. All buffers ! 539: / are in the BSS, and are not actually moved, or even ! 540: / saved in the boot block. ! 541: / ! 542: //////// ! 543: ! 544: .prvd ! 545: nbuf: .ascii "autoboot" / Name buffer. ! 546: .blkb DIRSIZE-8 / rest of buffer ! 547: ! 548: traks: .word NTRK ! 549: sects: .byte NSPT ! 550: heads: .byte NHD ! 551: cntrl: .byte CNTRL ! 552: wpcc: .word WPCC / not used currently ! 553: drive: .byte 0 ! 554: first: .word 0 ! 555: .word 0 ! 556: ! 557: / msg00: .ascii "Boot" ! 558: crlf: .byte CR, LF ! 559: ! 560: .byte 0x55,0xAA ! 561: ! 562: .bssd ! 563: stack: .blkb NSTK / Local Stack and name buffer ! 564: bbuf: .blkb BUFSIZE / Block buffer [must follow stack]. ! 565: iaddr: .blkw ND+NIND+NIND / Inode map words. ! 566: ! 567:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.