Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * Debugging boot sector.  Reads the first directory
 * sector from disk and displays it.
 *
 * It relies on the _volid field in the FAT header containing
 * the LBA of the root directory.
 */
#include "x16.h"

#define DIROFF          0x00200         /* where to read the root directory (offset) */
#define LOADSEG         (0x10000/16)    /* where to load code (64KB) */
#define LOADOFF         0

/*
 * FAT directory entry.
 */
#define Dname           0x00
#define Dext            0x08
#define Dattr           0x0B
#define Dtime           0x16
#define Ddate           0x18
#define Dstart          0x1A
#define Dlengthlo       0x1C
#define Dlengthhi       0x1E

#define Dirsz           0x20

/*
 * We keep data on the stack, indexed by rBP.
 */
#define Xdrive          0x00            /* boot drive, passed by BIOS in rDL */
#define Xrootlo         0x02            /* offset of root directory */
#define Xroothi         0x04
#define Xrootsz         0x06            /* file data area */
#define Xtotal          0x08            /* sum of allocated data above */
#define Xdap            0x00            /* disc address packet */

TEXT _magic(SB), $0
        BYTE $0xEB; BYTE $0x3C;         /* jmp .+ 0x3C  (_start0x3E) */
        BYTE $0x90                      /* nop */
TEXT _version(SB), $0
        BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
        BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
TEXT _sectsize(SB), $0
        BYTE $0x00; BYTE $0x00
TEXT _clustsize(SB), $0
        BYTE $0x00
TEXT _nresrv(SB), $0
        BYTE $0x00; BYTE $0x00
TEXT _nfats(SB), $0
        BYTE $0x00
TEXT _rootsize(SB), $0
        BYTE $0x00; BYTE $0x00
TEXT _volsize(SB), $0
        BYTE $0x00; BYTE $0x00
TEXT _mediadesc(SB), $0
        BYTE $0x00
TEXT _fatsize(SB), $0
        BYTE $0x00; BYTE $0x00
TEXT _trksize(SB), $0
        BYTE $0x00; BYTE $0x00
TEXT _nheads(SB), $0
        BYTE $0x00; BYTE $0x00
TEXT _nhiddenlo(SB), $0
        BYTE $0x00; BYTE $0x00
TEXT _nhiddenhi(SB), $0
        BYTE $0x00; BYTE $0x00;
TEXT _bigvolsize(SB), $0
        BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
TEXT _driveno(SB), $0
        BYTE $0x00
TEXT _reserved0(SB), $0
        BYTE $0x00
TEXT _bootsig(SB), $0
        BYTE $0x00
TEXT _volid(SB), $0
        BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
TEXT _label(SB), $0
        BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
        BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
        BYTE $0x00; BYTE $0x00; BYTE $0x00
TEXT _type(SB), $0
        BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
        BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;

_start0x3E:
        CLI
        CLR(rAX)
        MTSR(rAX, rSS)                  /* 0000 -> rSS */
        MTSR(rAX, rDS)                  /* 0000 -> rDS, source segment */
        MTSR(rAX, rES)
        LWI(_magic-Xtotal(SB), rSP)
        MW(rSP, rBP)                    /* set the indexed-data pointer */

        SBPB(rDL, Xdrive)               /* save the boot drive */

        STI

        LWI(confidence(SB), rSI)        /* for that warm, fuzzy feeling */
        CALL(BIOSputs(SB))

        LBI(0x41, rAH)                  /* check extensions present */
        LWI(0x55AA, rBX)
        LXB(Xdrive, xBP, rDL)           /* drive */
        SYSCALL(0x13)                   /* CF set on failure */
        JCS _jmp01
        CMPI(0xAA55, rBX)
        JNE _jmp01
        ANDI(0x0001, rCX)
        JEQ _jmp01

                                        /* rCX contains 0x0001 */
        SBPWI(0x0010, Xdap+0)           /* reserved + packet size */
        SBPW(rCX, Xdap+2)               /* reserved + # of blocks to transfer */

        DEC(rCX)
        SBPW(rCX, Xdap+12)
        SBPW(rCX, Xdap+14)

/* BIOSread will do this        CALL(dreset(SB)) */

_jmp00:
        LW(_volid(SB), rAX)             /* Xrootlo */
        LW(_volid+2(SB), rDX)           /* Xroothi */

        LWI(_magic+DIROFF(SB), rBX)
        CALL(BIOSread(SB))              /* read the root directory */

        CALL(printnl(SB))
        LWI(_magic+DIROFF(SB), rBX)
        LWI((512/2), rCX)
        CALL(printbuf(SB))

xloop:
        JMP xloop


_jmp01:

TEXT buggery(SB), $0
        LWI(error(SB), rSI)
        CALL(BIOSputs(SB))

xbuggery:
        JMP xbuggery

/*
 * Read a sector from a disc. On entry:
 *   rDX:rAX    sector number
 *   rES:rBX    buffer address
 */
TEXT BIOSread(SB), $0
        LWI(5, rDI)                     /* retry count (ATAPI ZIPs suck) */
_retry:
        PUSHA                           /* may be trashed by SYSCALL */

        SBPW(rBX, Xdap+4)               /* transfer buffer :offset */
        MFSR(rES, rDI)                  /* transfer buffer seg: */
        SBPW(rDI, Xdap+6)
        SBPW(rAX, Xdap+8)               /* LBA (64-bits) */
        SBPW(rDX, Xdap+10)

        MW(rBP, rSI)                    /* disk address packet */
        LBI(0x42, rAH)                  /* extended read */
        LBPB(Xdrive, rDL)               /* form drive */
        SYSCALL(0x13)                   /* CF set on failure */
        JCC _BIOSreadret

        POPA
        DEC(rDI)                        /* too many retries? */
        JEQ _ioerror

        CALL(dreset(SB))
        JMP _retry

_ioerror:
        LWI(ioerror(SB), rSI)
        CALL(BIOSputs(SB))
        JMP xbuggery

_BIOSreadret:
        POPA
        RET

TEXT dreset(SB), $0
        PUSHA
        CLR(rAX)                        /* rAH == 0 == reset disc system */
        LBPB(Xdrive, rDL)
        SYSCALL(0x13)
        ORB(rAH, rAH)                   /* status (0 == success) */
        POPA
        JNE _ioerror
        RET


TEXT printsharp(SB), $0
        LWI(sharp(SB), rSI)
_doprint:
        CALL(BIOSputs(SB))
        RET

TEXT printspace(SB), $0
        LWI(space(SB), rSI)
        JMP _doprint

TEXT printnl(SB), $0
        LWI(nl(SB), rSI)
        JMP _doprint

/*
 * Output a string to the display.
 * String argument is in rSI.
 */
TEXT BIOSputs(SB), $0
        PUSHA
        CLR(rBX)
_BIOSputs:
        LODSB
        ORB(rAL, rAL)
        JEQ _BIOSputsret

        LBI(0x0E, rAH)
        SYSCALL(0x10)
        JMP _BIOSputs

_BIOSputsret:
        POPA
        RET

/*
 * Output a register to the display.
 */
TEXT printAX(SB), $0
        PUSHW(rAX)
        PUSHW(rBX)
        PUSHW(rCX)
        PUSHW(rDI)

        LWI(4, rCX)
        LWI(numbuf+4(SB), rSI)

_nextchar:
        DEC(rSI)
        MW(rAX, rBX)
        ANDI(0x000F, rBX)
        ADDI(0x30, rBX) /* 0x30 = '0' */
        CMPI(0x39, rBX) /* 0x39 = '9' */
        JLE _dowrite
        ADDI(0x07, rBX) /* 0x07 = 'A'-(1+'9')*/

_dowrite:
        SXB(rBL, 0, xSI)
        SHRI(4, rAX)

        DEC(rCX)
        JNE _nextchar

        LWI(numbuf(SB), rSI)
        CALL(BIOSputs(SB))

        POPW(rDI)
        POPW(rCX)
        POPW(rBX)
        POPW(rAX)

        CALL(printspace(SB))
        RET

TEXT printDXAX(SB), $0
        PUSHW(rAX)
        MW(rDX, rAX)
        CALL(printAX(SB))
        POPW(rAX)
        CALL(printAX(SB))
        RET

TEXT printBX(SB), $0
        PUSHW(rAX)
        MW(rBX, rAX)
        CALL(printAX(SB))
        POPW(rAX)
        RET

/*
 * Output some number of words to the display
 * rDS:rDI - buffer
 * rCX: number of words
 */
TEXT printbuf(SB), $0
        PUSHW(rAX)
        PUSHW(rBX)
        PUSHW(rCX)

_nextword:
        LXW(0, xBX, rAX)
        CALL(printAX(SB))
        INC(rBX)
        INC(rBX)
        DEC(rCX)
        JNE _nextword

        POPW(rCX)
        POPW(rBX)
        POPW(rAX)
        RET

TEXT error(SB), $0
        BYTE $'E'; 

TEXT ioerror(SB), $0
        BYTE $'I'; 

TEXT nl(SB), $0
        BYTE $'\r';
        BYTE $'\n';
        BYTE $'\z';

TEXT numbuf(SB), $0
        BYTE $'X'; BYTE $'X'; BYTE $'X'; BYTE $'X';
        BYTE $'\z';

TEXT space(SB), $0
        BYTE $' ';
        BYTE $'\z';

TEXT sharp(SB), $0
        BYTE $'#'; BYTE $'\z';

Generated by GNU Enscript 1.6.6.