Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * expand gzipped boot loader appended to this binary and execute it.
3
 *
4
 * due to Russ Cox, rsc@swtch.com.
5
 * see http://plan9.bell-labs.com/wiki/plan9/Replacing_9load
6
 */
7
#include <u.h>
8
#include <libc.h>
9
#include <a.out.h>
10
#include <flate.h>
11
#include "mem.h"
12
#include "expand.h"
13
 
14
#include "inflate.guts.c"
15
 
16
#define KB		1024
17
#define MB		(1024*1024)
18
 
19
extern char edata[];
20
 
21
/* ldecomp.s */
22
void mb586(void);
23
void splhi(void);
24
void wbinvd(void);
25
 
26
/* inflate.guts.c */
27
int gunzip(uchar*, int, uchar*, int);
28
 
29
int isexec(void*);
30
int isgzip(uchar*);
31
void run(void*);
32
 
33
#pragma varargck type "d" ulong
34
#pragma varargck type "x" ulong
35
 
36
static uchar *kernel = (uchar*)Bootkernaddr;
37
static char *dbrk = (char*)Mallocbase;
38
 
39
ulong
40
swap(ulong p)
41
{
42
	return p<<24 | p>>24 | (p<<8)&0x00FF0000 | (p>>8)&0x0000FF00;
43
}
44
 
45
enum {
46
	/* keyboard controller ports & cmds */
47
	Data=		0x60,		/* data port */
48
	Status=		0x64,		/* status port */
49
	 Inready=	0x01,		/*  input character ready */
50
	 Outbusy=	0x02,		/*  output busy */
51
	Cmd=		0x64,		/* command port (write only) */
52
 
53
	/* system control port a */
54
	Sysctla=	0x92,
55
	 Sysctlreset=	1<<0,
56
	 Sysctla20ena=	1<<1,
57
};
58
 
59
static int
60
isa20on(void)
61
{
62
	int r;
63
	ulong o;
64
	ulong *zp, *mb1p;
65
 
66
	zp = 0;
67
	mb1p = (ulong *)MB;
68
	o = *zp;
69
 
70
	*zp = 0x1234;
71
	*mb1p = 0x8765;
72
	mb586();
73
	wbinvd();
74
	r = *zp != *mb1p;
75
 
76
	*zp = o;
77
	return r;
78
}
79
 
80
static void
81
delay(uint ms)				/* approximate */
82
{
83
	int i;
84
 
85
	while(ms-- > 0)
86
		for(i = 1000*1000; i > 0; i--)
87
			;
88
}
89
 
90
static int
91
kbdinit(void)
92
{
93
	int c, try;
94
 
95
	/* wait for a quiescent controller */
96
	try = 500;			/* was 1000 */
97
	while(try-- > 0 && (c = inb(Status)) & (Outbusy | Inready)) {
98
		if(c & Inready)
99
			inb(Data);
100
		delay(1);
101
	}
102
	return try <= 0? -1: 0;
103
}
104
 
105
/*
106
 *  wait for output no longer busy (but not forever,
107
 *  there might not be a keyboard controller).
108
 */
109
static void
110
outready(void)
111
{
112
	int i;
113
 
114
	for (i = 1000; i > 0 && inb(Status) & Outbusy; i--)
115
		delay(1);
116
}
117
 
118
/*
119
 *  ask 8042 to enable the use of address bit 20
120
 */
121
int
122
i8042a20(void)
123
{
124
	if (kbdinit() < 0)
125
		return -1;
126
	outready();
127
	outb(Cmd, 0xD1);
128
	outready();
129
	outb(Data, 0xDF);
130
	outready();
131
	return 0;
132
}
133
 
134
void
135
a20init(void)
136
{
137
	int b;
138
 
139
	if (isa20on())
140
		return;
141
	if (i8042a20() < 0) {		/* original method, via kbd ctlr */
142
		/* newer method, last resort */
143
		b = inb(Sysctla);
144
		if (!(b & Sysctla20ena))
145
			outb(Sysctla, (b & ~Sysctlreset) | Sysctla20ena);
146
	}
147
	if (!isa20on()){
148
		print("a20 didn't come on!\n");
149
		for(;;)
150
			;
151
	}
152
}
153
 
154
void
155
_main(void)
156
{
157
	int ksize;
158
	Exec *exec;
159
 
160
	splhi();
161
	a20init();		/* don't wrap addresses at 1MB boundaries */
162
	ksize = Lowmemsz - (ulong)edata;	/* payload size */
163
	memmove(kernel, edata, ksize);
164
	memset(edata, 0, end - edata);
165
 
166
	cgainit();
167
	if(isgzip(kernel)) {
168
		print("gz...");
169
		memmove((uchar*)Unzipbuf, kernel, ksize);
170
 
171
		/* we have to uncompress the entire kernel to get OK status */
172
		if(gunzip(kernel, Bootkernmax, (uchar*)Unzipbuf, ksize) < 0){
173
			print("gzip failed.");
174
			exits(0);
175
		}
176
	}
177
	if(isexec(kernel))
178
		run(kernel);
179
 
180
	exec = (Exec *)kernel;
181
	print("unrecognized program; magic # 0x%x\n", swap(exec->magic));
182
	exits(0);
183
}
184
 
185
int
186
isexec(void *v)
187
{
188
	Exec *exec;
189
 
190
	exec = v;
191
	return swap(exec->magic) == I_MAGIC || swap(exec->magic) == S_MAGIC;
192
}
193
 
194
void
195
run(void *v)
196
{
197
	ulong entry, text, data;
198
	uchar *base;
199
	Exec *exec;
200
 
201
	base = v;
202
	exec = v;
203
	entry = swap(exec->entry) & ~KSEGM;
204
	text = swap(exec->text);
205
	data = swap(exec->data);
206
	/*
207
	 * align data segment on the expected page boundary.
208
	 * sizeof(Exec)+text is offset from base to data segment.
209
	 */
210
	memmove(base+PGROUND(sizeof(Exec)+text), base+sizeof(Exec)+text, data);
211
 
212
	print("starting protected-mode loader at 0x%x\n", entry);
213
	((void(*)(void))entry)();
214
 
215
	print("exec failed");
216
	exits(0);
217
}
218
 
219
int
220
isgzip(uchar *p)
221
{
222
	return p[0] == 0x1F && p[1] == 0x8B;
223
}
224
 
225
void*
226
malloc(ulong n)
227
{
228
	void *v;
229
 
230
	v = dbrk;
231
	dbrk += ROUND(n, BY2WD);
232
	return v;
233
}
234
 
235
void
236
free(void*)
237
{
238
}
239
 
240
void
241
puts(char *s)
242
{
243
	for(; *s; s++)
244
		cgaputc(*s);
245
}
246
 
247
int
248
print(char *fmt, ...)
249
{
250
	int sign;
251
	long d;
252
	ulong x;
253
	char *p, *s, buf[20];
254
	va_list arg;
255
	static char *hex = "0123456789abcdef";
256
 
257
	va_start(arg, fmt);
258
	for(p = fmt; *p; p++){
259
		if(*p != '%') {
260
			cgaputc(*p);
261
			continue;
262
		}
263
		SET(s);
264
		switch(*++p){
265
		case 'p':
266
		case 'x':
267
			x = va_arg(arg, ulong);
268
			if(x == 0){
269
				s = "0";
270
				break;
271
			}
272
			s = buf+sizeof buf;
273
			*--s = 0;
274
			while(x > 0){
275
				*--s = hex[x&15];
276
				x /= 16;
277
			}
278
			if(s == buf+sizeof buf)
279
				*--s = '0';
280
			break;
281
		case 'd':
282
			d = va_arg(arg, ulong);
283
			if(d == 0){
284
				s = "0";
285
				break;
286
			}
287
			if(d < 0){
288
				d = -d;
289
				sign = -1;
290
			}else
291
				sign = 1;
292
			s = buf+sizeof buf;
293
			*--s = 0;
294
			while(d > 0){
295
				*--s = (d%10)+'0';
296
				d /= 10;
297
			}
298
			if(sign < 0)
299
				*--s = '-';
300
			break;
301
		case 's':
302
			s = va_arg(arg, char*);
303
			break;
304
		case 0:
305
			return 0;
306
		}
307
		puts(s);
308
	}
309
	return 0;
310
}
311
 
312
void
313
exits(char*)
314
{
315
	for(;;)
316
		;
317
}