Annotation of coherent/d/conf/boot/boot.m, revision 1.1

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