1*42dedc50SDavid du Colombier/* 2*42dedc50SDavid du Colombier * Debugging boot sector. Reads the first directory 3*42dedc50SDavid du Colombier * sector from disk and displays it. 4*42dedc50SDavid du Colombier * 5*42dedc50SDavid du Colombier * It relies on the _volid field in the FAT header containing 6*42dedc50SDavid du Colombier * the LBA of the root directory. 7*42dedc50SDavid du Colombier */ 8*42dedc50SDavid du Colombier#include "x16.h" 9*42dedc50SDavid du Colombier 10*42dedc50SDavid du Colombier#define DIROFF 0x00200 /* where to read the root directory (offset) */ 11*42dedc50SDavid du Colombier#define LOADSEG (0x10000/16) /* where to load code (64KB) */ 12*42dedc50SDavid du Colombier#define LOADOFF 0 13*42dedc50SDavid du Colombier 14*42dedc50SDavid du Colombier/* 15*42dedc50SDavid du Colombier * FAT directory entry. 16*42dedc50SDavid du Colombier */ 17*42dedc50SDavid du Colombier#define Dname 0x00 18*42dedc50SDavid du Colombier#define Dext 0x08 19*42dedc50SDavid du Colombier#define Dattr 0x0B 20*42dedc50SDavid du Colombier#define Dtime 0x16 21*42dedc50SDavid du Colombier#define Ddate 0x18 22*42dedc50SDavid du Colombier#define Dstart 0x1A 23*42dedc50SDavid du Colombier#define Dlengthlo 0x1C 24*42dedc50SDavid du Colombier#define Dlengthhi 0x1E 25*42dedc50SDavid du Colombier 26*42dedc50SDavid du Colombier#define Dirsz 0x20 27*42dedc50SDavid du Colombier 28*42dedc50SDavid du Colombier/* 29*42dedc50SDavid du Colombier * We keep data on the stack, indexed by rBP. 30*42dedc50SDavid du Colombier */ 31*42dedc50SDavid du Colombier#define Xdrive 0x00 /* boot drive, passed by BIOS in rDL */ 32*42dedc50SDavid du Colombier#define Xrootlo 0x02 /* offset of root directory */ 33*42dedc50SDavid du Colombier#define Xroothi 0x04 34*42dedc50SDavid du Colombier#define Xrootsz 0x06 /* file data area */ 35*42dedc50SDavid du Colombier#define Xtotal 0x08 /* sum of allocated data above */ 36*42dedc50SDavid du Colombier#define Xdap 0x00 /* disc address packet */ 37*42dedc50SDavid du Colombier 38*42dedc50SDavid du ColombierTEXT _magic(SB), $0 39*42dedc50SDavid du Colombier BYTE $0xEB; BYTE $0x3C; /* jmp .+ 0x3C (_start0x3E) */ 40*42dedc50SDavid du Colombier BYTE $0x90 /* nop */ 41*42dedc50SDavid du ColombierTEXT _version(SB), $0 42*42dedc50SDavid du Colombier BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; 43*42dedc50SDavid du Colombier BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00 44*42dedc50SDavid du ColombierTEXT _sectsize(SB), $0 45*42dedc50SDavid du Colombier BYTE $0x00; BYTE $0x00 46*42dedc50SDavid du ColombierTEXT _clustsize(SB), $0 47*42dedc50SDavid du Colombier BYTE $0x00 48*42dedc50SDavid du ColombierTEXT _nresrv(SB), $0 49*42dedc50SDavid du Colombier BYTE $0x00; BYTE $0x00 50*42dedc50SDavid du ColombierTEXT _nfats(SB), $0 51*42dedc50SDavid du Colombier BYTE $0x00 52*42dedc50SDavid du ColombierTEXT _rootsize(SB), $0 53*42dedc50SDavid du Colombier BYTE $0x00; BYTE $0x00 54*42dedc50SDavid du ColombierTEXT _volsize(SB), $0 55*42dedc50SDavid du Colombier BYTE $0x00; BYTE $0x00 56*42dedc50SDavid du ColombierTEXT _mediadesc(SB), $0 57*42dedc50SDavid du Colombier BYTE $0x00 58*42dedc50SDavid du ColombierTEXT _fatsize(SB), $0 59*42dedc50SDavid du Colombier BYTE $0x00; BYTE $0x00 60*42dedc50SDavid du ColombierTEXT _trksize(SB), $0 61*42dedc50SDavid du Colombier BYTE $0x00; BYTE $0x00 62*42dedc50SDavid du ColombierTEXT _nheads(SB), $0 63*42dedc50SDavid du Colombier BYTE $0x00; BYTE $0x00 64*42dedc50SDavid du ColombierTEXT _nhiddenlo(SB), $0 65*42dedc50SDavid du Colombier BYTE $0x00; BYTE $0x00 66*42dedc50SDavid du ColombierTEXT _nhiddenhi(SB), $0 67*42dedc50SDavid du Colombier BYTE $0x00; BYTE $0x00; 68*42dedc50SDavid du ColombierTEXT _bigvolsize(SB), $0 69*42dedc50SDavid du Colombier BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; 70*42dedc50SDavid du ColombierTEXT _driveno(SB), $0 71*42dedc50SDavid du Colombier BYTE $0x00 72*42dedc50SDavid du ColombierTEXT _reserved0(SB), $0 73*42dedc50SDavid du Colombier BYTE $0x00 74*42dedc50SDavid du ColombierTEXT _bootsig(SB), $0 75*42dedc50SDavid du Colombier BYTE $0x00 76*42dedc50SDavid du ColombierTEXT _volid(SB), $0 77*42dedc50SDavid du Colombier BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; 78*42dedc50SDavid du ColombierTEXT _label(SB), $0 79*42dedc50SDavid du Colombier BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; 80*42dedc50SDavid du Colombier BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00 81*42dedc50SDavid du Colombier BYTE $0x00; BYTE $0x00; BYTE $0x00 82*42dedc50SDavid du ColombierTEXT _type(SB), $0 83*42dedc50SDavid du Colombier BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; 84*42dedc50SDavid du Colombier BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; 85*42dedc50SDavid du Colombier 86*42dedc50SDavid du Colombier_start0x3E: 87*42dedc50SDavid du Colombier CLI 88*42dedc50SDavid du Colombier CLR(rAX) 89*42dedc50SDavid du Colombier MTSR(rAX, rSS) /* 0000 -> rSS */ 90*42dedc50SDavid du Colombier MTSR(rAX, rDS) /* 0000 -> rDS, source segment */ 91*42dedc50SDavid du Colombier MTSR(rAX, rES) 92*42dedc50SDavid du Colombier LWI(_magic-Xtotal(SB), rSP) 93*42dedc50SDavid du Colombier MW(rSP, rBP) /* set the indexed-data pointer */ 94*42dedc50SDavid du Colombier 95*42dedc50SDavid du Colombier SBPB(rDL, Xdrive) /* save the boot drive */ 96*42dedc50SDavid du Colombier 97*42dedc50SDavid du Colombier STI 98*42dedc50SDavid du Colombier 99*42dedc50SDavid du Colombier LWI(confidence(SB), rSI) /* for that warm, fuzzy feeling */ 100*42dedc50SDavid du Colombier CALL(BIOSputs(SB)) 101*42dedc50SDavid du Colombier 102*42dedc50SDavid du Colombier LBI(0x41, rAH) /* check extensions present */ 103*42dedc50SDavid du Colombier LWI(0x55AA, rBX) 104*42dedc50SDavid du Colombier LXB(Xdrive, xBP, rDL) /* drive */ 105*42dedc50SDavid du Colombier SYSCALL(0x13) /* CF set on failure */ 106*42dedc50SDavid du Colombier JCS _jmp01 107*42dedc50SDavid du Colombier CMPI(0xAA55, rBX) 108*42dedc50SDavid du Colombier JNE _jmp01 109*42dedc50SDavid du Colombier ANDI(0x0001, rCX) 110*42dedc50SDavid du Colombier JEQ _jmp01 111*42dedc50SDavid du Colombier 112*42dedc50SDavid du Colombier /* rCX contains 0x0001 */ 113*42dedc50SDavid du Colombier SBPWI(0x0010, Xdap+0) /* reserved + packet size */ 114*42dedc50SDavid du Colombier SBPW(rCX, Xdap+2) /* reserved + # of blocks to transfer */ 115*42dedc50SDavid du Colombier 116*42dedc50SDavid du Colombier DEC(rCX) 117*42dedc50SDavid du Colombier SBPW(rCX, Xdap+12) 118*42dedc50SDavid du Colombier SBPW(rCX, Xdap+14) 119*42dedc50SDavid du Colombier 120*42dedc50SDavid du Colombier/* BIOSread will do this CALL(dreset(SB)) */ 121*42dedc50SDavid du Colombier 122*42dedc50SDavid du Colombier_jmp00: 123*42dedc50SDavid du Colombier LW(_volid(SB), rAX) /* Xrootlo */ 124*42dedc50SDavid du Colombier LW(_volid+2(SB), rDX) /* Xroothi */ 125*42dedc50SDavid du Colombier 126*42dedc50SDavid du Colombier LWI(_magic+DIROFF(SB), rBX) 127*42dedc50SDavid du Colombier CALL(BIOSread(SB)) /* read the root directory */ 128*42dedc50SDavid du Colombier 129*42dedc50SDavid du Colombier CALL(printnl(SB)) 130*42dedc50SDavid du Colombier LWI(_magic+DIROFF(SB), rBX) 131*42dedc50SDavid du Colombier LWI((512/2), rCX) 132*42dedc50SDavid du Colombier CALL(printbuf(SB)) 133*42dedc50SDavid du Colombier 134*42dedc50SDavid du Colombierxloop: 135*42dedc50SDavid du Colombier JMP xloop 136*42dedc50SDavid du Colombier 137*42dedc50SDavid du Colombier 138*42dedc50SDavid du Colombier_jmp01: 139*42dedc50SDavid du Colombier 140*42dedc50SDavid du ColombierTEXT buggery(SB), $0 141*42dedc50SDavid du Colombier LWI(error(SB), rSI) 142*42dedc50SDavid du Colombier CALL(BIOSputs(SB)) 143*42dedc50SDavid du Colombier 144*42dedc50SDavid du Colombierxbuggery: 145*42dedc50SDavid du Colombier JMP xbuggery 146*42dedc50SDavid du Colombier 147*42dedc50SDavid du Colombier/* 148*42dedc50SDavid du Colombier * Read a sector from a disc. On entry: 149*42dedc50SDavid du Colombier * rDX:rAX sector number 150*42dedc50SDavid du Colombier * rES:rBX buffer address 151*42dedc50SDavid du Colombier */ 152*42dedc50SDavid du ColombierTEXT BIOSread(SB), $0 153*42dedc50SDavid du Colombier LWI(5, rDI) /* retry count (ATAPI ZIPs suck) */ 154*42dedc50SDavid du Colombier_retry: 155*42dedc50SDavid du Colombier PUSHA /* may be trashed by SYSCALL */ 156*42dedc50SDavid du Colombier 157*42dedc50SDavid du Colombier SBPW(rBX, Xdap+4) /* transfer buffer :offset */ 158*42dedc50SDavid du Colombier MFSR(rES, rDI) /* transfer buffer seg: */ 159*42dedc50SDavid du Colombier SBPW(rDI, Xdap+6) 160*42dedc50SDavid du Colombier SBPW(rAX, Xdap+8) /* LBA (64-bits) */ 161*42dedc50SDavid du Colombier SBPW(rDX, Xdap+10) 162*42dedc50SDavid du Colombier 163*42dedc50SDavid du Colombier MW(rBP, rSI) /* disk address packet */ 164*42dedc50SDavid du Colombier LBI(0x42, rAH) /* extended read */ 165*42dedc50SDavid du Colombier LBPB(Xdrive, rDL) /* form drive */ 166*42dedc50SDavid du Colombier SYSCALL(0x13) /* CF set on failure */ 167*42dedc50SDavid du Colombier JCC _BIOSreadret 168*42dedc50SDavid du Colombier 169*42dedc50SDavid du Colombier POPA 170*42dedc50SDavid du Colombier DEC(rDI) /* too many retries? */ 171*42dedc50SDavid du Colombier JEQ _ioerror 172*42dedc50SDavid du Colombier 173*42dedc50SDavid du Colombier CALL(dreset(SB)) 174*42dedc50SDavid du Colombier JMP _retry 175*42dedc50SDavid du Colombier 176*42dedc50SDavid du Colombier_ioerror: 177*42dedc50SDavid du Colombier LWI(ioerror(SB), rSI) 178*42dedc50SDavid du Colombier CALL(BIOSputs(SB)) 179*42dedc50SDavid du Colombier JMP xbuggery 180*42dedc50SDavid du Colombier 181*42dedc50SDavid du Colombier_BIOSreadret: 182*42dedc50SDavid du Colombier POPA 183*42dedc50SDavid du Colombier RET 184*42dedc50SDavid du Colombier 185*42dedc50SDavid du ColombierTEXT dreset(SB), $0 186*42dedc50SDavid du Colombier PUSHA 187*42dedc50SDavid du Colombier CLR(rAX) /* rAH == 0 == reset disc system */ 188*42dedc50SDavid du Colombier LBPB(Xdrive, rDL) 189*42dedc50SDavid du Colombier SYSCALL(0x13) 190*42dedc50SDavid du Colombier ORB(rAH, rAH) /* status (0 == success) */ 191*42dedc50SDavid du Colombier POPA 192*42dedc50SDavid du Colombier JNE _ioerror 193*42dedc50SDavid du Colombier RET 194*42dedc50SDavid du Colombier 195*42dedc50SDavid du Colombier 196*42dedc50SDavid du ColombierTEXT printsharp(SB), $0 197*42dedc50SDavid du Colombier LWI(sharp(SB), rSI) 198*42dedc50SDavid du Colombier_doprint: 199*42dedc50SDavid du Colombier CALL(BIOSputs(SB)) 200*42dedc50SDavid du Colombier RET 201*42dedc50SDavid du Colombier 202*42dedc50SDavid du ColombierTEXT printspace(SB), $0 203*42dedc50SDavid du Colombier LWI(space(SB), rSI) 204*42dedc50SDavid du Colombier JMP _doprint 205*42dedc50SDavid du Colombier 206*42dedc50SDavid du ColombierTEXT printnl(SB), $0 207*42dedc50SDavid du Colombier LWI(nl(SB), rSI) 208*42dedc50SDavid du Colombier JMP _doprint 209*42dedc50SDavid du Colombier 210*42dedc50SDavid du Colombier/* 211*42dedc50SDavid du Colombier * Output a string to the display. 212*42dedc50SDavid du Colombier * String argument is in rSI. 213*42dedc50SDavid du Colombier */ 214*42dedc50SDavid du ColombierTEXT BIOSputs(SB), $0 215*42dedc50SDavid du Colombier PUSHA 216*42dedc50SDavid du Colombier CLR(rBX) 217*42dedc50SDavid du Colombier_BIOSputs: 218*42dedc50SDavid du Colombier LODSB 219*42dedc50SDavid du Colombier ORB(rAL, rAL) 220*42dedc50SDavid du Colombier JEQ _BIOSputsret 221*42dedc50SDavid du Colombier 222*42dedc50SDavid du Colombier LBI(0x0E, rAH) 223*42dedc50SDavid du Colombier SYSCALL(0x10) 224*42dedc50SDavid du Colombier JMP _BIOSputs 225*42dedc50SDavid du Colombier 226*42dedc50SDavid du Colombier_BIOSputsret: 227*42dedc50SDavid du Colombier POPA 228*42dedc50SDavid du Colombier RET 229*42dedc50SDavid du Colombier 230*42dedc50SDavid du Colombier/* 231*42dedc50SDavid du Colombier * Output a register to the display. 232*42dedc50SDavid du Colombier */ 233*42dedc50SDavid du ColombierTEXT printAX(SB), $0 234*42dedc50SDavid du Colombier PUSHW(rAX) 235*42dedc50SDavid du Colombier PUSHW(rBX) 236*42dedc50SDavid du Colombier PUSHW(rCX) 237*42dedc50SDavid du Colombier PUSHW(rDI) 238*42dedc50SDavid du Colombier 239*42dedc50SDavid du Colombier LWI(4, rCX) 240*42dedc50SDavid du Colombier LWI(numbuf+4(SB), rSI) 241*42dedc50SDavid du Colombier 242*42dedc50SDavid du Colombier_nextchar: 243*42dedc50SDavid du Colombier DEC(rSI) 244*42dedc50SDavid du Colombier MW(rAX, rBX) 245*42dedc50SDavid du Colombier ANDI(0x000F, rBX) 246*42dedc50SDavid du Colombier ADDI(0x30, rBX) /* 0x30 = '0' */ 247*42dedc50SDavid du Colombier CMPI(0x39, rBX) /* 0x39 = '9' */ 248*42dedc50SDavid du Colombier JLE _dowrite 249*42dedc50SDavid du Colombier ADDI(0x07, rBX) /* 0x07 = 'A'-(1+'9')*/ 250*42dedc50SDavid du Colombier 251*42dedc50SDavid du Colombier_dowrite: 252*42dedc50SDavid du Colombier SXB(rBL, 0, xSI) 253*42dedc50SDavid du Colombier SHRI(4, rAX) 254*42dedc50SDavid du Colombier 255*42dedc50SDavid du Colombier DEC(rCX) 256*42dedc50SDavid du Colombier JNE _nextchar 257*42dedc50SDavid du Colombier 258*42dedc50SDavid du Colombier LWI(numbuf(SB), rSI) 259*42dedc50SDavid du Colombier CALL(BIOSputs(SB)) 260*42dedc50SDavid du Colombier 261*42dedc50SDavid du Colombier POPW(rDI) 262*42dedc50SDavid du Colombier POPW(rCX) 263*42dedc50SDavid du Colombier POPW(rBX) 264*42dedc50SDavid du Colombier POPW(rAX) 265*42dedc50SDavid du Colombier 266*42dedc50SDavid du Colombier CALL(printspace(SB)) 267*42dedc50SDavid du Colombier RET 268*42dedc50SDavid du Colombier 269*42dedc50SDavid du ColombierTEXT printDXAX(SB), $0 270*42dedc50SDavid du Colombier PUSHW(rAX) 271*42dedc50SDavid du Colombier MW(rDX, rAX) 272*42dedc50SDavid du Colombier CALL(printAX(SB)) 273*42dedc50SDavid du Colombier POPW(rAX) 274*42dedc50SDavid du Colombier CALL(printAX(SB)) 275*42dedc50SDavid du Colombier RET 276*42dedc50SDavid du Colombier 277*42dedc50SDavid du ColombierTEXT printBX(SB), $0 278*42dedc50SDavid du Colombier PUSHW(rAX) 279*42dedc50SDavid du Colombier MW(rBX, rAX) 280*42dedc50SDavid du Colombier CALL(printAX(SB)) 281*42dedc50SDavid du Colombier POPW(rAX) 282*42dedc50SDavid du Colombier RET 283*42dedc50SDavid du Colombier 284*42dedc50SDavid du Colombier/* 285*42dedc50SDavid du Colombier * Output some number of words to the display 286*42dedc50SDavid du Colombier * rDS:rDI - buffer 287*42dedc50SDavid du Colombier * rCX: number of words 288*42dedc50SDavid du Colombier */ 289*42dedc50SDavid du ColombierTEXT printbuf(SB), $0 290*42dedc50SDavid du Colombier PUSHW(rAX) 291*42dedc50SDavid du Colombier PUSHW(rBX) 292*42dedc50SDavid du Colombier PUSHW(rCX) 293*42dedc50SDavid du Colombier 294*42dedc50SDavid du Colombier_nextword: 295*42dedc50SDavid du Colombier LXW(0, xBX, rAX) 296*42dedc50SDavid du Colombier CALL(printAX(SB)) 297*42dedc50SDavid du Colombier INC(rBX) 298*42dedc50SDavid du Colombier INC(rBX) 299*42dedc50SDavid du Colombier DEC(rCX) 300*42dedc50SDavid du Colombier JNE _nextword 301*42dedc50SDavid du Colombier 302*42dedc50SDavid du Colombier POPW(rCX) 303*42dedc50SDavid du Colombier POPW(rBX) 304*42dedc50SDavid du Colombier POPW(rAX) 305*42dedc50SDavid du Colombier RET 306*42dedc50SDavid du Colombier 307*42dedc50SDavid du ColombierTEXT error(SB), $0 308*42dedc50SDavid du Colombier BYTE $'E'; 309*42dedc50SDavid du Colombier 310*42dedc50SDavid du ColombierTEXT ioerror(SB), $0 311*42dedc50SDavid du Colombier BYTE $'I'; 312*42dedc50SDavid du Colombier 313*42dedc50SDavid du ColombierTEXT nl(SB), $0 314*42dedc50SDavid du Colombier BYTE $'\r'; 315*42dedc50SDavid du Colombier BYTE $'\n'; 316*42dedc50SDavid du Colombier BYTE $'\z'; 317*42dedc50SDavid du Colombier 318*42dedc50SDavid du ColombierTEXT numbuf(SB), $0 319*42dedc50SDavid du Colombier BYTE $'X'; BYTE $'X'; BYTE $'X'; BYTE $'X'; 320*42dedc50SDavid du Colombier BYTE $'\z'; 321*42dedc50SDavid du Colombier 322*42dedc50SDavid du ColombierTEXT space(SB), $0 323*42dedc50SDavid du Colombier BYTE $' '; 324*42dedc50SDavid du Colombier BYTE $'\z'; 325*42dedc50SDavid du Colombier 326*42dedc50SDavid du ColombierTEXT sharp(SB), $0 327*42dedc50SDavid du Colombier BYTE $'#'; BYTE $'\z'; 328