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