summaryrefslogtreecommitdiff
path: root/os/boot/pc/pbsdisk.s
diff options
context:
space:
mode:
Diffstat (limited to 'os/boot/pc/pbsdisk.s')
-rw-r--r--os/boot/pc/pbsdisk.s344
1 files changed, 344 insertions, 0 deletions
diff --git a/os/boot/pc/pbsdisk.s b/os/boot/pc/pbsdisk.s
new file mode 100644
index 00000000..f879e79e
--- /dev/null
+++ b/os/boot/pc/pbsdisk.s
@@ -0,0 +1,344 @@
+/*
+ * 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 */
+
+ /* VMware starts us at 7C0:0. Move to 0:7C00 */
+ PUSHR(rAX)
+ LWI(_nxt(SB), rAX)
+ PUSHR(rAX)
+ BYTE $0xCB /* FAR RET */
+
+TEXT _nxt(SB), $0
+ STI
+ LWI(confidence(SB), rSI) /* for that warm, fuzzy feeling */
+ CALL16(BIOSputs(SB))
+
+ CALL16(dreset(SB))
+
+_jmp00:
+ LW(_volid(SB), rAX) /* Xrootlo */
+ LW(_volid+2(SB), rDX) /* Xroothi */
+
+ LWI(_magic+DIROFF(SB), rBX)
+ CALL16(BIOSread(SB)) /* read the root directory */
+
+ CALL16(printnl(SB))
+ LWI(_magic+DIROFF(SB), rBX)
+ LWI((512/2), rCX)
+ CALL16(printbuf(SB))
+
+xloop:
+ JMP xloop
+
+
+TEXT buggery(SB), $0
+ LWI(error(SB), rSI)
+ CALL16(BIOSputs(SB))
+
+TEXT quietbuggery(SB), $0
+xbuggery:
+ JMP xbuggery
+
+/*
+ * Read a sector from a disc. On entry:
+ * rDX:rAX sector number
+ * rES:rBX buffer address
+ * For BIOSCALL(0x13):
+ * rAH 0x02
+ * rAL number of sectors to read (1)
+ * rCH low 8 bits of cylinder
+ * rCL high 2 bits of cylinder (7-6), sector (5-0)
+ * rDH head
+ * rDL drive
+ * rES:rBX buffer address
+ */
+TEXT BIOSread(SB), $0
+ LWI(5, rDI) /* retry count (ATAPI ZIPs suck) */
+_retry:
+ PUSHA /* may be trashed by BIOSCALL */
+ PUSHR(rBX)
+
+ LW(_trksize(SB), rBX)
+ LW(_nheads(SB), rDI)
+ IMUL(rDI, rBX)
+ OR(rBX, rBX)
+ JZ _ioerror
+
+_okay:
+ DIV(rBX) /* cylinder -> rAX, track,sector -> rDX */
+
+ MW(rAX, rCX) /* save cylinder */
+ ROLI(0x08, rCX) /* swap rC[HL] */
+ SHLBI(0x06, rCL) /* move high bits up */
+
+ MW(rDX, rAX)
+ CLR(rDX)
+ LW(_trksize(SB), rBX)
+
+ DIV(rBX) /* head -> rAX, sector -> rDX */
+
+ INC(rDX) /* sector numbers are 1-based */
+ ANDI(0x003F, rDX) /* should not be necessary */
+ OR(rDX, rCX)
+
+ MW(rAX, rDX)
+ SHLI(0x08, rDX) /* form head */
+ LBPB(Xdrive, rDL) /* form drive */
+
+ POPR(rBX)
+ LWI(0x0201, rAX) /* form command and sectors */
+ BIOSCALL(0x13) /* CF set on failure */
+ JCC _BIOSreadret
+
+ POPA
+ DEC(rDI) /* too many retries? */
+ JEQ _ioerror
+
+ CALL16(dreset(SB))
+ JMP _retry
+
+_ioerror:
+ LWI(ioerror(SB), rSI)
+ CALL16(BIOSputs(SB))
+ JMP xbuggery
+
+_BIOSreadret:
+ POPA
+ RET
+
+TEXT dreset(SB), $0
+ PUSHA
+ CLR(rAX) /* rAH == 0 == reset disc system */
+ LBPB(Xdrive, rDL)
+ BIOSCALL(0x13)
+ ORB(rAH, rAH) /* status (0 == success) */
+ POPA
+ JNE _ioerror
+ RET
+
+TEXT printsharp(SB), $0
+ LWI(sharp(SB), rSI)
+_doprint:
+ CALL16(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)
+ BIOSCALL(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)
+ CALL16(BIOSputs(SB))
+
+ POPW(rDI)
+ POPW(rCX)
+ POPW(rBX)
+ POPW(rAX)
+
+ CALL16(printspace(SB))
+ RET
+
+TEXT printDXAX(SB), $0
+ PUSHW(rAX)
+ MW(rDX, rAX)
+ CALL16(printAX(SB))
+ POPW(rAX)
+ CALL16(printAX(SB))
+ RET
+
+TEXT printBX(SB), $0
+ PUSHW(rAX)
+ MW(rBX, rAX)
+ CALL16(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)
+ CALL16(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';
+
+TEXT confidence(SB), $0
+ BYTE $'P'; BYTE $'\z'