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