]> git.lizzy.rs Git - plan9front.git/blob - sys/src/boot/pc/bcom.c
perms
[plan9front.git] / sys / src / boot / pc / bcom.c
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 int vga;
87
88 static Medium*
89 parse(char *line, char **file)
90 {
91         char *p;
92         Type *tp;
93         Medium *mp;
94
95         if(p = strchr(line, '!')) {
96                 *p++ = 0;
97                 *file = p;
98         } else
99                 *file = "";
100
101         for(tp = types; tp->type != Tnil; tp++)
102                 for(mp = tp->media; mp; mp = mp->next)
103                         if(strcmp(mp->name, line) == 0)
104                                 return mp;
105         return nil;
106 }
107
108 static int
109 boot(Medium *mp, char *file)
110 {
111         static Boot b;
112
113         memset(&b, 0, sizeof b);
114         b.state = INIT9LOAD;
115
116 //      sprint(BOOTLINE, "%s!%s", mp->name, file);
117         return (*mp->type->boot)(mp->dev, file, &b);
118 }
119
120 static Medium*
121 allocm(Type *tp)
122 {
123         Medium **l;
124
125         if(curmedium >= &media[Nmedia])
126                 return 0;
127
128         for(l = &tp->media; *l; l = &(*l)->next)
129                 ;
130         *l = curmedium++;
131         return *l;
132 }
133
134 char *parts[] = { "dos", "9fat", "fs", 0 };
135
136 Medium*
137 probe(int type, int flag, int dev)
138 {
139         Type *tp;
140         int i;
141         Medium *mp;
142
143         for(tp = types; tp->type != Tnil; tp++){
144                 if(type != Tany && type != tp->type)
145                         continue;
146
147                 if(flag != Fnone){
148                         for(mp = tp->media; mp; mp = mp->next){
149                                 if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
150                                         return mp;
151                         }
152                 }
153
154                 if((tp->flag & Fprobe) == 0){
155                         tp->flag |= Fprobe;
156                         tp->mask = (*tp->init)();
157                 }
158
159                 for(i = 0; tp->mask; i++){
160                         if((tp->mask & (1<<i)) == 0)
161                                 continue;
162                         tp->mask &= ~(1<<i);
163
164                         if((mp = allocm(tp)) == 0)
165                                 continue;
166
167                         mp->dev = i;
168                         mp->flag = tp->flag;
169                         mp->type = tp;
170                         (*tp->initdev)(i, mp->name);
171
172                         if((flag & mp->flag) && (dev == Dany || dev == i))
173                                 return mp;
174                 }
175         }
176
177         return 0;
178 }
179
180 extern int loopconst;
181 void
182 main(void)
183 {
184         Medium *mp;
185         int flag;
186         char def[2*NAMELEN], line[80], *p, *file;
187         Type *tp;
188
189         i8042a20();
190         memset(m, 0, sizeof(Mach));
191         trapinit();
192         clockinit();
193         alarminit();
194         spllo();
195
196         kbdinit();
197         
198         if((ulong)&end > (KZERO|(640*1024)))
199                 panic("i'm too big");
200
201         /*
202          * If there were any arguments, MS-DOS leaves a character
203          * count followed by the arguments in the runtime header.
204          * Step over the leading space.
205          */
206         p = (char*)0x80080080;
207         if(p[0]){
208                 p[p[0]+1] = 0;
209                 p += 2;
210         }
211         else
212                 p = 0;
213
214         /*
215          * Advance command line to first option, if any
216          */
217         if(p) {
218                 while(*p==' ' || *p=='\t')
219                         p++;
220                 if(*p == 0)
221                         p = nil;
222         }
223
224         /*
225          * Probe everything, to collect device names.
226          */
227         probe(Tany, Fnone, Dany);
228
229         if(p != 0) {
230                 if((mp = parse(p, &file)) == nil) {
231                         print("bad loadfile syntax: %s\n", p);
232                         goto done;
233                 }
234                 boot(mp, file);
235         }
236
237 done:
238         flag = 0;
239         for(tp = types; tp->type != Tnil; tp++){
240                 for(mp = tp->media; mp; mp = mp->next){
241                         if(flag == 0){
242                                 flag = 1;
243                                 print("Load devices:");
244                         }
245                         print(" %s", mp->name);
246                 }
247         }
248         if(flag)
249                 print("\n");
250
251         for(;;){
252                 if(getstr("load from", line, sizeof(line), nil, 0) >= 0)
253                         if(mp = parse(line, &file))
254                                 boot(mp, file);
255                 def[0] = 0;
256         }
257 }
258
259 int
260 getfields(char *lp, char **fields, int n, char sep)
261 {
262         int i;
263
264         for(i = 0; lp && *lp && i < n; i++){
265                 while(*lp == sep)
266                         *lp++ = 0;
267                 if(*lp == 0)
268                         break;
269                 fields[i] = lp;
270                 while(*lp && *lp != sep){
271                         if(*lp == '\\' && *(lp+1) == '\n')
272                                 *lp++ = ' ';
273                         lp++;
274                 }
275         }
276         return i;
277 }
278
279 int
280 cistrcmp(char *a, char *b)
281 {
282         int ac, bc;
283
284         for(;;){
285                 ac = *a++;
286                 bc = *b++;
287         
288                 if(ac >= 'A' && ac <= 'Z')
289                         ac = 'a' + (ac - 'A');
290                 if(bc >= 'A' && bc <= 'Z')
291                         bc = 'a' + (bc - 'A');
292                 ac -= bc;
293                 if(ac)
294                         return ac;
295                 if(bc == 0)
296                         break;
297         }
298         return 0;
299 }
300
301 int
302 cistrncmp(char *a, char *b, int n)
303 {
304         unsigned ac, bc;
305
306         while(n > 0){
307                 ac = *a++;
308                 bc = *b++;
309                 n--;
310
311                 if(ac >= 'A' && ac <= 'Z')
312                         ac = 'a' + (ac - 'A');
313                 if(bc >= 'A' && bc <= 'Z')
314                         bc = 'a' + (bc - 'A');
315
316                 ac -= bc;
317                 if(ac)
318                         return ac;
319                 if(bc == 0)
320                         break;
321         }
322
323         return 0;
324 }
325
326 void*
327 ialloc(ulong n, int align)
328 {
329
330         static ulong palloc;
331         ulong p;
332         int a;
333
334         if(palloc == 0)
335                 palloc = 3*1024*1024;
336
337         p = palloc;
338         if(align <= 0)
339                 align = 4;
340         if(a = n % align)
341                 n += align - a;
342         if(a = p % align)
343                 p += align - a;
344
345         palloc = p+n;
346
347         return memset((void*)(p|KZERO), 0, n);
348 }
349
350 void*
351 xspanalloc(ulong size, int align, ulong span)
352 {
353         ulong a, v;
354
355         a = (ulong)ialloc(size+align+span, 0);
356
357         if(span > 2)
358                 v = (a + span) & ~(span-1);
359         else
360                 v = a;
361
362         if(align > 1)
363                 v = (v + align) & ~(align-1);
364
365         return (void*)v;
366 }
367
368 static Block *allocbp;
369
370 Block*
371 allocb(int size)
372 {
373         Block *bp, **lbp;
374         ulong addr;
375
376         lbp = &allocbp;
377         for(bp = *lbp; bp; bp = bp->next){
378                 if((bp->lim - bp->base) >= size){
379                         *lbp = bp->next;
380                         break;
381                 }
382                 lbp = &bp->next;
383         }
384         if(bp == 0){
385                 bp = ialloc(sizeof(Block)+size+64, 0);
386                 addr = (ulong)bp;
387                 addr = ROUNDUP(addr + sizeof(Block), 8);
388                 bp->base = (uchar*)addr;
389                 bp->lim = ((uchar*)bp) + sizeof(Block)+size+64;
390         }
391
392         if(bp->flag)
393                 panic("allocb reuse");
394
395         bp->rp = bp->base;
396         bp->wp = bp->rp;
397         bp->next = 0;
398         bp->flag = 1;
399
400         return bp;
401 }
402
403 void
404 freeb(Block* bp)
405 {
406         bp->next = allocbp;
407         allocbp = bp;
408
409         bp->flag = 0;
410 }
411
412 enum {
413         Paddr=          0x70,   /* address port */
414         Pdata=          0x71,   /* data port */
415 };
416
417 uchar
418 nvramread(int offset)
419 {
420         outb(Paddr, offset);
421         return inb(Pdata);
422 }
423
424 void (*etherdetach)(void);
425 void (*floppydetach)(void);
426 void (*sddetach)(void);
427
428 void
429 warp9(ulong entry)
430 {
431         if(etherdetach)
432                 etherdetach();
433         consdrain();
434         (*(void(*)(void))(PADDR(entry)))();
435 }
436
437 char*
438 getconf(char*)
439 {
440         return nil;
441 }
442
443 void
444 addconf(char*, ...)
445 {
446 }
447
448 void
449 uartspecial(int, void(*)(int), int(*)(void), int)
450 {
451 }
452
453 void
454 uartputs(IOQ*, char*, int)
455 {
456 }
457
458 void
459 uartputc(int)
460 {}
461
462 void
463 uartdrain(void)
464 {
465 }