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