summaryrefslogtreecommitdiff
path: root/os/boot/pc/pbsdisklba.s
diff options
context:
space:
mode:
Diffstat (limited to 'os/boot/pc/pbsdisklba.s')
-rw-r--r--os/boot/pc/pbsdisklba.s327
1 files changed, 327 insertions, 0 deletions
diff --git a/os/boot/pc/pbsdisklba.s b/os/boot/pc/pbsdisklba.s
new file mode 100644
index 00000000..357abd00
--- /dev/null
+++ b/os/boot/pc/pbsdisklba.s
@@ -0,0 +1,327 @@
+/*
+ * 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 */
+ SBPWI(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';