xref: /inferno-os/os/boot/mpc/main.c (revision ecc9caba0e344ed50c05ee8156b2734f4d76e463)
1 #include "u.h"
2 #include "lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 
8 #include "dosfs.h"
9 
10 typedef struct Type Type;
11 typedef struct Medium Medium;
12 typedef struct Mode Mode;
13 
14 enum {
15 	Dany		= -1,
16 	Nmedia		= 16,
17 
18 	/* DS1 switch options */
19 	Sflashfs		= 1<<0,	/* take local fs from flash */
20 	Snotflash		= 1<<1,	/* don't boot from flash */
21 };
22 
23 enum {					/* type */
24 	Tflash,
25 	Tuart,
26 	Tether,
27 	Thard,
28 
29 	Tany		= -1,
30 };
31 
32 enum {					/* flag and name */
33 	Fnone		= 0x00,
34 
35 	Fdos		= 0x01,
36 	Ndos		= 0x00,
37 	Fboot		= 0x02,
38 	Nboot		= 0x01,
39 	Fbootp		= 0x04,
40 	Nbootp		= 0x02,
41 	Fflash		= 0x08,
42 	Fuart		= 0x10,
43 	NName		= 0x03,
44 
45 	Fany		= Fbootp|Fboot|Fdos|Fflash|Fuart,
46 
47 	Fini		= 0x10,
48 	Fprobe		= 0x80,
49 };
50 
51 enum {					/* mode */
52 	Mauto		= 0x00,
53 	Mlocal		= 0x01,
54 	Manual		= 0x02,
55 	NMode		= 0x03,
56 };
57 
58 typedef struct Type {
59 	int	type;
60 	char	*cname;
61 	int	flag;
62 	int	(*init)(void);
63 	long	(*read)(int, void*, long);
64 	long	(*seek)(int, long);
65 	Partition* (*setpart)(int, char*);
66 	char*	name[NName];
67 
68 	int	mask;
69 	Medium*	media;
70 } Type;
71 
72 typedef struct Medium {
73 	Type*	type;
74 	int	flag;
75 	Partition* partition;
76 	Dos;
77 
78 	Medium*	next;
79 } Medium;
80 
81 typedef struct Mode {
82 	char*	name;
83 	int	mode;
84 } Mode;
85 
86 static Type types[] = {
87 	{	Tflash, "flash",
88 		Fflash,
89 		flashinit, 0, 0, 0,
90 		{ 0, "F", 0, }
91 	},
92 /*
93 	{	Tuart, "uart",
94 		Fuart|Fboot,
95 		uartinit, uartread, uartseek, setuartpart,
96 		{ 0, "u", 0, }
97 	},
98 */
99 	{	Tether, "ether",
100 		Fbootp,
101 		etherinit, 0, 0, 0,
102 		{ 0, 0, "e", },
103 	},
104 	{	Thard, "ata",
105 		Fini|Fboot|Fdos,
106 		0, 0, 0, 0,		/* not used now, will be later with PCMCIA */
107 		{ "hd", "h", 0, },
108 	},
109 	{-1},
110 };
111 
112 static Medium media[Nmedia];
113 static Medium *curmedium = media;
114 
115 static Mode modes[NMode+1] = {
116 	[Mauto]		{ "auto",   Mauto,  },
117 	[Mlocal]	{ "local",  Mlocal, },
118 	[Manual]	{ "manual", Manual, },
119 };
120 
121 static char *inis[] = {
122 	"inferno/inferno.ini",
123 	"inferno.ini",
124 	"plan9/plan9.ini",
125 	"plan9.ini",
126 	0,
127 };
128 char **ini;
129 int	predawn;
130 
131 static int
132 parse(char *line, int *type, int *flag, int *dev, char *file)
133 {
134 	Type *tp;
135 	char buf[2*NAMELEN], *v[4], *p;
136 	int i;
137 
138 	strcpy(buf, line);
139 	switch(getcfields(buf, v, 4, "!")){
140 
141 	case 3:
142 		break;
143 
144 	case 2:
145 		v[2] = "";
146 		break;
147 
148 	default:
149 		return 0;
150 	}
151 
152 	*flag = 0;
153 	for(tp = types; tp->cname; tp++){
154 		for(i = 0; i < NName; i++){
155 
156 			if(tp->name[i] == 0 || strcmp(v[0], tp->name[i]))
157 				continue;
158 			*type = tp->type;
159 			*flag |= 1<<i;
160 
161 			if((*dev = strtoul(v[1], &p, 0)) == 0 && p == v[1])
162 				return 0;
163 
164 			strcpy(file, v[2]);
165 
166 			return 1;
167 		}
168 	}
169 
170 	return 0;
171 
172 }
173 
174 static int
175 boot(Medium *mp, int flag, char *file)
176 {
177 	Dosfile df;
178 	char ixdos[128], *p;
179 	int r;
180 
181 	uartsetboot(0);
182 	if(flag & Fbootp){
183 		sprint(BOOTLINE, "%s!%d", mp->type->name[Nbootp], mp->dev);
184 		return bootp(mp->dev, file);
185 	}
186 
187 	if(flag & Fflash){
188 		if(mp->flag & Fflash && flashbootable(0))
189 			flashboot(mp->dev);
190 	}
191 
192 	if(flag & Fboot){
193 
194 		if(mp->flag & Fini){
195 			(*mp->type->setpart)(mp->dev, "disk");
196 			plan9ini(mp, nil);
197 		}
198 		if(file == 0 || *file == 0)
199 			file = mp->partition->name;
200 		(*mp->type->setpart)(mp->dev, file);
201 		sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Nboot], mp->dev, file);
202 		r = plan9boot(mp->dev, mp->seek, mp->read);
203 		uartsetboot(0);
204 		return r;
205 	}
206 
207 	if(flag & Fdos){
208 		if(mp->type->setpart)
209 			(*mp->type->setpart)(mp->dev, "disk");
210 		if(mp->flag & Fini)
211 			plan9ini(mp, nil);
212 		if(file == 0 || *file == 0){
213 			strcpy(ixdos, *ini);
214 			if(p = strrchr(ixdos, '/'))
215 				p++;
216 			else
217 				p = ixdos;
218 			strcpy(p, "impc");
219 			if(dosstat(mp, ixdos, &df) <= 0)
220 				return -1;
221 		}
222 		else
223 			strcpy(ixdos, file);
224 		sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Ndos], mp->dev, ixdos);
225 		return dosboot(mp, ixdos);
226 	}
227 
228 	return -1;
229 }
230 
231 static Medium*
232 allocm(Type *tp)
233 {
234 	Medium **l;
235 
236 	if(curmedium >= &media[Nmedia])
237 		return 0;
238 
239 	for(l = &tp->media; *l; l = &(*l)->next)
240 		;
241 	*l = curmedium++;
242 	return *l;
243 }
244 
245 Medium*
246 probe(int type, int flag, int dev)
247 {
248 	Type *tp;
249 	int dombr, i, start;
250 	Medium *mp;
251 	Dosfile df;
252 	Partition *pp;
253 
254 	for(tp = types; tp->cname; tp++){
255 		if(type != Tany && type != tp->type || tp->init == 0)
256 			continue;
257 
258 		if(flag != Fnone){
259 			for(mp = tp->media; mp; mp = mp->next){
260 				if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
261 					return mp;
262 			}
263 		}
264 		if((tp->flag & Fprobe) == 0){
265 			tp->flag |= Fprobe;
266 			tp->mask = (*tp->init)();
267 		}
268 
269 		for(i = 0; tp->mask; i++){
270 			if((tp->mask & (1<<i)) == 0)
271 				continue;
272 			tp->mask &= ~(1<<i);
273 
274 			if((mp = allocm(tp)) == 0)
275 				continue;
276 
277 			mp->dev = i;
278 			mp->flag = tp->flag;
279 			mp->seek = tp->seek;
280 			mp->read = tp->read;
281 			mp->type = tp;
282 
283 			if(mp->flag & Fboot){
284 				if((mp->partition = (*tp->setpart)(i, "boot")) == 0)
285 					mp->flag &= ~Fboot;
286 				if((mp->flag & (Fflash|Fuart)) == 0)
287 					(*tp->setpart)(i, "disk");
288 			}
289 
290 			if(mp->flag & Fdos){
291 				start = 0;
292 				dombr = 1;
293 				if(mp->type->setpart){
294 					if(pp = (*mp->type->setpart)(i, "dos")){
295 						if(start = pp->start)
296 							dombr = 0;
297 					}
298 					(*tp->setpart)(i, "disk");
299 				}
300 				if(dosinit(mp, start, dombr) < 0)
301 					mp->flag &= ~(Fini|Fdos);
302 				else
303 					print("dos init failed\n");
304 			}
305 
306 			if(mp->flag & Fini){
307 				mp->flag &= ~Fini;
308 				for(ini = inis; *ini; ini++){
309 					if(dosstat(mp, *ini, &df) <= 0)
310 						continue;
311 					mp->flag |= Fini;
312 					break;
313 				}
314 			}
315 
316 			if((flag & mp->flag) && (dev == Dany || dev == i))
317 				return mp;
318 		}
319 	}
320 
321 	return 0;
322 }
323 
324 void
325 main(void)
326 {
327 	Medium *mp;
328 	int dev, flag, i, mode, tried, type, options;
329 	char def[2*NAMELEN], file[2*NAMELEN], line[80], *p;
330 	Type *tp;
331 
332 	machinit();
333 	archinit();
334 	meminit();
335 	cpminit();
336 	trapinit();
337 	consinit();	/* screen and keyboard initially */
338 	screeninit();
339 	cpuidprint();
340 	alarminit();
341 	clockinit();
342 	predawn = 0;
343 	spllo();
344 	options = archoptionsw();
345 
346 	mp = 0;
347 	for(tp = types; tp->cname; tp++){
348 		if(tp->type == Tether)
349 			continue;
350 		if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
351 			plan9ini(mp, nil);
352 			break;
353 		}
354 	}
355 
356 	if(mp == 0 || (mp->flag & Fini) == 0)
357 		plan9ini(nil, flashconfig(0));
358 
359 	//consinit();	/* establish new console location */
360 
361 	if((options & Snotflash) == 0 && flashbootable(0)){
362 		print("Flash boot\n");
363 		flashboot(0);
364 	}
365 
366 	tried = 0;
367 	mode = Mauto;
368 	p = getconf("bootfile");
369 	flag = 0;
370 
371 	if(p != 0) {
372 		mode = Manual;
373 		for(i = 0; i < NMode; i++){
374 			if(strcmp(p, modes[i].name) == 0){
375 				mode = modes[i].mode;
376 				goto done;
377 			}
378 		}
379 		if(parse(p, &type, &flag, &dev, file) == 0) {
380 			print("Bad bootfile syntax: %s\n", p);
381 			goto done;
382 		}
383 		mp = probe(type, flag, dev);
384 		if(mp == 0) {
385 			print("Cannot access device: %s\n", p);
386 			goto done;
387 		}
388 		tried = boot(mp, flag, file);
389 	}
390 done:
391 	if(tried == 0 && mode != Manual){
392 		flag = Fany;
393 		if(mode == Mlocal)
394 			flag &= ~Fbootp;
395 		if(options & Snotflash)
396 			flag &= ~Fflash;
397 		if((mp = probe(Tany, flag, Dany)) != 0)
398 			boot(mp, flag & mp->flag, 0);
399 	}
400 
401 	def[0] = 0;
402 	probe(Tany, Fnone, Dany);
403 
404 	flag = 0;
405 	for(tp = types; tp->cname; tp++){
406 		for(mp = tp->media; mp; mp = mp->next){
407 			if(flag == 0){
408 				flag = 1;
409 				print("Boot devices:");
410 			}
411 
412 			if(mp->flag & Fbootp)
413 				print(" %s!%d", mp->type->name[Nbootp], mp->dev);
414 			if(mp->flag & Fdos)
415 				print(" %s!%d", mp->type->name[Ndos], mp->dev);
416 			if(mp->flag & (Fflash|Fuart) || mp->flag & Fboot)
417 				print(" %s!%d", mp->type->name[Nboot], mp->dev);
418 		}
419 	}
420 	if(flag)
421 		print("\n");
422 
423 	for(;;){
424 		if(getstr("boot from", line, sizeof(line), def) >= 0){
425 			if(parse(line, &type, &flag, &dev, file)){
426 				if(mp = probe(type, flag, dev))
427 					boot(mp, flag, file);
428 			}
429 		}
430 		def[0] = 0;
431 	}
432 }
433 
434 void
435 machinit(void)
436 {
437 	memset(m, 0, sizeof(*m));
438 	m->delayloop = 20000;
439 	m->cpupvr = getpvr();
440 	m->iomem = KADDR(INTMEM);
441 }
442 
443 int
444 getcfields(char* lp, char** fields, int n, char* sep)
445 {
446 	int i;
447 
448 	for(i = 0; lp && *lp && i < n; i++){
449 		while(*lp && strchr(sep, *lp) != 0)
450 			*lp++ = 0;
451 		if(*lp == 0)
452 			break;
453 		fields[i] = lp;
454 		while(*lp && strchr(sep, *lp) == 0){
455 			if(*lp == '\\' && *(lp+1) == '\n')
456 				*lp++ = ' ';
457 			lp++;
458 		}
459 	}
460 
461 	return i;
462 }
463 
464 static	Map	memv[512];
465 static	RMap	rammap = {"physical memory"};
466 
467 void
468 meminit(void)
469 {
470 	ulong e;
471 
472 	mapinit(&rammap, memv, sizeof(memv));
473 	e = PADDR(&end);
474 	mapfree(&rammap, e, 4*1024*1024-e);	/* fixed 4Mbytes is plenty for bootstrap */
475 }
476 
477 void*
478 ialloc(ulong n, int align)
479 {
480 	ulong a;
481 	int s;
482 
483 	if(align <= 0)
484 		align = 4;
485 	s = splhi();
486 	a = mapalloc(&rammap, 0, n, align);
487 	splx(s);
488 	if(a == 0)
489 		panic("ialloc");
490 	return memset(KADDR(a), 0, n);
491 }
492 
493 void*
494 malloc(ulong n)
495 {
496 	ulong *p;
497 
498 	n = ((n+sizeof(int)-1)&~(sizeof(int)-1))+2*sizeof(int);
499 	p = ialloc(n, sizeof(int));
500 	*p++ = 0xcafebeef;
501 	*p++ = n;
502 	return p;
503 }
504 
505 void
506 free(void *ap)
507 {
508 	int s;
509 	ulong *p;
510 
511 	p = ap;
512 	if(p){
513 		if(*(p -= 2) != 0xcafebeef)
514 			panic("free");
515 		s = splhi();
516 		mapfree(&rammap, (ulong)p, p[1]);
517 		splx(s);
518 	}
519 }
520 
521 void
522 sched(void)
523 {
524 }
525