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 SBPB(rDL, Xdrive) /* save the boot drive */ 95*42dedc50SDavid du Colombier 96*42dedc50SDavid du Colombier /* VMware starts us at 7C0:0. Move to 0:7C00 */ 97*42dedc50SDavid du Colombier PUSHR(rAX) 98*42dedc50SDavid du Colombier LWI(_nxt(SB), rAX) 99*42dedc50SDavid du Colombier PUSHR(rAX) 100*42dedc50SDavid du Colombier BYTE $0xCB /* FAR RET */ 101*42dedc50SDavid du Colombier 102*42dedc50SDavid du ColombierTEXT _nxt(SB), $0 103*42dedc50SDavid du Colombier STI 104*42dedc50SDavid du Colombier LWI(confidence(SB), rSI) /* for that warm, fuzzy feeling */ 105*42dedc50SDavid du Colombier CALL16(BIOSputs(SB)) 106*42dedc50SDavid du Colombier 107*42dedc50SDavid du Colombier CALL16(dreset(SB)) 108*42dedc50SDavid du Colombier 109*42dedc50SDavid du Colombier_jmp00: 110*42dedc50SDavid du Colombier LW(_volid(SB), rAX) /* Xrootlo */ 111*42dedc50SDavid du Colombier LW(_volid+2(SB), rDX) /* Xroothi */ 112*42dedc50SDavid du Colombier 113*42dedc50SDavid du Colombier LWI(_magic+DIROFF(SB), rBX) 114*42dedc50SDavid du Colombier CALL16(BIOSread(SB)) /* read the root directory */ 115*42dedc50SDavid du Colombier 116*42dedc50SDavid du Colombier CALL16(printnl(SB)) 117*42dedc50SDavid du Colombier LWI(_magic+DIROFF(SB), rBX) 118*42dedc50SDavid du Colombier LWI((512/2), rCX) 119*42dedc50SDavid du Colombier CALL16(printbuf(SB)) 120*42dedc50SDavid du Colombier 121*42dedc50SDavid du Colombierxloop: 122*42dedc50SDavid du Colombier JMP xloop 123*42dedc50SDavid du Colombier 124*42dedc50SDavid du Colombier 125*42dedc50SDavid du ColombierTEXT buggery(SB), $0 126*42dedc50SDavid du Colombier LWI(error(SB), rSI) 127*42dedc50SDavid du Colombier CALL16(BIOSputs(SB)) 128*42dedc50SDavid du Colombier 129*42dedc50SDavid du ColombierTEXT quietbuggery(SB), $0 130*42dedc50SDavid du Colombierxbuggery: 131*42dedc50SDavid du Colombier JMP xbuggery 132*42dedc50SDavid du Colombier 133*42dedc50SDavid du Colombier/* 134*42dedc50SDavid du Colombier * Read a sector from a disc. On entry: 135*42dedc50SDavid du Colombier * rDX:rAX sector number 136*42dedc50SDavid du Colombier * rES:rBX buffer address 137*42dedc50SDavid du Colombier * For BIOSCALL(0x13): 138*42dedc50SDavid du Colombier * rAH 0x02 139*42dedc50SDavid du Colombier * rAL number of sectors to read (1) 140*42dedc50SDavid du Colombier * rCH low 8 bits of cylinder 141*42dedc50SDavid du Colombier * rCL high 2 bits of cylinder (7-6), sector (5-0) 142*42dedc50SDavid du Colombier * rDH head 143*42dedc50SDavid du Colombier * rDL drive 144*42dedc50SDavid du Colombier * rES:rBX buffer address 145*42dedc50SDavid du Colombier */ 146*42dedc50SDavid du ColombierTEXT BIOSread(SB), $0 147*42dedc50SDavid du Colombier LWI(5, rDI) /* retry count (ATAPI ZIPs suck) */ 148*42dedc50SDavid du Colombier_retry: 149*42dedc50SDavid du Colombier PUSHA /* may be trashed by BIOSCALL */ 150*42dedc50SDavid du Colombier PUSHR(rBX) 151*42dedc50SDavid du Colombier 152*42dedc50SDavid du Colombier LW(_trksize(SB), rBX) 153*42dedc50SDavid du Colombier LW(_nheads(SB), rDI) 154*42dedc50SDavid du Colombier IMUL(rDI, rBX) 155*42dedc50SDavid du Colombier OR(rBX, rBX) 156*42dedc50SDavid du Colombier JZ _ioerror 157*42dedc50SDavid du Colombier 158*42dedc50SDavid du Colombier_okay: 159*42dedc50SDavid du Colombier DIV(rBX) /* cylinder -> rAX, track,sector -> rDX */ 160*42dedc50SDavid du Colombier 161*42dedc50SDavid du Colombier MW(rAX, rCX) /* save cylinder */ 162*42dedc50SDavid du Colombier ROLI(0x08, rCX) /* swap rC[HL] */ 163*42dedc50SDavid du Colombier SHLBI(0x06, rCL) /* move high bits up */ 164*42dedc50SDavid du Colombier 165*42dedc50SDavid du Colombier MW(rDX, rAX) 166*42dedc50SDavid du Colombier CLR(rDX) 167*42dedc50SDavid du Colombier LW(_trksize(SB), rBX) 168*42dedc50SDavid du Colombier 169*42dedc50SDavid du Colombier DIV(rBX) /* head -> rAX, sector -> rDX */ 170*42dedc50SDavid du Colombier 171*42dedc50SDavid du Colombier INC(rDX) /* sector numbers are 1-based */ 172*42dedc50SDavid du Colombier ANDI(0x003F, rDX) /* should not be necessary */ 173*42dedc50SDavid du Colombier OR(rDX, rCX) 174*42dedc50SDavid du Colombier 175*42dedc50SDavid du Colombier MW(rAX, rDX) 176*42dedc50SDavid du Colombier SHLI(0x08, rDX) /* form head */ 177*42dedc50SDavid du Colombier LBPB(Xdrive, rDL) /* form drive */ 178*42dedc50SDavid du Colombier 179*42dedc50SDavid du Colombier POPR(rBX) 180*42dedc50SDavid du Colombier LWI(0x0201, rAX) /* form command and sectors */ 181*42dedc50SDavid du Colombier BIOSCALL(0x13) /* CF set on failure */ 182*42dedc50SDavid du Colombier JCC _BIOSreadret 183*42dedc50SDavid du Colombier 184*42dedc50SDavid du Colombier POPA 185*42dedc50SDavid du Colombier DEC(rDI) /* too many retries? */ 186*42dedc50SDavid du Colombier JEQ _ioerror 187*42dedc50SDavid du Colombier 188*42dedc50SDavid du Colombier CALL16(dreset(SB)) 189*42dedc50SDavid du Colombier JMP _retry 190*42dedc50SDavid du Colombier 191*42dedc50SDavid du Colombier_ioerror: 192*42dedc50SDavid du Colombier LWI(ioerror(SB), rSI) 193*42dedc50SDavid du Colombier CALL16(BIOSputs(SB)) 194*42dedc50SDavid du Colombier JMP xbuggery 195*42dedc50SDavid du Colombier 196*42dedc50SDavid du Colombier_BIOSreadret: 197*42dedc50SDavid du Colombier POPA 198*42dedc50SDavid du Colombier RET 199*42dedc50SDavid du Colombier 200*42dedc50SDavid du ColombierTEXT dreset(SB), $0 201*42dedc50SDavid du Colombier PUSHA 202*42dedc50SDavid du Colombier CLR(rAX) /* rAH == 0 == reset disc system */ 203*42dedc50SDavid du Colombier LBPB(Xdrive, rDL) 204*42dedc50SDavid du Colombier BIOSCALL(0x13) 205*42dedc50SDavid du Colombier ORB(rAH, rAH) /* status (0 == success) */ 206*42dedc50SDavid du Colombier POPA 207*42dedc50SDavid du Colombier JNE _ioerror 208*42dedc50SDavid du Colombier RET 209*42dedc50SDavid du Colombier 210*42dedc50SDavid du ColombierTEXT printsharp(SB), $0 211*42dedc50SDavid du Colombier LWI(sharp(SB), rSI) 212*42dedc50SDavid du Colombier_doprint: 213*42dedc50SDavid du Colombier CALL16(BIOSputs(SB)) 214*42dedc50SDavid du Colombier RET 215*42dedc50SDavid du Colombier 216*42dedc50SDavid du ColombierTEXT printspace(SB), $0 217*42dedc50SDavid du Colombier LWI(space(SB), rSI) 218*42dedc50SDavid du Colombier JMP _doprint 219*42dedc50SDavid du Colombier 220*42dedc50SDavid du ColombierTEXT printnl(SB), $0 221*42dedc50SDavid du Colombier LWI(nl(SB), rSI) 222*42dedc50SDavid du Colombier JMP _doprint 223*42dedc50SDavid du Colombier 224*42dedc50SDavid du Colombier/* 225*42dedc50SDavid du Colombier * Output a string to the display. 226*42dedc50SDavid du Colombier * String argument is in rSI. 227*42dedc50SDavid du Colombier */ 228*42dedc50SDavid du ColombierTEXT BIOSputs(SB), $0 229*42dedc50SDavid du Colombier PUSHA 230*42dedc50SDavid du Colombier CLR(rBX) 231*42dedc50SDavid du Colombier_BIOSputs: 232*42dedc50SDavid du Colombier LODSB 233*42dedc50SDavid du Colombier ORB(rAL, rAL) 234*42dedc50SDavid du Colombier JEQ _BIOSputsret 235*42dedc50SDavid du Colombier 236*42dedc50SDavid du Colombier LBI(0x0E, rAH) 237*42dedc50SDavid du Colombier BIOSCALL(0x10) 238*42dedc50SDavid du Colombier JMP _BIOSputs 239*42dedc50SDavid du Colombier 240*42dedc50SDavid du Colombier_BIOSputsret: 241*42dedc50SDavid du Colombier POPA 242*42dedc50SDavid du Colombier RET 243*42dedc50SDavid du Colombier 244*42dedc50SDavid du Colombier/* 245*42dedc50SDavid du Colombier * Output a register to the display. 246*42dedc50SDavid du Colombier */ 247*42dedc50SDavid du ColombierTEXT printAX(SB), $0 248*42dedc50SDavid du Colombier PUSHW(rAX) 249*42dedc50SDavid du Colombier PUSHW(rBX) 250*42dedc50SDavid du Colombier PUSHW(rCX) 251*42dedc50SDavid du Colombier PUSHW(rDI) 252*42dedc50SDavid du Colombier 253*42dedc50SDavid du Colombier LWI(4, rCX) 254*42dedc50SDavid du Colombier LWI(numbuf+4(SB), rSI) 255*42dedc50SDavid du Colombier 256*42dedc50SDavid du Colombier_nextchar: 257*42dedc50SDavid du Colombier DEC(rSI) 258*42dedc50SDavid du Colombier MW(rAX, rBX) 259*42dedc50SDavid du Colombier ANDI(0x000F, rBX) 260*42dedc50SDavid du Colombier ADDI(0x30, rBX) /* 0x30 = '0' */ 261*42dedc50SDavid du Colombier CMPI(0x39, rBX) /* 0x39 = '9' */ 262*42dedc50SDavid du Colombier JLE _dowrite 263*42dedc50SDavid du Colombier ADDI(0x07, rBX) /* 0x07 = 'A'-(1+'9')*/ 264*42dedc50SDavid du Colombier 265*42dedc50SDavid du Colombier_dowrite: 266*42dedc50SDavid du Colombier SXB(rBL, 0, xSI) 267*42dedc50SDavid du Colombier SHRI(4, rAX) 268*42dedc50SDavid du Colombier 269*42dedc50SDavid du Colombier DEC(rCX) 270*42dedc50SDavid du Colombier JNE _nextchar 271*42dedc50SDavid du Colombier 272*42dedc50SDavid du Colombier LWI(numbuf(SB), rSI) 273*42dedc50SDavid du Colombier CALL16(BIOSputs(SB)) 274*42dedc50SDavid du Colombier 275*42dedc50SDavid du Colombier POPW(rDI) 276*42dedc50SDavid du Colombier POPW(rCX) 277*42dedc50SDavid du Colombier POPW(rBX) 278*42dedc50SDavid du Colombier POPW(rAX) 279*42dedc50SDavid du Colombier 280*42dedc50SDavid du Colombier CALL16(printspace(SB)) 281*42dedc50SDavid du Colombier RET 282*42dedc50SDavid du Colombier 283*42dedc50SDavid du ColombierTEXT printDXAX(SB), $0 284*42dedc50SDavid du Colombier PUSHW(rAX) 285*42dedc50SDavid du Colombier MW(rDX, rAX) 286*42dedc50SDavid du Colombier CALL16(printAX(SB)) 287*42dedc50SDavid du Colombier POPW(rAX) 288*42dedc50SDavid du Colombier CALL16(printAX(SB)) 289*42dedc50SDavid du Colombier RET 290*42dedc50SDavid du Colombier 291*42dedc50SDavid du ColombierTEXT printBX(SB), $0 292*42dedc50SDavid du Colombier PUSHW(rAX) 293*42dedc50SDavid du Colombier MW(rBX, rAX) 294*42dedc50SDavid du Colombier CALL16(printAX(SB)) 295*42dedc50SDavid du Colombier POPW(rAX) 296*42dedc50SDavid du Colombier RET 297*42dedc50SDavid du Colombier 298*42dedc50SDavid du Colombier/* 299*42dedc50SDavid du Colombier * Output some number of words to the display 300*42dedc50SDavid du Colombier * rDS:rDI - buffer 301*42dedc50SDavid du Colombier * rCX: number of words 302*42dedc50SDavid du Colombier */ 303*42dedc50SDavid du ColombierTEXT printbuf(SB), $0 304*42dedc50SDavid du Colombier PUSHW(rAX) 305*42dedc50SDavid du Colombier PUSHW(rBX) 306*42dedc50SDavid du Colombier PUSHW(rCX) 307*42dedc50SDavid du Colombier 308*42dedc50SDavid du Colombier_nextword: 309*42dedc50SDavid du Colombier LXW(0, xBX, rAX) 310*42dedc50SDavid du Colombier CALL16(printAX(SB)) 311*42dedc50SDavid du Colombier INC(rBX) 312*42dedc50SDavid du Colombier INC(rBX) 313*42dedc50SDavid du Colombier DEC(rCX) 314*42dedc50SDavid du Colombier JNE _nextword 315*42dedc50SDavid du Colombier 316*42dedc50SDavid du Colombier POPW(rCX) 317*42dedc50SDavid du Colombier POPW(rBX) 318*42dedc50SDavid du Colombier POPW(rAX) 319*42dedc50SDavid du Colombier RET 320*42dedc50SDavid du Colombier 321*42dedc50SDavid du ColombierTEXT error(SB), $0 322*42dedc50SDavid du Colombier BYTE $'E'; 323*42dedc50SDavid du Colombier 324*42dedc50SDavid du ColombierTEXT ioerror(SB), $0 325*42dedc50SDavid du Colombier BYTE $'I'; 326*42dedc50SDavid du Colombier 327*42dedc50SDavid du ColombierTEXT nl(SB), $0 328*42dedc50SDavid du Colombier BYTE $'\r'; 329*42dedc50SDavid du Colombier BYTE $'\n'; 330*42dedc50SDavid du Colombier BYTE $'\z'; 331*42dedc50SDavid du Colombier 332*42dedc50SDavid du ColombierTEXT numbuf(SB), $0 333*42dedc50SDavid du Colombier BYTE $'X'; BYTE $'X'; BYTE $'X'; BYTE $'X'; 334*42dedc50SDavid du Colombier BYTE $'\z'; 335*42dedc50SDavid du Colombier 336*42dedc50SDavid du ColombierTEXT space(SB), $0 337*42dedc50SDavid du Colombier BYTE $' '; 338*42dedc50SDavid du Colombier BYTE $'\z'; 339*42dedc50SDavid du Colombier 340*42dedc50SDavid du ColombierTEXT sharp(SB), $0 341*42dedc50SDavid du Colombier BYTE $'#'; BYTE $'\z'; 342*42dedc50SDavid du Colombier 343*42dedc50SDavid du ColombierTEXT confidence(SB), $0 344*42dedc50SDavid du Colombier BYTE $'P'; BYTE $'\z' 345