Annotation of coherent/d/conf/boot.s, revision 1.1.1.1

1.1       root        1: / $Header: /z/vlad/boot/src/RCS/boot.s,v 1.4 91/08/27 14:19:59 vlad Exp Locker: vlad $
                      2: / (lgl-
                      3: /      The information contained herein is a trade secret of Mark Williams
                      4: /      Company, and  is confidential information.  It is provided  under a
                      5: /      license agreement,  and may be  copied or disclosed  only under the
                      6: /      terms of  that agreement.  Any  reproduction or disclosure  of this
                      7: /      material without the express written authorization of Mark Williams
                      8: /      Company or persuant to the license agreement is unlawful.
                      9: /
                     10: /      COHERENT Version 2.3.37
                     11: /      Copyright (c) 1982, 1983, 1984.
                     12: /      An unpublished work by Mark Williams Company, Chicago.
                     13: /      All rights reserved.
                     14: / -lgl)
                     15: 
                     16: ////////
                     17: /
                     18: / Bootstrap block for the IBM
                     19: / PC. This code, which lives in sector 1,
                     20: / track 0 of the floppy (or sector 1 of a hard disk partition)
                     21: / gets read into location 0x7C00 by the ROM.
                     22: / The code relocates itself to location 0x2060:0x0000
                     23: / (128K above the fixed memory used by the ROM). The system image is read
                     24: / in beginning at paragraph 0x0060.
                     25: /
                     26: / $Log:        boot.s,v $
                     27: /RCS-> Revision 1.4  91/08/27  14:19:59  vlad
                     28: /RCS-> Fixed boot that allow to boot from arbitrary place of the disk, by
                     29: /RCS-> using four byte block numbers. Original (oldest and Ciarian) used
                     30: /RCS-> only two byte block numbers -- only the first 32 Meg were accessable.
                     31: /RCS-> 
                     32: / Revision 1.1 88/03/24  16:44:09      src
                     33: / Initial revision
                     34: / 
                     35: / 87/10/04     Allan Cornish           /usr/src/sys/i8086/boot/boot.s
                     36: / Number of heads now defined by NHD macro.  Should be 1 for f*d*, 2 for f*a*.
                     37: /
                     38: / 85/10/04     Allan Cornish           /usr/src/sys/i8086/boot/boot.s
                     39: / Bootstrap extended to increase max file size from 64 Kbytes to 128 Kbytes.
                     40: / The private code segment is now loaded, where previously it had to be empty.
                     41: / File name editing enhanced to help cursor stay in the 14 char entry field,
                     42: / and to provide a destructive backspace.
                     43: /
                     44: / 85/01/04     Allan Cornish
                     45: / Added backspace editing of file name.
                     46: /
                     47: ////////
                     48: 
                     49: #ifndef        NHD
                     50: #define        NHD     1                       / # of heads per drive [1 for f9d0].
                     51: #endif
                     52: 
                     53: #ifndef        NSPT
                     54: #define        NSPT    9                       / # of sectors per track on floppy.
                     55: #define        NTRK    40                      / # of tracks on floppy.
                     56: #endif
                     57: 
                     58: NSTK   =       256                     / # of bytes of stack.
                     59: BS     =       0x08                    / BS character.
                     60: CR     =       0x0D                    / CR character.
                     61: LF     =       0x0A                    / LF character.
                     62: SP     =       0x20                    / Backspace character.
                     63: BOOTLC =       0x7C00                  / Boot location (ROM).
                     64: BOOTS  =       0                       / boot segment (ROM).
                     65: RBOOTS =       0x2060                  / Relocated boot segment.
                     66: BSHIFT =       9                       / Shift, bytes to blocks.
                     67: ROOTINO =      2                       / Root inode #
                     68: INOORG =       2                       / First inode block.
                     69: IBSHIFT =      3                       / Shift, inode to blocks
                     70: IOSHIFT =      6                       / Shift, inode to bytes
                     71: INOMASK =      0x0007                  / Mask, inode to offset
                     72: DIRSIZE =      14                      / Directory size.
                     73: DIRSIZ2 =      7                       / Directory size / 2.
                     74: BUFSIZE =      512                     / Block size.
                     75: HDRSIZE =      44                      / L.out header size.
                     76: HDRSIZ2 =      22                      / L.out header size / 2.
                     77: BUFMSK2 =      0x00FF                  / Block [word] mask, for reads.
                     78: DISK   =       0x13                    / Disk Interrupt
                     79: KEYBD  =       0x16                    / Keyboard Interrupt
                     80: READ1  =       0x0201                  / read one sector
                     81: DADDR  =       4                       / number of bytes in a disk block number
                     82: ND     =       10                      / # of direct blocks.
                     83: NIND   =       128                     / # of blocks in indirect block.
                     84: NINDX2 =       256                     / NIND * 2 (number of words in indirect)
                     85: ISIZE  =       8                       / Offset of "di_size".
                     86: IADDR  =       12                      / Offset of "di_addr".
                     87: JMPF   =       0xEA                    / Jump far, direct.
                     88: LMAGIC =       0                       / Offset of "l_magic"
                     89: LFLAG  =       2                       / Offset of "l_flag"
                     90: LSHRI  =       10                      / Offset of "l_ssize[SHRI]"
                     91: LPRVI  =       14                      / Offset of "l_ssize[PRVI]"
                     92: LSHRD  =       22                      / Offset of "l_ssize[SHRD]"
                     93: LPRVD  =       26                      / Offset of "l_ssize[PRVD]"
                     94: LBSSD  =       30                      / Offset of "l_ssize[BSSD]"
                     95: LFMAG  =       0x0107                  / Magic number.
                     96: LFSEP  =       0x02                    / Sep I/D flag bit.
                     97: SYSBASE =      0x0060                  / System load base paragraph.
                     98: FIRST  =       8                       / relative start of partition
                     99: 
                    100: ////////
                    101: / Overall structure of boot.s (the secondary boot):
                    102: /
                    103: / boot: relocate secondary to high memory (0x2060:0x0000)
                    104: /      if needed, get hard disk parameters from bios
                    105: /      jump far to high memory (RBOOTS:entry)
                    106: / entry: open directory "/"
                    107: / search: while filename not found
                    108: /      walk through "/" looking for filename (in nbuf)
                    109: /      if not found, ask for another name (call input:), and loop to search
                    110: / found: open file that we just found
                    111: /      read the l.out header (verify magic number, get partition sizes)
                    112: /      load the shared and private code segments as one (call load:)
                    113: /      load the initialized data segment (call load:)
                    114: /      jump far to the newly loaded program
                    115: /      
                    116: ////////
                    117: 
                    118: ////////
                    119: /
                    120: / Bootstrap mainline. Relocate the
                    121: / boot to high memory, so it won't be written
                    122: / over by the system. Read in a file name. Look up
                    123: / the file name by following out the directory
                    124: / structure. Read in the image and jump to it.
                    125: /
                    126: ////////
                    127: 
                    128: boot:  xor     di, di
                    129:        mov     ds, di
                    130:        mov     si, $BOOTLC             / Make DS:SI point at the code
                    131: / "mov es, 1f(si)" really means "mov es, $RBOOTS".  Clever Intel... :-(
                    132:        mov     es, 1f(si)              / Make ES:DI point at where it goes
                    133:        mov     cx, $512                / cx = # of bytes to move
                    134:        cld
                    135:        rep                             / Move the bootstrap
                    136:        movsb                           / to high memory.
                    137: 
                    138: / Check to see if we were invoked by mboot.  (That means we're booting
                    139: / off a hard disk and need to load disk parameters.
                    140: 
                    141:                                        / mboot sets bx = sp
                    142:        cmp     bx, sp                  / trick to tell
                    143:        jne     0f                      / whether or not xt
                    144: 
                    145: / Assertion: at this point we know we're boot off a hard disk.
                    146:        mov     si, bp                  / set si to partition table
                    147: 
                    148:        movb    dl, (si)                / get drive number
                    149:        movb    ah, $8                  / get drive parameters
                    150:        int     DISK
                    151:        jc      0f                      / abort on error
                    152: 
                    153:        movb    al, ch                  / fetch cyl(lo)
                    154:        movb    ah, cl                  / move cyl(hi), sects
                    155:        rolb    ah, $1                  / shift cylinder high to
                    156:        rolb    ah, $1                  / the least sig bits
                    157:        andb    ah, $3                  / mask out cylinder bits
                    158:        
                    159:        mov     di, $traks              / point to drive
                    160:        stosw                           / set number of tracks
                    161: 
                    162:        movb    al, $0x3F               / sector mask
                    163:        andb    al,cl                   / mask sector
                    164:        stosb                           / set sector
                    165: 
                    166:        movb    al, dh                  / get max head
                    167:        inc     ax                      / change to # of heads [incb al]
                    168:        stosb                           / set number of heads
                    169: 
                    170:        movsb                           / set drive
                    171:        add     si, $FIRST-1            / point to first block
                    172:        movsw
                    173:        movsw                           / fetch first block
                    174: 
                    175: / Set registers.
                    176: 
                    177: 0:     mov     bp, $stack+NSTK         / stack pointer value
                    178:        mov     ax, es
                    179:        mov     ds, ax
                    180:        mov     ss, ax
                    181:        mov     sp, bp
                    182: 
                    183:        call    login                   / print signon message
                    184: 
                    185: / Jump to (relocated) boot.
                    186: 
                    187:        .byte   JMPF
                    188:        .word   entry
                    189: 1:     .word   RBOOTS
                    190: 
                    191: ////////
                    192: /
                    193: / This is the equivalent of "open()",
                    194: / but takes an inode instead of a pathname.
                    195: /
                    196: / Read the inode specified by "ax"
                    197: / into the external variable "iaddr".
                    198: /
                    199: / Makes a list of block numbers in "iaddr"
                    200: / consisting of the 10 direct block numbers, the 128
                    201: / block numbers pointed to the singly indirect block,
                    202: / and the first 128 block numbers pointed to by the
                    203: / first doubly indirect block.
                    204: /
                    205: / Note that "iread" can only access the first 256
                    206: / block numbers in this list, so the last 10 are
                    207: / ignored.
                    208: /
                    209: / Note that block numbers are actually 32 bits on disk--
                    210: / this routine only uses the lower 16 bits.
                    211: / In fact, iaddr is loaded with 16 bit numbers, not 32 bit.
                    212: /
                    213: / No checking is done to make sure that
                    214: / the inumber is in range on the filesystem.
                    215: / Sets dx and cx to 0.
                    216: / Mungs si, di, ax.
                    217: /
                    218: ////////
                    219: 
                    220: igrab: dec     ax                      / Make origin 0 and
                    221:        push    ax                      / remember for later use.
                    222: 
                    223:        / We assume that the inode table appears in the first 32 meg of disk.
                    224:        / Look up the inode in the inode table.
                    225:        movb    cl, $IBSHIFT            / Convert to
                    226:        shr     ax, cl                  / inode block number,
                    227:        inc     ax                      / then to physical block number,
                    228:        inc     ax
                    229:        sub     bx, bx                  / Assume inode within first 32 meg.
                    230:        call    bread                   / and read in the data.
                    231: 
                    232:        pop     ax                      / Get i-number back.
                    233:        and     ax, $INOMASK            / Get inode within block
                    234:        movb    cl, $IOSHIFT            / and convert to
                    235:        shl     ax, cl                  / a byte offset in the block.
                    236:        add     si, ax                  / si = inode pointer.
                    237: 
                    238:        / Assertion: si now points at the start of the desired
                    239:        / inode structure (see <sys/inode.h>).
                    240: 
                    241:        / Copy out the direct block numbers to iaddr.
                    242:        add     si, $IADDR              / Point at address field.
                    243:        mov     di, $iaddr              / Copy out area.
                    244: 
                    245:        / The block numbers in the inode on disk are stored as
                    246:        / 3 bytes: msb, lsw.  lsw is lsb, msb.  We want to store them
                    247:        / in memory as msw, lsw, just like the inodes in the indirect
                    248:        / blocks on disk.  So we need to cast msb as msw.
                    249:        movb    cl, $ND                 / cx = # of direct blocks
                    250:        sub     ax, ax                  / cast byte in al to word in ax
                    251: 0:     lodsb                           / al = msb for direct byte
                    252:        stosw                           / store msb cast as a word
                    253:        movsw                           / store lsw.
                    254:        loop    0b
                    255: 
                    256:        lodsb                           / Get the msb for the indirect block.
                    257:        xchg    bx, ax                  / (implicit cast of msb to msw)
                    258:        lodsw                           / Get the lsw for the indirect block.
                    259:        call    bread                   / Read (first) indirect block.
                    260: 
                    261:        / Copy out the singly indirect block numbers to iaddr.
                    262:        / These are stored on disk as 4 byte numbers: msw, lsw
                    263:        / where each word is lsb, msb.  This is how we store them
                    264:        / in memory.
                    265:        mov     cx, $NINDX2
                    266:        rep
                    267:        movsw
                    268:        
                    269:        / Finish by reading the first block of the file into bbuf.
                    270:        sub     dx, dx                  / Set dh to first block number in iaddr.
                    271: /      jmp     iread                   / Done return through iread.
                    272: 
                    273: ////////
                    274: /
                    275: / This routine reads the virtual
                    276: / block iaddr[dh] (the dh'th block number
                    277: / in iaddr) into the buffer "bbuf".
                    278: / It uses the mapping data that
                    279: / has been provided by a previous call to igrab
                    280: / On return "si" points at "bbuf".
                    281: / Holes in files (sparse blocks) are correctly done.
                    282: / mungs ax, bx, si.
                    283: / clears cx.
                    284: /
                    285: ///////
                    286: 
                    287: iread:
                    288:        sub     bx, bx                  / Convert from words to blocks.
                    289:        movb    bl, dh                  /
                    290: 
                    291:        / Block numbers are 4 bytes long, stored msw, lsw.
                    292:        shl     bx, $2                  / Compute index into iaddr table.
                    293:        push    iaddr(bx)               / fetch msw
                    294:        inc     bx
                    295:        inc     bx
                    296:        mov     ax, iaddr(bx)           / fetch lsw
                    297:        pop     bx                      / put msw where it belongs
                    298: /      jmp     bread                   / Yes, return through "bread".
                    299: 
                    300: ////////
                    301: /
                    302: / Read a block from the floppy disk,
                    303: / drive A:, using the code in the IBM firmware.
                    304: / The physical block # is in ax and bx.
                    305: / Register bx is the MSW, and ax is the LSW.
                    306: /
                    307: / This code is restricted to reading from the first 32meg of
                    308: / disk because the block number is only 16 bits long.
                    309: ////////
                    310: 
                    311: bread: push    es                      / Save registers
                    312:        push    di
                    313:        push    dx
                    314: 
                    315:        push    ds
                    316:        pop     es                      / set ES to the address of the buffer
                    317: 
                    318:        mov     di, bp                  / Blast the buffer contents.
                    319:        mov     cx, $BUFSIZE            / For block 0, this fills the buffer
                    320:        rep                             / with zeros.
                    321:        stosb
                    322: 
                    323:        / Block #0 is the sparse block--it means a block of all zeros.
                    324:        test    ax, ax                  / if block 0, return zeroed buffer
                    325:        jz      2f
                    326: 
                    327:        / Translate block number into cylinder, head, and sector.
                    328:        push    bx
                    329:        pop     dx
                    330: /      xor     dx, dx                  / extend block number
                    331:        add     ax, first               / add first block
                    332:        adc     dx, first+2             / add rest
                    333: 
                    334:        mov     bx, ax                  / save block number
                    335:        movb    al, heads               / get number of heads
                    336:        movb    cl, sects               / get number of sectors
                    337:        mulb    cl                      / calculate sectors per cylinder
                    338:        xchg    bx,ax                   / swap block/sectors
                    339:        div     bx                      / calculate track
                    340:        xchg    dx, ax                  / put track in DX
                    341:        divb    cl                      / calculate head/sector
                    342: 
                    343:        movb    cl, ah                  / set sector
                    344:        inc     cx                      / sectors start at 1 [incb cl]
                    345:        
                    346:        cmp     dx, traks               / check for second side
                    347:        jb      0f
                    348:        sub     dx, traks               / fold track
                    349:        inc     ax                      / next head [incb al]
                    350: 
                    351: 0:     rorb    dh, $1                  / rotate track(low) into
                    352:        rorb    dh, $1                  /  msbits of DX
                    353:        orb     cl, dh                  / set track(high)
                    354:        movb    ch, dl                  / set track(low)
                    355:        movb    dh, al                  / set head
                    356:        movb    dl, drive               / set drive
                    357:        mov     bx, bp                  / set offset [bbuf]
                    358: 
                    359:        mov     ax, $READ1              / Read, 1 sector.
                    360:        int     DISK                    / Disk I/O.
                    361:        jnc     2f                      / Jump if no error.
                    362:        mov     ax, $READ1              / try again
                    363:        int     DISK
                    364:        jc      error
                    365: 
                    366: 2:     mov     si, bp                  / set SI to point to buffer for return
                    367:        sub     cx, cx                  / clear CX here to save space
                    368: 
                    369:        pop     dx                      / restore registers.
                    370:        pop     di
                    371:        pop     es
                    372:        ret                             / return.
                    373: 
                    374: ////////
                    375: /
                    376: / Print signon message
                    377: /
                    378: ////////
                    379: 
                    380: login: mov     si, $msg00              / point si to message
                    381: 
                    382: print: lodsb                           / al=byte
                    383:        cmpb    al, $LF                 / check for end of message
                    384:        call    putc                    / Type it and
                    385:        jne     print                   / go back for more.
                    386:        ret
                    387: 
                    388: / Prompt with a "?" and read the file name
                    389: / into "nbuf".  No character editing facilites
                    390: / are provided.
                    391: 
                    392: error: mov     sp, bp                  / Reset stack
                    393:        call    login                   / print boot message
                    394: 
                    395: input: mov     di, $nbuf               / di=name buffer pointer
                    396:        mov     cx, $DIRSIZE            / cx=size of
                    397:        movb    al, $'?                 / set prompt
                    398: 0:     call    putc
                    399: 
                    400: 1:     movb    ah, $0                  / Get ASCII opcode.
                    401:        int     KEYBD                   / Read keyboard ROM call.
                    402: 
                    403: 2:     cmpb    al, $CR                 / CR ?
                    404:        je      3f                      / Yup, do next thing
                    405: 
                    406:        jcxz    1b                      / skip over too big name
                    407:        stosb                           / put it into the buffer,
                    408:        dec     cx                      / adjust char count
                    409:        jmp     0b                      / and continue.
                    410: 
                    411: 3:     mov     si, $crlf               / Echo LF followed by CR.
                    412:        call    print
                    413: 
                    414:        movb    al, $0                  / zero out
                    415:        rep
                    416:        stosb                           / rest of name
                    417: 
                    418: ////////
                    419: / This is where we jump after boot has been relocated.
                    420: / 
                    421: / Open "/"; we're going to search for "autoboot".
                    422: ////////
                    423: entry: mov     ax, $ROOTINO            / ax = current inode
                    424:        call    igrab                   / Read in inode and set dx
                    425: 
                    426: ////////
                    427: / Search directory for filename in nbuf.
                    428: / Assume directory size = 64 Kbytes.
                    429: / This assumption works because block numbers
                    430: / from the inode beyond end of file are zero.
                    431: ////////
                    432: 
                    433: search: orb    dl, dl                  / On block boundry ?
                    434:        jnz     0f                      / Nope.
                    435:        call    iread                   / Read block, set si.
                    436: 
                    437: 0:     movb    cl, $DIRSIZE            / cx = count left
                    438:        mov     di, $nbuf               / Point at name buffer and
                    439:        lodsw                           / ax = inumber, this entry.
                    440:        or      ax, ax                  / Empty directory slot ?
                    441:        je      1f                      / Yes, skip.
                    442:        repe                            / compare the
                    443:        cmpsb                           / two file names.
                    444:        je      found                   / If eq, go and get inode.
                    445: 
                    446: 1:     add     si, cx                  / Advance by count remaining.
                    447:        add     dx, $DIRSIZ2+1          / Bump [word] seek pointer
                    448:        jg      search                  / Scan up to 64 Kbytes of directory.
                    449: 
                    450:        jmp     input                   / File not found.
                    451: 
                    452: ////////
                    453: /
                    454: / Found the file so read it in.
                    455: / ax = inode number of file
                    456: /
                    457: ////////
                    458: 
                    459: found: call    igrab                   / read in inode and first block
                    460:        cmp     LMAGIC(si),$LFMAG       / Check the magic number.
                    461:        jne     error                   / not Ok.
                    462: 
                    463: /      push    LBSSD(si)               / Push the uninitialized data size.
                    464: 
                    465:        / Get the total size of shared and private data segments.
                    466:        / They are contigious on disk.  see <l.out.h>
                    467:        mov     ax, LSHRD(si)           / Push the sum
                    468:        add     ax, LPRVD(si)           / of the shared and private
                    469:        push    ax                      / [initialized] data sizes.
                    470:        / If this is not a sep I/D executable, then we
                    471:        / don't want to load the non-existent data segment.
                    472:        andb    LFLAG(si), $LFSEP       / check image flags.
                    473:        pushf                           / Push result of test.
                    474:        mov     ax, LSHRI(si)           / Get the sum of the
                    475:        add     ax, LPRVI(si)           / shared and private code sizes.
                    476: 
                    477:        / Find the start of the first segment on disk.
                    478:        mov     dx, $HDRSIZ2            / Seek after header and
                    479:        add     si, $HDRSIZE            / set buffer pointer appropriately.
                    480:        mov     es, 1f                  / Set ES:DI to point to the load
                    481:        sub     di, di                  / base of the new system.
                    482: 
                    483:        / Load the code segment.
                    484:        call    load                    / Load code.
                    485: 
                    486:        / Skip loading the data segment for non-sep I/D executables.
                    487:        popf                            / Pop sep I/D flag test
                    488:        jz      0f                      / Not sep.
                    489: 
                    490:        / Assertion: at this point we are dealing with a sep I/D
                    491:        / l.out executable.
                    492: 
                    493:        / Calculate load point for data segment.
                    494:        add     di, $15                 / Round up the system code
                    495:        movb    cl, $4                  / size to 16 byte
                    496:        shr     di, cl                  / paragraphs.
                    497:        mov     ax, es                  / fetch program base
                    498:        add     ax, di                  / Compute the data base and
                    499:        mov     es, ax                  / set up ES:DI to point
                    500:        sub     di, di                  / at it.
                    501: 
                    502: 0:     pop     ax                      / Pop off initialized data size and
                    503:        / Load the initialized data segment.
                    504:        call    load                    / load the image.
                    505: 
                    506: /      pop     cx                      / Pop off uninitialized data size and
                    507: /      rep                             / clear it.
                    508: /      stosb
                    509: 
                    510:        / Run the program that we just loaded.
                    511:        .byte   JMPF                    / Jump to offset
                    512:        .word   0x0100                  / 0x0100 (after base) in system
                    513: 1:     .word   SYSBASE                 / code segment.
                    514: 
                    515: ////////
                    516: /
                    517: / Load a segment from an l.out file into memory.
                    518: / The "dx" register holds the
                    519: / seek pointer into the file. The "si" holds
                    520: / a pointer into the "bbuf". The "es:di" pair
                    521: / holds the target address. The "ax" holds
                    522: / the number of bytes to load. On return the
                    523: / "ax" must equal 0 (the caller assumes this
                    524: / and uses "al" to clear the BSS).
                    525: /
                    526: / Note that since the number of bytes to load is
                    527: / stored in a 16 bit register, a segment may be no
                    528: / longer than 64K.  For small model this is just fine.
                    529: ////////
                    530: 
                    531: load:  or      ax, ax                  / Any left ?
                    532:        jz      return                  / Jump if all loaded.
                    533: 
                    534:        mov     cx, $bbuf+BUFSIZE       / Compute the number of bytes
                    535:        sub     cx, si                  / remaining in the block.
                    536:        jnz     0f                      / Jump if some.
                    537: 
                    538:        push    ax                      / Save count registers, then
                    539:        call    iread                   / read the next block
                    540:        pop     ax                      / of the file.
                    541:        mov     cx, $BUFSIZE            / We now have a full block.
                    542: 
                    543: 0:     cmp     cx, ax                  / More than we need ?
                    544:        jbe     1f                      / Nope.
                    545:        mov     cx, ax                  / Only take what we need.
                    546: 
                    547: 1:     sub     ax, cx                  / Fix up the count
                    548:        shr     cx, $1                  /
                    549:        add     dx, cx                  / Fix up the seek [word] address, then
                    550:        rep                             / copy the words from the block
                    551:        movsw                           / buffer to the load point and
                    552:        jmp     load                    / loop until done.
                    553: 
                    554: ////////
                    555: /
                    556: / Write the character in "al" out to
                    557: / the display, using routines in the ROM.
                    558: / Like most calls to the ROM, this routine spends
                    559: / most of its time saving and restoring the
                    560: / registers.
                    561: /
                    562: / Note: The ZF in the PSW word must be preserved.
                    563: /
                    564: ////////
                    565: 
                    566: putc:  push    si                      / Save registers.
                    567:        push    di
                    568:        push    bp
                    569: 
                    570:        mov     bx, $0x0007             / Page 0, white on black
                    571:        movb    ah, $0x0E               / Write TTY.
                    572:        int     0x10                    / Call video I/O in ROM.
                    573: 
                    574:        pop     bp                      / Restore registers.
                    575:        pop     di
                    576:        pop     si
                    577: return: ret                            / Return
                    578: 
                    579: ////////
                    580: /
                    581: / Data. There is some pure data in
                    582: / the "prvd" segment. This data is moved to the
                    583: / new memory when the boot is relocated. All buffers
                    584: / are in the BSS, and are not actually moved, or even
                    585: / saved in the boot block.
                    586: /
                    587: ////////
                    588: 
                    589:        .prvd
                    590: nbuf:  .ascii  "autoboot"              / Name buffer.
                    591:        .blkb   DIRSIZE-8               / rest of buffer (8=sizeof("autoboot"))
                    592: 
                    593: / Defaults for all the following parameters match a floppy disk.
                    594: 
                    595: traks: .word   NTRK    / Number of cylinders on drive we're booting off of.
                    596: sects: .byte   NSPT    / Number of sectors per track for our drive.
                    597: heads: .byte   NHD     / Number of heads on drive we're booting off of.
                    598: 
                    599: drive: .byte   0       / Drive our partition resides upon.
                    600: first: .word   0       / First block of our partition (?)
                    601:        .word   0
                    602: 
                    603: msg00: .ascii  "NATboot"
                    604: crlf:  .byte   CR, LF
                    605: 
                    606: / This magic pair of bytes must be the last two bytes of
                    607: / the sector (address 0x1FE), otherwise mboot will refuse
                    608: / to execute it.
                    609: / If needed, uncomment the .blkb and adjust the number appropriately.
                    610:        .blkb   0x1c    / Padding need to make magic byte line up
                    611:        .byte   0x55,0xAA
                    612: 
                    613:        .bssd
                    614: stack: .blkb   NSTK                    / Local Stack and name buffer
                    615: bbuf:  .blkb   BUFSIZE                 / Block buffer [must follow stack].
                    616: iaddr: .blkw   ND+ND+NIND+NIND         / Inode map words.

unix.superglobalmegacorp.com

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