xref: /plan9/sys/src/boot/pc/pbslbadebug.s (revision 42dedc50a943b5d120c8c26dac13fc4664b65146)
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