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
 * Hard disc boot block. Loaded at 0x7C00, relocates to 0x0600:
3
 *	8a mbr.s; 8l -o mbr -l -H3 -T0x0600 mbr.8
4
 */
5
#include "x16.h"
6
 
7
/*#define FLOPPY	1		/* test on a floppy */
8
#define TRACE(C)	PUSHA;\
9
			CLR(rBX);\
10
			MOVB $C, AL;\
11
			LBI(0x0E, rAH);\
12
			BIOSCALL(0x10);\
13
			POPA
14
 
15
/*
16
 * We keep data on the stack, indexed by BP.
17
 */
18
#define Xdap		0x00		/* disc address packet */
19
#define Xtable		0x10		/* partition table entry */
20
#define Xdrive		0x12		/* starting disc */
21
#define Xtotal		0x14		/* sum of allocated data above */
22
 
23
/*
24
 * Start: loaded at 0000:7C00, relocate to 0000:0600.
25
 * Boot drive is in rDL.
26
 */
27
TEXT _start(SB), $0
28
	CLI
29
	CLR(rAX)
30
	MTSR(rAX, rSS)			/* 0000 -> rSS */
31
	LWI((0x7C00-Xtotal), rSP)	/* 7Bxx -> rSP */
32
	MW(rSP, rBP)			/* set the indexed-data pointer */
33
 
34
	MTSR(rAX, rDS)			/* 0000 -> rDS, source segment */
35
	LWI(0x7C00, rSI)		/* 7C00 -> rSI, source offset */
36
	MTSR(rAX, rES)			/* 0000 -> rES, destination segment */
37
	LWI(0x600, rDI)			/* 0600 -> rDI, destination offset */
38
	LWI(0x100, rCX)			/* 0100 -> rCX, loop count (words) */
39
 
40
	CLD
41
	REP; MOVSL			/* MOV DS:[(E)SI] -> ES:[(E)DI] */
42
 
43
	FARJUMP16(0x0000, _start0600(SB))
44
 
45
TEXT _start0600(SB), $0
46
#ifdef FLOPPY
47
	LBI(0x80, rDL)
48
#else
49
	CLRB(rAL)			/* some systems pass 0 */
50
	CMPBR(rAL, rDL)
51
	JNE _save
52
	LBI(0x80, rDL)
53
#endif /* FLOPPY */
54
_save:
55
	SXB(rDL, Xdrive, xBP)		/* save disc */
56
 
57
	LWI(confidence(SB), rSI)	/* for that warm, fuzzy feeling */
58
	CALL16(BIOSputs(SB))
59
 
60
	LWI(_start+0x01BE(SB), rSI)	/* address of partition table */
61
	LWI(0x04, rCX)			/* 4 entries in table */
62
	LBI(0x80, rAH)			/* active entry value */
63
	CLRB(rAL)			/* inactive entry value */
64
 
65
_activeloop0:
66
	LXB(0x00, xSI, rBL)		/* get active entry from table */
67
	CMPBR(rBL, rAH)			/* is this an active entry? */
68
	JEQ _active
69
 
70
	CMPBR(rBL, rAL)			/* if not active it should be 0 */
71
	JNE _invalidMBR
72
 
73
	ADDI(0x10, rSI)			/* next table entry */
74
	DEC(rCX)
75
	JNE _activeloop0
76
 
77
	LWI(noentry(SB), rSI)
78
	CALL16(buggery(SB))
79
 
80
_active:
81
	MW(rSI, rDI)			/* save table address */
82
 
83
_activeloop1:
84
	ADDI(0x10, rSI)			/* next table entry */
85
	DEC(rCX)
86
	JEQ _readsector
87
 
88
	LXB(0x00, xSI, rBL)		/* get active entry from table */
89
	CMPBR(rBL, rAH)			/* is this an active entry? */
90
	JNE _activeloop1		/* should only be one active */
91
 
92
_invalidMBR:
93
	LWI(invalidMBR(SB), rSI)
94
	CALL16(buggery(SB))
95
 
96
_readsector:
97
	LBI(0x41, rAH)			/* check extensions present */
98
	LWI(0x55AA, rBX)
99
	LXB(Xdrive, xBP, rDL)		/* drive */
100
	BIOSCALL(0x13)			/* CF set on failure */
101
	JCS _readsector2
102
	CMPI(0xAA55, rBX)
103
	JNE _readsector2
104
	ANDI(0x0001, rCX)
105
	JEQ _readsector2
106
 
107
_readsector42:
108
	SBPBI(0x10, Xdap+0)		/* packet size */
109
	SBPBI(0x00, Xdap+1)		/* reserved */
110
	SBPBI(0x01, Xdap+2)		/* number of blocks to transfer */
111
	SBPBI(0x00, Xdap+3)		/* reserved */
112
	SBPWI(0x7C00, Xdap+4)		/* transfer buffer :offset */
113
	SBPWI(0x0000, Xdap+6)		/* transfer buffer seg: */
114
	LXW(0x08, xDI, rAX)		/* LBA (64-bits) */
115
	SBPW(rAX, Xdap+8)
116
	LXW(0x0A, xDI, rAX)
117
	SBPW(rAX, Xdap+10)
118
	SBPWI(0x0000, Xdap+12)
119
	SBPWI(0x0000, Xdap+14)
120
 
121
	MW(rBP, rSI)			/* disk address packet */
122
	LBI(0x42, rAH)			/* extended read */
123
	BIOSCALL(0x13)			/* CF set on failure */
124
	JCC _readsectorok
125
 
126
	LWI(ioerror(SB), rSI)
127
	CALL16(buggery(SB))
128
 
129
/*
130
 * Read a sector from a disc using the traditional BIOS call.
131
 * For BIOSCALL(0x13/AH=0x02):
132
 *   rAH	0x02
133
 *   rAL	number of sectors to read (1)
134
 *   rCH	low 8 bits of cylinder
135
 *   rCL	high 2 bits of cylinder (7-6), sector (5-0)
136
 *   rDH	head
137
 *   rDL	drive
138
 *   rES:rBX	buffer address
139
 */
140
_readsector2:
141
	LXB(0x01, xDI, rDH)		/* head */
142
	LXW(0x02, xDI, rCX)		/* save active cylinder/sector */
143
 
144
	LWI(0x0201, rAX)		/* read one sector */
145
	LXB(Xdrive, xBP, rDL)		/* drive */
146
	LWI(0x7C00, rBX)		/* buffer address (rES already OK) */
147
	BIOSCALL(0x13)			/* CF set on failure */
148
	JCC _readsectorok
149
 
150
	LWI(ioerror(SB), rSI)
151
	CALL16(buggery(SB))
152
 
153
_readsectorok:
154
	LWI(0x7C00, rBX)		/* buffer address (rES already OK) */
155
	LXW(0x1FE, xBX, rAX)
156
	CMPI(0xAA55, rAX)
157
	JNE _bbnotok
158
 
159
	/*
160
	 * Jump to the loaded PBS.
161
	 * rDL and rSI should still contain the drive
162
	 * and partition table pointer respectively.
163
	 */
164
	MW(rDI, rSI)
165
	FARJUMP16(0x0000, 0x7C00)
166
 
167
_bbnotok:
168
	LWI(invalidPBS(SB), rSI)
169
 
170
TEXT buggery(SB), $0
171
	CALL16(BIOSputs(SB))
172
	LWI(reboot(SB), rSI)
173
	CALL16(BIOSputs(SB))
174
 
175
_wait:
176
	CLR(rAX)			/* wait for any key */
177
	BIOSCALL(0x16)
178
 
179
_reset:
180
	CLR(rBX)			/* set ES segment for BIOS area */
181
	MTSR(rBX, rES)
182
 
183
	LWI(0x0472, rBX)		/* warm-start code address */
184
	LWI(0x1234, rAX)		/* warm-start code */
185
	POKEW				/* MOVW	AX, ES:[BX] */
186
 
187
	FARJUMP16(0xFFFF, 0x0000)	/* reset */
188
 
189
/*
190
 * Output a string to the display.
191
 * String argument is in rSI.
192
 */
193
TEXT BIOSputs(SB), $0
194
	PUSHA
195
	CLR(rBX)
196
_BIOSputs:
197
	LODSB
198
	ORB(rAL, rAL)
199
	JEQ _BIOSputsret
200
 
201
	LBI(0x0E, rAH)
202
	BIOSCALL(0x10)
203
	JMP _BIOSputs
204
 
205
_BIOSputsret:
206
	POPA
207
	RET
208
 
209
/* "No active entry in MBR" */
210
TEXT noentry(SB), $0
211
	BYTE $'N'; BYTE $'o'; BYTE $' '; BYTE $'a';
212
	BYTE $'c'; BYTE $'t'; BYTE $'i'; BYTE $'v';
213
	BYTE $'e'; BYTE $' '; BYTE $'e'; BYTE $'n';
214
	BYTE $'t'; BYTE $'r'; BYTE $'y'; BYTE $' ';
215
	BYTE $'i'; BYTE $'n'; BYTE $' '; BYTE $'M';
216
	BYTE $'B'; BYTE $'R';
217
	BYTE $'\z';
218
 
219
/* "Invalid MBR" */
220
TEXT invalidMBR(SB), $0
221
	BYTE $'I'; BYTE $'n'; BYTE $'v'; BYTE $'a';
222
	BYTE $'l'; BYTE $'i'; BYTE $'d'; BYTE $' ';
223
	BYTE $'M'; BYTE $'B'; BYTE $'R';
224
	BYTE $'\z';
225
 
226
/* "I/O error" */
227
TEXT ioerror(SB), $0
228
	BYTE $'I'; BYTE $'/'; BYTE $'O'; BYTE $' ';
229
	BYTE $'e'; BYTE $'r'; BYTE $'r'; BYTE $'o';
230
	BYTE $'r';
231
	BYTE $'\z';
232
 
233
/* "Invalid PBS" */
234
TEXT invalidPBS(SB), $0
235
	BYTE $'I'; BYTE $'n'; BYTE $'v'; BYTE $'a';
236
	BYTE $'l'; BYTE $'i'; BYTE $'d'; BYTE $' ';
237
	BYTE $'P'; BYTE $'B'; BYTE $'S';
238
	BYTE $'\z';
239
 
240
/* "\r\nPress almost any key to reboot..." */
241
TEXT reboot(SB), $0
242
	BYTE $'\r';BYTE $'\n';
243
	BYTE $'P'; BYTE $'r'; BYTE $'e'; BYTE $'s';
244
	BYTE $'s'; BYTE $' '; BYTE $'a'; BYTE $'l'; 
245
	BYTE $'m'; BYTE $'o'; BYTE $'s'; BYTE $'t';
246
	BYTE $' '; BYTE $'a'; BYTE $'n'; BYTE $'y';
247
	BYTE $' '; BYTE $'k'; BYTE $'e'; BYTE $'y';
248
	BYTE $' '; BYTE $'t'; BYTE $'o'; BYTE $' ';
249
	BYTE $'r'; BYTE $'e'; BYTE $'b'; BYTE $'o';
250
	BYTE $'o'; BYTE $'t'; BYTE $'.'; BYTE $'.';
251
	BYTE $'.';
252
	BYTE $'\z';
253
 
254
/* "MBR..." */
255
TEXT confidence(SB), $0
256
	BYTE $'M'; BYTE $'B'; BYTE $'R'; BYTE $'.';
257
	BYTE $'.'; BYTE $'.';
258
	BYTE $'\z';