Annotation of coherent/d/conf/boot.s, revision 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.