diff options
Diffstat (limited to 'os/boot/pc/pbsdisklba.s')
| -rw-r--r-- | os/boot/pc/pbsdisklba.s | 327 |
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'; |
