Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 *  Partition Boot Sector. Loaded at 0x7C00:
3
 *	8a pbsraw.s; 8l -o pbsraw -l -H3 -T0x7C00 pbsraw.8
4
 * Will load the target at LOADSEG*16+LOADOFF, so the target
5
 * should be probably be loaded with LOADOFF added to the
6
 * -Taddress.
7
 * If LOADSEG is a multiple of 64KB and LOADOFF is 0 then
8
 * targets larger than 64KB can be loaded.
9
 *
10
 * This code is uses Enhanced BIOS Services for Disc Drives and
11
 * can be used with discs up to 137GB in capacity.
12
 *
13
 * It relies on the _startlba,  _filesz and _sectsz containing the start lba of
14
 * the loader and filesz to contain the size of the file and the sector size.
15
 * The sector size can be probably detected by the bios.
16
 */
17
#include "x16.h"
18
 
19
#define LOADSEG		(0x10000/16)	/* where to load code (64KB) */
20
#define LOADOFF		0
21
 
22
/*
23
 * Data is kept on the stack, indexed by rBP.
24
 */
25
#define Xdap		0x00		/* disc address packet */
26
#define Xrootsz		0x10		/* file data area */
27
#define Xdrive		0x12		/* boot drive, passed by BIOS or MBR */
28
#define Xtotal		0x14		/* sum of allocated data above */
29
 
30
TEXT _magic(SB), $0
31
	BYTE $0xEB; BYTE $0x3C;		/* jmp .+ 0x3C  (_start0x3E) */
32
	BYTE $0x90			/* nop */
33
TEXT _startlba(SB), $0
34
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
35
TEXT _filesz(SB), $0
36
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
37
TEXT _sectsz(SB), $0
38
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
39
TEXT _pad(SB), $0
40
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
41
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
42
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
43
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
44
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
45
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
46
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
47
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
48
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
49
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
50
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
51
	BYTE $0x00; BYTE $0x00; BYTE $0x00
52
 
53
_start0x3E:
54
	CLI
55
	CLR(rAX)
56
	MTSR(rAX, rSS)			/* 0000 -> rSS */
57
	MTSR(rAX, rDS)			/* 0000 -> rDS, source segment */
58
	MTSR(rAX, rES)
59
	LWI(_magic-Xtotal(SB), rSP)
60
	MW(rSP, rBP)			/* set the indexed-data pointer */
61
 
62
	SBPB(rDL, Xdrive)		/* save the boot drive */
63
 
64
	/* booting from a CD starts us at 7C0:0.  Move to 0:7C00 */
65
	PUSHR(rAX)
66
	LWI(_nxt(SB), rAX)
67
	PUSHR(rAX)
68
	BYTE $0xCB			/* FAR RET */
69
 
70
TEXT _nxt(SB), $0
71
	STI
72
 
73
	LWI(confidence(SB), rSI)	/* for that warm, fuzzy feeling */
74
	CALL16(BIOSputs(SB))
75
 
76
	LBI(0x41, rAH)			/* check extensions present */
77
	LWI(0x55AA, rBX)
78
	LXB(Xdrive, xBP, rDL)		/* drive */
79
	BIOSCALL(0x13)			/* CF set on failure */
80
	JCS _jmp00
81
	CMPI(0xAA55, rBX)
82
	JNE _jmp00
83
	ANDI(0x0001, rCX)
84
	JNE _jmp01
85
 
86
_jmp00:
87
	CALL16(buggery(SB))
88
 
89
_jmp01:
90
	SBPWI(0x0010, Xdap+0)		/* reserved + packet size */
91
	SBPW(rCX, Xdap+2)		/* reserved + # of blocks to transfer */
92
 
93
	DEC(rCX)
94
	SBPW(rCX, Xdap+12)
95
	SBPW(rCX, Xdap+14)
96
 
97
	CALL16(dreset(SB))
98
 
99
_jmp02:
100
	CLR(rBX)			/* a handy value */
101
 
102
	LW(_startlba(SB), rAX)
103
	LW(_startlba+2(SB), rDX)
104
	CALL16(printDXAX(SB))
105
	PUSHR(rAX)
106
	PUSHR(rDX)
107
	LW(_filesz(SB), rAX)
108
	LW(_filesz+2(SB), rDX)
109
	CALL16(printDXAX(SB))
110
 
111
	MW(rAX, rCX)
112
	POPR(rDX)
113
	POPR(rAX)
114
 
115
	LWI(LOADSEG, rBX)		/* address to load into (seg+offset) */
116
	MTSR(rBX, rES)			/*  seg */
117
	LWI(LOADOFF, rBX)		/*  offset */
118
 
119
_readboot:
120
	CALL16(BIOSread(SB))		/* read the sector */
121
 
122
	LW(_sectsz(SB), rDI)		/* bump addresses/counts */
123
	ADD(rDI, rBX)
124
	JCC _incsecno
125
 
126
	MFSR(rES, rDI)			/* next 64KB segment */
127
	ADDI(0x1000, rDI)
128
	MTSR(rDI, rES)
129
 
130
_incsecno:
131
	CLR(rDI)
132
	INC(rAX)
133
	ADC(rDI, rDX)
134
	LOOP _readboot
135
 
136
	LWI(LOADSEG, rDI)		/* set rDS for loaded code */
137
	MTSR(rDI, rDS)
138
	FARJUMP16(LOADSEG, LOADOFF)	/* no deposit, no return */
139
 
140
TEXT buggery(SB), $0
141
	LWI(error(SB), rSI)
142
	CALL16(BIOSputs(SB))
143
 
144
_wait:
145
	CLR(rAX)			/* wait for almost any key */
146
	BIOSCALL(0x16)
147
 
148
_reset:
149
	CLR(rBX)			/* set ES segment for BIOS area */
150
	MTSR(rBX, rES)
151
 
152
	LWI(0x0472, rBX)		/* warm-start code address */
153
	LWI(0x1234, rAX)		/* warm-start code */
154
	POKEW				/* MOVW	AX, ES:[BX] */
155
 
156
	FARJUMP16(0xFFFF, 0x0000)	/* reset */
157
 
158
/*
159
 * Read a sector from a disc. On entry:
160
 *   rDX:rAX	sector number
161
 *   rES:rBX	buffer address
162
 */
163
TEXT BIOSread(SB), $0
164
	LWI(5, rDI)			/* retry count (ATAPI ZIPs suck) */
165
_retry:
166
	PUSHA				/* may be trashed by BIOSCALL */
167
 
168
	SBPW(rBX, Xdap+4)		/* transfer buffer :offset */
169
	MFSR(rES, rDI)			/* transfer buffer seg: */
170
	SBPW(rDI, Xdap+6)
171
	SBPW(rAX, Xdap+8)		/* LBA (64-bits) */
172
	SBPW(rDX, Xdap+10)
173
 
174
	MW(rBP, rSI)			/* disk address packet */
175
	LBI(0x42, rAH)			/* extended read */
176
	LBPB(Xdrive, rDL)		/* form drive */
177
	BIOSCALL(0x13)			/* CF set on failure */
178
	JCC _BIOSreadret
179
 
180
	POPA
181
	DEC(rDI)			/* too many retries? */
182
	JEQ _ioerror
183
 
184
	CALL16(dreset(SB))
185
	JMP _retry
186
 
187
_ioerror:
188
	LWI(ioerror(SB), rSI)
189
	CALL16(BIOSputs(SB))
190
	JMP _wait
191
 
192
_BIOSreadret:
193
	POPA
194
	RET
195
 
196
TEXT dreset(SB), $0
197
	PUSHA
198
	CLR(rAX)			/* rAH == 0 == reset disc system */
199
	LBPB(Xdrive, rDL)
200
	BIOSCALL(0x13)
201
	ORB(rAH, rAH)			/* status (0 == success) */
202
	POPA
203
	JNE _ioerror
204
	RET
205
 
206
TEXT printsharp(SB), $0
207
	LWI(sharp(SB), rSI)
208
_doprint:
209
	CALL16(BIOSputs(SB))
210
	RET
211
 
212
TEXT printspace(SB), $0
213
	LWI(space(SB), rSI)
214
	JMP _doprint
215
 
216
TEXT printnl(SB), $0
217
	LWI(nl(SB), rSI)
218
	JMP _doprint
219
 
220
/*
221
 * Output a string to the display.
222
 * String argument is in rSI.
223
 */
224
TEXT BIOSputs(SB), $0
225
	PUSHA
226
	CLR(rBX)
227
_BIOSputs:
228
	LODSB
229
	ORB(rAL, rAL)
230
	JEQ _BIOSputsret
231
 
232
	LBI(0x0E, rAH)
233
	BIOSCALL(0x10)
234
	JMP _BIOSputs
235
 
236
_BIOSputsret:
237
	POPA
238
	RET
239
 
240
/*
241
 * Output a register to the display.
242
 */
243
TEXT printAX(SB), $0
244
	PUSHR(rAX)
245
	PUSHR(rBX)
246
	PUSHR(rCX)
247
	PUSHR(rDI)
248
 
249
	LWI(4, rCX)
250
	LWI(numbuf+4(SB), rSI)
251
 
252
_nextchar:
253
	DEC(rSI)
254
	MW(rAX, rBX)
255
	ANDI(0x000F, rBX)
256
	ADDI(0x30, rBX)	/* 0x30 = '0' */
257
	CMPI(0x39, rBX)	/* 0x39 = '9' */
258
	JLE _dowrite
259
	ADDI(0x07, rBX)	/* 0x07 = 'A'-(1+'9')*/
260
 
261
_dowrite:
262
	SXB(rBL, 0, xSI)
263
	SHRI(4, rAX)
264
 
265
	DEC(rCX)
266
	JNE _nextchar
267
 
268
	LWI(numbuf(SB), rSI)
269
	CALL16(BIOSputs(SB))
270
 
271
	POPR(rDI)
272
	POPR(rCX)
273
	POPR(rBX)
274
	POPR(rAX)
275
 
276
	CALL16(printspace(SB))
277
	RET
278
 
279
TEXT printDXAX(SB), $0
280
	PUSHR(rAX)
281
	MW(rDX, rAX)
282
	CALL16(printAX(SB))
283
	POPR(rAX)
284
	CALL16(printAX(SB))
285
	RET
286
 
287
TEXT printBX(SB), $0
288
	PUSHR(rAX)
289
	MW(rBX, rAX)
290
	CALL16(printAX(SB))
291
	POPR(rAX)
292
	RET
293
 
294
TEXT error(SB), $0
295
	BYTE $'E';
296
 
297
TEXT ioerror(SB), $0
298
	BYTE $'I';
299
 
300
TEXT nl(SB), $0
301
	BYTE $'\r';
302
	BYTE $'\n';
303
	BYTE $'\z';
304
 
305
TEXT numbuf(SB), $0
306
	BYTE $'X'; BYTE $'X'; BYTE $'X'; BYTE $'X';
307
	BYTE $'\z';
308
 
309
TEXT space(SB), $0
310
	BYTE $' ';
311
	BYTE $'\z';
312
 
313
TEXT sharp(SB), $0
314
	BYTE $'#'; BYTE $'\z';
315
 
316
/* "PBSR..." */
317
TEXT confidence(SB), $0
318
	BYTE $'P'; BYTE $'B'; BYTE $'S'; BYTE $'R';
319
	BYTE $'.'; BYTE $'.'; BYTE $'.';
320
	BYTE $'\z';