Annotation of coherent/d/conf/boot/pboot.m, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.