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