xref: /inferno-os/os/boot/pc/bcom.c (revision 8a8c2d742b51525f66c2210e3c8a251de10022ff)
1 /*
2  * ld - DOS boot loader of Plan 9
3  */
4 #include "u.h"
5 #include "lib.h"
6 #include "mem.h"
7 #include "dat.h"
8 #include "fns.h"
9 #include "io.h"
10 
11 #include "fs.h"
12 
13 Type types[] = {
14 	{	Tfloppy,
15 		Fini|Ffs,
16 		floppyinit, floppyinitdev,
17 		floppygetfspart, 0, floppyboot,
18 	},
19 	{	Tsd,
20 		Fini|Ffs,
21 		sdinit, sdinitdev,
22 		sdgetfspart, sdaddconf, sdboot,
23 	},
24 	{	Tnil,
25 		0,
26 		0, 0,
27 		0, 0, 0,
28 	},
29 };
30 
31 #include "sd.h"
32 
33 extern SDifc sdataifc;
34 extern SDifc sdmylexifc;
35 extern SDifc sd53c8xxifc;
36 SDifc* sdifc[] = {
37 	&sdataifc,
38 //	&sdmylexifc,
39 //	&sd53c8xxifc,
40 	nil,
41 };
42 
43 typedef struct Mode Mode;
44 
45 enum {
46 	Maxdev		= 7,
47 	Dany		= -1,
48 	Nmedia		= 16,
49 	Nini		= 10,
50 };
51 
52 enum {					/* mode */
53 	Mauto		= 0x00,
54 	Mlocal		= 0x01,
55 	Manual		= 0x02,
56 	NMode		= 0x03,
57 };
58 
59 typedef struct Medium Medium;
60 struct Medium {
61 	Type*	type;
62 	int	flag;
63 	int	dev;
64 	char name[NAMELEN];
65 	Fs*	inifs;
66 
67 	Medium*	next;
68 };
69 
70 typedef struct Mode {
71 	char*	name;
72 	int	mode;
73 } Mode;
74 
75 static Medium media[Nmedia];
76 static Medium *curmedium = media;
77 
78 static Mode modes[NMode+1] = {
79 	[Mauto]		{ "auto",   Mauto,  },
80 	[Mlocal]	{ "local",  Mlocal, },
81 	[Manual]	{ "manual", Manual, },
82 };
83 
84 char *defaultpartition = "new";
85 
86 static Medium*
parse(char * line,char ** file)87 parse(char *line, char **file)
88 {
89 	char *p;
90 	Type *tp;
91 	Medium *mp;
92 
93 	if(p = strchr(line, '!')) {
94 		*p++ = 0;
95 		*file = p;
96 	} else
97 		*file = "";
98 
99 	for(tp = types; tp->type != Tnil; tp++)
100 		for(mp = tp->media; mp; mp = mp->next)
101 			if(strcmp(mp->name, line) == 0)
102 				return mp;
103 	return nil;
104 }
105 
106 static int
boot(Medium * mp,char * file)107 boot(Medium *mp, char *file)
108 {
109 	static Boot b;
110 
111 	memset(&b, 0, sizeof b);
112 	b.state = INIT9LOAD;
113 
114 //	sprint(BOOTLINE, "%s!%s", mp->name, file);
115 	return (*mp->type->boot)(mp->dev, file, &b);
116 }
117 
118 static Medium*
allocm(Type * tp)119 allocm(Type *tp)
120 {
121 	Medium **l;
122 
123 	if(curmedium >= &media[Nmedia])
124 		return 0;
125 
126 	for(l = &tp->media; *l; l = &(*l)->next)
127 		;
128 	*l = curmedium++;
129 	return *l;
130 }
131 
132 char *parts[] = { "dos", "9fat", "fs", 0 };
133 
134 Medium*
probe(int type,int flag,int dev)135 probe(int type, int flag, int dev)
136 {
137 	Type *tp;
138 	int i;
139 	Medium *mp;
140 
141 	for(tp = types; tp->type != Tnil; tp++){
142 		if(type != Tany && type != tp->type)
143 			continue;
144 
145 		if(flag != Fnone){
146 			for(mp = tp->media; mp; mp = mp->next){
147 				if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
148 					return mp;
149 			}
150 		}
151 
152 		if((tp->flag & Fprobe) == 0){
153 			tp->flag |= Fprobe;
154 			tp->mask = (*tp->init)();
155 		}
156 
157 		for(i = 0; tp->mask; i++){
158 			if((tp->mask & (1<<i)) == 0)
159 				continue;
160 			tp->mask &= ~(1<<i);
161 
162 			if((mp = allocm(tp)) == 0)
163 				continue;
164 
165 			mp->dev = i;
166 			mp->flag = tp->flag;
167 			mp->type = tp;
168 			(*tp->initdev)(i, mp->name);
169 
170 			if((flag & mp->flag) && (dev == Dany || dev == i))
171 				return mp;
172 		}
173 	}
174 
175 	return 0;
176 }
177 
178 extern int loopconst;
179 void
main(void)180 main(void)
181 {
182 	Medium *mp;
183 	int flag;
184 	char def[2*NAMELEN], line[80], *p, *file;
185 	Type *tp;
186 
187 	i8042a20();
188 	memset(m, 0, sizeof(Mach));
189 	trapinit();
190 	clockinit();
191 	alarminit();
192 	spllo();
193 
194 	kbdinit();
195 
196 	if((ulong)&end > (KZERO|(640*1024)))
197 		panic("i'm too big");
198 
199 	/*
200 	 * If there were any arguments, MS-DOS leaves a character
201 	 * count followed by the arguments in the runtime header.
202 	 * Step over the leading space.
203 	 */
204 	p = (char*)0x80080080;
205 	if(p[0]){
206 		p[p[0]+1] = 0;
207 		p += 2;
208 	}
209 	else
210 		p = 0;
211 
212 	/*
213 	 * Advance command line to first option, if any
214 	 */
215 	if(p) {
216 		while(*p==' ' || *p=='\t')
217 			p++;
218 		if(*p == 0)
219 			p = nil;
220 	}
221 
222 	/*
223  	 * Probe everything, to collect device names.
224 	 */
225 	probe(Tany, Fnone, Dany);
226 
227 	if(p != 0) {
228 		if((mp = parse(p, &file)) == nil) {
229 			print("bad loadfile syntax: %s\n", p);
230 			goto done;
231 		}
232 		boot(mp, file);
233 	}
234 
235 done:
236 	flag = 0;
237 	for(tp = types; tp->type != Tnil; tp++){
238 		for(mp = tp->media; mp; mp = mp->next){
239 			if(flag == 0){
240 				flag = 1;
241 				print("Load devices:");
242 			}
243 			print(" %s", mp->name);
244 		}
245 	}
246 	if(flag)
247 		print("\n");
248 
249 	for(;;){
250 		if(getstr("load from", line, sizeof(line), nil, 0) >= 0)
251 			if(mp = parse(line, &file))
252 				boot(mp, file);
253 		def[0] = 0;
254 	}
255 }
256 
257 int
getfields(char * lp,char ** fields,int n,char sep)258 getfields(char *lp, char **fields, int n, char sep)
259 {
260 	int i;
261 
262 	for(i = 0; lp && *lp && i < n; i++){
263 		while(*lp == sep)
264 			*lp++ = 0;
265 		if(*lp == 0)
266 			break;
267 		fields[i] = lp;
268 		while(*lp && *lp != sep){
269 			if(*lp == '\\' && *(lp+1) == '\n')
270 				*lp++ = ' ';
271 			lp++;
272 		}
273 	}
274 	return i;
275 }
276 
277 int
cistrcmp(char * a,char * b)278 cistrcmp(char *a, char *b)
279 {
280 	int ac, bc;
281 
282 	for(;;){
283 		ac = *a++;
284 		bc = *b++;
285 
286 		if(ac >= 'A' && ac <= 'Z')
287 			ac = 'a' + (ac - 'A');
288 		if(bc >= 'A' && bc <= 'Z')
289 			bc = 'a' + (bc - 'A');
290 		ac -= bc;
291 		if(ac)
292 			return ac;
293 		if(bc == 0)
294 			break;
295 	}
296 	return 0;
297 }
298 
299 int
cistrncmp(char * a,char * b,int n)300 cistrncmp(char *a, char *b, int n)
301 {
302 	unsigned ac, bc;
303 
304 	while(n > 0){
305 		ac = *a++;
306 		bc = *b++;
307 		n--;
308 
309 		if(ac >= 'A' && ac <= 'Z')
310 			ac = 'a' + (ac - 'A');
311 		if(bc >= 'A' && bc <= 'Z')
312 			bc = 'a' + (bc - 'A');
313 
314 		ac -= bc;
315 		if(ac)
316 			return ac;
317 		if(bc == 0)
318 			break;
319 	}
320 
321 	return 0;
322 }
323 
324 void*
ialloc(ulong n,int align)325 ialloc(ulong n, int align)
326 {
327 
328 	static ulong palloc;
329 	ulong p;
330 	int a;
331 
332 	if(palloc == 0)
333 		palloc = 3*1024*1024;
334 
335 	p = palloc;
336 	if(align <= 0)
337 		align = 4;
338 	if(a = n % align)
339 		n += align - a;
340 	if(a = p % align)
341 		p += align - a;
342 
343 	palloc = p+n;
344 
345 	return memset((void*)(p|KZERO), 0, n);
346 }
347 
348 void*
xspanalloc(ulong size,int align,ulong span)349 xspanalloc(ulong size, int align, ulong span)
350 {
351 	ulong a, v;
352 
353 	a = (ulong)ialloc(size+align+span, 0);
354 
355 	if(span > 2)
356 		v = (a + span) & ~(span-1);
357 	else
358 		v = a;
359 
360 	if(align > 1)
361 		v = (v + align) & ~(align-1);
362 
363 	return (void*)v;
364 }
365 
366 static Block *allocbp;
367 
368 Block*
allocb(int size)369 allocb(int size)
370 {
371 	Block *bp, **lbp;
372 	ulong addr;
373 
374 	lbp = &allocbp;
375 	for(bp = *lbp; bp; bp = bp->next){
376 		if((bp->lim - bp->base) >= size){
377 			*lbp = bp->next;
378 			break;
379 		}
380 		lbp = &bp->next;
381 	}
382 	if(bp == 0){
383 		bp = ialloc(sizeof(Block)+size+64, 0);
384 		addr = (ulong)bp;
385 		addr = ROUNDUP(addr + sizeof(Block), 8);
386 		bp->base = (uchar*)addr;
387 		bp->lim = ((uchar*)bp) + sizeof(Block)+size+64;
388 	}
389 
390 	if(bp->flag)
391 		panic("allocb reuse\n");
392 
393 	bp->rp = bp->base;
394 	bp->wp = bp->rp;
395 	bp->next = 0;
396 	bp->flag = 1;
397 
398 	return bp;
399 }
400 
401 void
freeb(Block * bp)402 freeb(Block* bp)
403 {
404 	bp->next = allocbp;
405 	allocbp = bp;
406 
407 	bp->flag = 0;
408 }
409 
410 enum {
411 	Paddr=		0x70,	/* address port */
412 	Pdata=		0x71,	/* data port */
413 };
414 
415 uchar
nvramread(int offset)416 nvramread(int offset)
417 {
418 	outb(Paddr, offset);
419 	return inb(Pdata);
420 }
421 
422 void (*etherdetach)(void);
423 void (*floppydetach)(void);
424 void (*sddetach)(void);
425 
426 void
warp9(ulong entry)427 warp9(ulong entry)
428 {
429 	if(etherdetach)
430 		etherdetach();
431 	consdrain();
432 	(*(void(*)(void))(PADDR(entry)))();
433 }
434 
435 char*
getconf(char *)436 getconf(char*)
437 {
438 	return nil;
439 }
440 
441 void
addconf(char *,...)442 addconf(char*, ...)
443 {
444 }
445 
446 void
uartspecial(int,void (*)(int),int (*)(void),int)447 uartspecial(int, void(*)(int), int(*)(void), int)
448 {
449 }
450 
451 void
uartputs(IOQ *,char *,int)452 uartputs(IOQ*, char*, int)
453 {
454 }
455 
456 void
uartputc(int)457 uartputc(int)
458 {}
459 
460 void
uartdrain(void)461 uartdrain(void)
462 {
463 }
464