xref: /inferno-os/os/boot/rpcg/main.c (revision 4eb166cf184c1f102fb79e31b1465ea3e2021c39)
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 print("predawn\n");
343 	predawn = 0;
344 	spllo();
345 print("dawn\n");
346 	options = archoptionsw();
347 print("options=#%ux\n", options);
348 
349 	mp = 0;
350 	for(tp = types; tp->cname; tp++){
351 		if(tp->type == Tether)
352 			continue;
353 		if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
354 			plan9ini(mp, nil);
355 			break;
356 		}
357 	}
358 
359 	if(mp == 0 || (mp->flag & Fini) == 0)
360 		plan9ini(nil, flashconfig(0));
361 
362 	//consinit();	/* establish new console location */
363 
364 	if((options & Snotflash) == 0 && flashbootable(0)){
365 		print("Flash boot\n");
366 		flashboot(0);
367 	}
368 
369 	tried = 0;
370 	mode = Mauto;
371 	p = getconf("bootfile");
372 	flag = 0;
373 
374 	if(p != 0) {
375 		mode = Manual;
376 		for(i = 0; i < NMode; i++){
377 			if(strcmp(p, modes[i].name) == 0){
378 				mode = modes[i].mode;
379 				goto done;
380 			}
381 		}
382 		if(parse(p, &type, &flag, &dev, file) == 0) {
383 			print("Bad bootfile syntax: %s\n", p);
384 			goto done;
385 		}
386 		mp = probe(type, flag, dev);
387 		if(mp == 0) {
388 			print("Cannot access device: %s\n", p);
389 			goto done;
390 		}
391 		tried = boot(mp, flag, file);
392 	}
393 done:
394 	if(tried == 0 && mode != Manual){
395 		flag = Fany;
396 		if(mode == Mlocal)
397 			flag &= ~Fbootp;
398 		if(options & Snotflash)
399 			flag &= ~Fflash;
400 		if((mp = probe(Tany, flag, Dany)) != 0)
401 			boot(mp, flag & mp->flag, 0);
402 	}
403 
404 	def[0] = 0;
405 	probe(Tany, Fnone, Dany);
406 
407 	flag = 0;
408 	for(tp = types; tp->cname; tp++){
409 		for(mp = tp->media; mp; mp = mp->next){
410 			if(flag == 0){
411 				flag = 1;
412 				print("Boot devices:");
413 			}
414 
415 			if(mp->flag & Fbootp)
416 				print(" %s!%d", mp->type->name[Nbootp], mp->dev);
417 			if(mp->flag & Fdos)
418 				print(" %s!%d", mp->type->name[Ndos], mp->dev);
419 			if(mp->flag & (Fflash|Fuart) || mp->flag & Fboot)
420 				print(" %s!%d", mp->type->name[Nboot], mp->dev);
421 		}
422 	}
423 	if(flag)
424 		print("\n");
425 
426 	for(;;){
427 		if(getstr("boot from", line, sizeof(line), def) >= 0){
428 			if(parse(line, &type, &flag, &dev, file)){
429 				if(mp = probe(type, flag, dev))
430 					boot(mp, flag, file);
431 			}
432 		}
433 		def[0] = 0;
434 	}
435 }
436 
437 void
438 machinit(void)
439 {
440 	memset(m, 0, sizeof(*m));
441 	m->delayloop = 20000;
442 	m->cpupvr = getpvr();
443 	m->iomem = KADDR(INTMEM);
444 }
445 
446 int
447 getcfields(char* lp, char** fields, int n, char* sep)
448 {
449 	int i;
450 
451 	for(i = 0; lp && *lp && i < n; i++){
452 		while(*lp && strchr(sep, *lp) != 0)
453 			*lp++ = 0;
454 		if(*lp == 0)
455 			break;
456 		fields[i] = lp;
457 		while(*lp && strchr(sep, *lp) == 0){
458 			if(*lp == '\\' && *(lp+1) == '\n')
459 				*lp++ = ' ';
460 			lp++;
461 		}
462 	}
463 
464 	return i;
465 }
466 
467 static	Map	memv[512];
468 static	RMap	rammap = {"physical memory"};
469 
470 void
471 meminit(void)
472 {
473 	ulong e;
474 
475 	mapinit(&rammap, memv, sizeof(memv));
476 	e = PADDR(&end);
477 	mapfree(&rammap, e, 4*1024*1024-e);	/* fixed 4Mbytes is plenty for bootstrap */
478 }
479 
480 void*
481 ialloc(ulong n, int align)
482 {
483 	ulong a;
484 	int s;
485 
486 	if(align <= 0)
487 		align = 4;
488 	s = splhi();
489 	a = mapalloc(&rammap, 0, n, align);
490 	splx(s);
491 	if(a == 0)
492 		panic("ialloc");
493 	return memset(KADDR(a), 0, n);
494 }
495 
496 void*
497 malloc(ulong n)
498 {
499 	ulong *p;
500 
501 	n = ((n+sizeof(int)-1)&~(sizeof(int)-1))+2*sizeof(int);
502 	p = ialloc(n, sizeof(int));
503 	*p++ = 0xcafebeef;
504 	*p++ = n;
505 	return p;
506 }
507 
508 void
509 free(void *ap)
510 {
511 	int s;
512 	ulong *p;
513 
514 	p = ap;
515 	if(p){
516 		if(*(p -= 2) != 0xcafebeef)
517 			panic("free");
518 		s = splhi();
519 		mapfree(&rammap, (ulong)p, p[1]);
520 		splx(s);
521 	}
522 }
523 
524 void
525 sched(void)
526 {
527 }
528