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
 * Protected-mode bootstrap, to be jumped to by a Primary Bootstrap Sector.
3
 * Load with -H3 -R4 -T0xNNNNNNNN to get a binary image with no header.
4
 * Note that the processor is in 'real' mode on entry, so care must be taken
5
 * as the assembler assumes protected mode, hence the sometimes weird-looking
6
 * code to assure 16-bit instructions are issued.
7
 */
8
#include "mem.h"
9
#include "/sys/src/boot/pc/x16.h"
10
 
11
#undef BIOSCALL		/* we don't know what evil the bios gets up to */
12
#define BIOSCALL(b)	INT $(b); CLI
13
 
14
#define CMPL(r0, r1)	BYTE $0x66; CMP(r0, r1)
15
#define LLI(i, rX)	BYTE $0x66;		/* i -> rX */		\
16
			BYTE $(0xB8+rX);				\
17
			LONG $i;
18
 
19
/*
20
 * Start:
21
 *	disable interrupts;
22
 *	set all segments;
23
 *	create temporary stack.
24
 */
25
TEXT _start16r(SB), $0
26
	CLI				/* interrupts off */
27
 
28
	MFSR(rCS, rAX)
29
	MTSR(rAX, rDS)			/* set the data segment */
30
 
31
	LWI(0, rAX)			/* always put stack in first 64k */
32
	MTSR(rAX, rSS)
33
	LWI(PXEBASE, rSP)		/* set the stack */
34
 
35
	LWI(0x2401, rAX)		/* enable a20 line */
36
	BIOSCALL(0x15)
37
 
38
/*
39
 * Do any real-mode BIOS calls before going to protected mode.
40
 * Data will be stored at BIOSTABLES, not ROUND(end, BY2PG) as before.
41
 */
42
 
43
/*
44
 * Check for CGA mode.
45
 */
46
_cgastart:
47
	LWI(0x0F00, rAX)		/* get current video mode in AL */
48
	BIOSCALL(0x10)
49
	ANDI(0x007F, rAX)
50
	SUBI(0x0003, rAX)		/* is it mode 3? */
51
	JEQ	_cgaputs
52
 
53
	LWI(0x0003, rAX)		/* turn on text mode 3 */
54
	BIOSCALL(0x10)
55
 
56
_cgaputs:				/* output a cheery wee message */
57
	LWI(_hello(SB), rSI)
58
	CLR(rBX)
59
_cgaputsloop:
60
	LODSB
61
	ORB(rAL, rAL)
62
	JEQ	_cgaend
63
 
64
	LBI(0x0E,rAH)
65
	BIOSCALL(0x10)
66
	JMP	_cgaputsloop
67
_cgaend:
68
 
69
/*
70
 * Reset floppy disc system.
71
 * If successful, make sure the motor is off.
72
 */
73
_floppystart:
74
	CLR(rAX)
75
	CLR(rDX)
76
	BIOSCALL(0x13)
77
	ORB(rAL, rAL)
78
	JNE	_floppyend
79
	OUTPORTB(0x3F2, 0x00)		/* turn off motor */
80
_floppyend:
81
 
82
	LLI(BIOSTABLES, rAX)	/* tables in low memory, not after end */
83
	OPSIZE; ANDL $~(BY2PG-1), AX
84
	OPSIZE; SHRL $4, AX
85
	SW(rAX, _ES(SB))
86
	CLR(rDI)
87
	SW(rDI, _DI(SB))
88
 
89
	MTSR(rAX, rES)
90
 
91
/*
92
 * Check for APM1.2 BIOS support.
93
 */
94
	LWI(0x5304, rAX)		/* disconnect anyone else */
95
	CLR(rBX)
96
	BIOSCALL(0x15)
97
	JCS	_apmfail
98
 
99
	LWI(0x5303, rAX)		/* connect */
100
	CLR(rBX)
101
	CLC
102
	BIOSCALL(0x15)
103
	JCC	_apmpush
104
_apmfail:
105
	LW(_ES(SB), rAX)		/* no support */
106
	MTSR(rAX, rES)
107
	LW(_DI(SB), rDI)
108
	JCS	_apmend
109
 
110
_apmpush:
111
	OPSIZE; PUSHR(rSI)		/* save returned APM data on stack */
112
	OPSIZE; PUSHR(rBX)
113
	PUSHR(rDI)
114
	PUSHR(rDX)
115
	PUSHR(rCX)
116
	PUSHR(rAX)
117
 
118
	LW(_ES(SB), rAX)
119
	MTSR(rAX, rES)
120
	LW(_DI(SB), rDI)
121
 
122
	LWI(0x5041, rAX)		/* first 4 bytes are APM\0 */
123
	STOSW
124
	LWI(0x004D, rAX)
125
	STOSW
126
 
127
	LWI(8, rCX)			/* pop the saved APM data */
128
_apmpop:
129
	POPR(rAX)
130
	STOSW
131
	LOOP	_apmpop
132
_apmend:
133
 
134
/*
135
 * Try to retrieve the 0xE820 memory map.
136
 * This is weird because some BIOS do not seem to preserve
137
 * ES/DI on failure. Consequently they may not be valid
138
 * at _e820end:.
139
 */
140
	SW(rDI, _DI(SB))		/* save DI */
141
	CLR(rAX)			/* write terminator */
142
	STOSW
143
	STOSW
144
 
145
	CLR(rBX)
146
	PUSHR(rBX)			/* keep loop count on stack */
147
					/* BX is the continuation value */
148
_e820loop:
149
	POPR(rAX)
150
	INC(rAX)
151
	PUSHR(rAX)			/* doesn't affect FLAGS */
152
	CMPI(32, rAX)			/* mmap[32+1] in C code */
153
	JGT	_e820pop
154
 
155
	LLI(20, rCX)			/* buffer size */
156
	LLI(0x534D4150, rDX)		/* signature - ASCII "SMAP" */
157
	LLI(0x0000E820, rAX)		/* function code */
158
 
159
	BIOSCALL(0x15)			/* writes 20 bytes at (es,di) */
160
 
161
	JCS	_e820pop		/* some kind of error */
162
	LLI(0x534D4150, rDX)
163
	CMPL(rDX, rAX)			/* verify correct BIOS version */
164
	JNE	_e820pop
165
	LLI(20, rDX)
166
	CMPL(rDX, rCX)			/* verify correct count */
167
	JNE	_e820pop
168
 
169
	SUBI(4, rDI)			/* overwrite terminator */
170
	LWI(0x414D, rAX)		/* first 4 bytes are "MAP\0" */
171
	STOSW
172
	LWI(0x0050, rAX)
173
	STOSW
174
 
175
	ADDI(20, rDI)			/* bump to next entry */
176
 
177
	SW(rDI, _DI(SB))		/* save DI */
178
	CLR(rAX)			/* write terminator */
179
	STOSW
180
	STOSW
181
 
182
	OR(rBX, rBX)			/* zero if last entry */
183
	JNE	_e820loop
184
 
185
_e820pop:
186
	POPR(rAX)			/* loop count */
187
	LW(_DI(SB), rDI)
188
	CLR(rAX)
189
	MTSR(rAX, rES)
190
_e820end:
191
 
192
/*
193
 * Done with BIOS calls for now.  realmode calls may use the BIOS later.
194
 */
195
 
196
/*
197
 * Load a basic GDT to map 4GB, turn on the protected mode bit in CR0,
198
 * set all the segments to point to the new GDT then jump to the 32-bit code.
199
 */
200
_real:
201
	LGDT(_gdtptr16r(SB))		/* load a basic gdt */
202
 
203
	MFCR(rCR0, rAX)
204
	ORI(1, rAX)
205
	MTCR(rAX, rCR0)			/* turn on protected mode */
206
	DELAY				/* JMP .+2 */
207
 
208
	LWI(SELECTOR(1, SELGDT, 0), rAX)/* set all segments */
209
	MTSR(rAX, rDS)
210
	MTSR(rAX, rES)
211
	MTSR(rAX, rFS)
212
	MTSR(rAX, rGS)
213
	MTSR(rAX, rSS)
214
 
215
	FARJUMP32(SELECTOR(2, SELGDT, 0), _start32p-KZERO(SB))
216
 
217
TEXT _hello(SB), $0
218
	BYTE $'\r';
219
	BYTE $'\n';
220
	BYTE $'P'; BYTE $'l'; BYTE $'a'; BYTE $'n';
221
	BYTE $' '; BYTE $'9'; BYTE $' '; BYTE $'f';
222
	BYTE $'r'; BYTE $'o'; BYTE $'m'; BYTE $' ';
223
	BYTE $'B'; BYTE $'e'; BYTE $'l'; BYTE $'l';
224
	BYTE $' '; BYTE $'L'; BYTE $'a'; BYTE $'b';
225
	BYTE $'s'; 
226
	BYTE $'\z';
227
 
228
TEXT _DI(SB), $0
229
	LONG $0
230
 
231
TEXT _ES(SB), $0
232
	LONG $0