|
|
1.1 root 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: Maxdev = 7,
16: Dany = -1,
17: Nmedia = 16,
18: };
19:
20: enum { /* type */
21: Tfloppy = 0x00,
22: Thard = 0x01,
23: Tscsi = 0x02,
24: Tether = 0x03,
25: NType = 0x04,
26:
27: Tany = -1,
28: };
29:
30: enum { /* flag and name */
31: Fnone = 0x00,
32:
33: Fdos = 0x01,
34: Ndos = 0x00,
35: Fboot = 0x02,
36: Nboot = 0x01,
37: Fbootp = 0x04,
38: Nbootp = 0x02,
39: NName = 0x03,
40:
41: Fany = Fbootp|Fboot|Fdos,
42:
43: Fini = 0x10,
44: Freverse = 0x20,
45: Fprobe = 0x80,
46: };
47:
48: enum { /* mode */
49: Mauto = 0x00,
50: Mlocal = 0x01,
51: Manual = 0x02,
52: NMode = 0x03,
53: };
54:
55: typedef struct Type {
56: int type;
57: int flag;
58: int (*init)(void);
59: long (*read)(int, void*, long);
60: long (*seek)(int, long);
61: Partition* (*setpart)(int, char*);
62: char* name[NName];
63:
64: int mask;
65: Medium* media;
66: } Type;
67:
68: typedef struct Medium {
69: Type* type;
70: int flag;
71: Partition* partition;
72: Dos;
73:
74: Medium* next;
75: } Medium;
76:
77: typedef struct Mode {
78: char* name;
79: int mode;
80: } Mode;
81:
82: static Type types[NType] = {
83: { Tfloppy,
84: Fini|Fdos,
85: floppyinit, floppyread, floppyseek, 0,
86: { "fd", }
87: },
88: { Tether,
89: Fbootp,
90: etherinit, 0, 0, 0,
91: { 0, 0, "e", },
92: },
93: { Thard,
94: Fini|Fboot|Fdos,
95: hardinit, hardread, hardseek, sethardpart,
96: { "hd", "h", },
97: },
98: { Tscsi,
99: Fini|Fboot|Fdos,
100: scsiinit, scsiread, scsiseek, setscsipart,
101: { "sd", "s", },
102: },
103: };
104:
105: static Medium media[Nmedia];
106: static Medium *curmedium = media;
107:
108: static Mode modes[NMode+1] = {
109: [Mauto] { "auto", Mauto, },
110: [Mlocal] { "local", Mlocal, },
111: [Manual] { "manual", Manual, },
112: };
113:
114: static char *inis[] = {
115: "plan9/plan9.ini",
116: "plan9.ini",
117: 0,
118: };
119: char **ini;
120:
121: static int
122: parse(char *line, int *type, int *flag, int *dev, char *file)
123: {
124: Type *tp;
125: char buf[2*NAMELEN], *v[4], *p;
126: int i;
127:
128: strcpy(buf, line);
129: switch(getfields(buf, v, 4, '!')){
130:
131: case 3:
132: break;
133:
134: case 2:
135: v[2] = "";
136: break;
137:
138: default:
139: return 0;
140: }
141:
142: *flag = 0;
143: for(tp = types; tp < &types[NType]; tp++){
144: for(i = 0; i < NName; i++){
145:
146: if(tp->name[i] == 0 || strcmp(v[0], tp->name[i]))
147: continue;
148: *type = tp->type;
149: *flag |= 1<<i;
150:
151: if((*dev = strtoul(v[1], &p, 0)) == 0 && p == v[1])
152: return 0;
153:
154: strcpy(file, v[2]);
155:
156: return 1;
157: }
158: }
159:
160: return 0;
161:
162: }
163:
164: static int
165: boot(Medium *mp, int flag, char *file)
166: {
167: Dosfile df;
168: char ixdos[128], *p;
169:
170: if(flag & Fbootp){
171: sprint(BOOTLINE, "%s!%d", mp->type->name[Nbootp], mp->dev);
172: return bootp(mp->dev, file);
173: }
174:
175: if(flag & Fboot){
176: if(mp->flag & Fini){
177: (*mp->type->setpart)(mp->dev, "disk");
178: plan9ini(mp);
179: }
180: if(file == 0 || *file == 0)
181: file = mp->partition->name;
182: (*mp->type->setpart)(mp->dev, file);
183: sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Nboot], mp->dev, file);
184: return plan9boot(mp->dev, mp->seek, mp->read);
185: }
186:
187: if(flag & Fdos){
188: if(mp->type->setpart)
189: (*mp->type->setpart)(mp->dev, "disk");
190: if(mp->flag & Fini)
191: plan9ini(mp);
192: if(file == 0 || *file == 0){
193: strcpy(ixdos, *ini);
194: if(p = strrchr(ixdos, '/'))
195: p++;
196: else
197: p = ixdos;
198: strcpy(p, "9dos");
199: if(dosstat(mp, ixdos, &df) <= 0)
200: return -1;
201: }
202: else
203: strcpy(ixdos, file);
204: sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Ndos], mp->dev, ixdos);
205: return dosboot(mp, ixdos);
206: }
207:
208: return -1;
209: }
210:
211: static Medium*
212: allocm(Type *tp)
213: {
214: Medium **l;
215:
216: if(curmedium >= &media[Nmedia])
217: return 0;
218:
219: for(l = &tp->media; *l; l = &(*l)->next)
220: ;
221: *l = curmedium++;
222: return *l;
223: }
224:
225: Medium*
226: probe(int type, int flag, int dev)
227: {
228: Type *tp;
229: int d, i, m;
230: Medium *mp;
231: Dosfile df;
232:
233: for(tp = types; tp < &types[NType]; tp++){
234: if(type != Tany && type != tp->type)
235: continue;
236:
237: if(flag != Fnone){
238: for(mp = tp->media; mp; mp = mp->next){
239: if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
240: return mp;
241: }
242: }
243:
244: if((tp->flag & Fprobe) == 0){
245: tp->flag |= Fprobe;
246: tp->mask = (*tp->init)();
247: }
248:
249: for(i = 0; tp->mask; i++){
250: if(tp->flag & Freverse){
251: m = 1<<(Maxdev-i);
252: d = (Maxdev-i);
253: }
254: else{
255: m = 1<<i;
256: d = i;
257: }
258: if((tp->mask & m) == 0)
259: continue;
260: tp->mask &= ~m;
261:
262: if((mp = allocm(tp)) == 0)
263: continue;
264:
265: mp->dev = d;
266: mp->flag = tp->flag;
267: mp->seek = tp->seek;
268: mp->read = tp->read;
269: mp->type = tp;
270:
271: if(mp->flag & Fboot){
272: if((mp->partition = (*tp->setpart)(d, "boot")) == 0)
273: mp->flag &= ~Fboot;
274: (*tp->setpart)(d, "disk");
275: }
276:
277: if((mp->flag & Fdos) && (dosinit(mp) < 0))
278: mp->flag &= ~(Fini|Fdos);
279:
280: if(mp->flag & Fini){
281: mp->flag &= ~Fini;
282: for(ini = inis; *ini; ini++){
283: if(dosstat(mp, *ini, &df) <= 0)
284: continue;
285: mp->flag |= Fini;
286: break;
287: }
288: }
289:
290: if((flag & mp->flag) && (dev == Dany || dev == d))
291: return mp;
292: }
293: }
294:
295: return 0;
296: }
297:
298: void
299: main(void)
300: {
301: Medium *mp;
302: int dev, flag, i, mode, tried, type;
303: char def[2*NAMELEN], file[2*NAMELEN], line[80], *p;
304: Type *tp;
305:
306: i8042a20();
307: memset(m, 0, sizeof(Mach));
308: trapinit();
309: clockinit();
310: alarminit();
311: spllo();
312:
313: if((ulong)&end > (KZERO|(640*1024)))
314: panic("b.com too big\n");
315:
316: for(tp = types; tp < &types[NType]; tp++){
317: if(tp->type == Tether)
318: continue;
319: if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
320: plan9ini(mp);
321: break;
322: }
323: }
324:
325: consinit();
326:
327: /*
328: * If there were any arguments, MS-DOS leaves a character
329: * count followed by the arguments in the runtime header.
330: * Step over the leading space.
331: */
332: p = (char*)0x80080080;
333: if(p[0]){
334: p[p[0]+1] = 0;
335: p += 2;
336: }
337: else
338: p = 0;
339:
340: tried = 0;
341: mode = Mauto;
342: if(p == 0)
343: p = getconf("bootfile");
344:
345: if(p != 0) {
346: mode = Manual;
347: for(i = 0; i < NMode; i++){
348: if(strcmp(p, modes[i].name) == 0){
349: mode = modes[i].mode;
350: goto done;
351: }
352: }
353: if(parse(p, &type, &flag, &dev, file) == 0) {
354: print("Bad bootfile syntax: %s\n", p);
355: goto done;
356: }
357: mp = probe(type, flag, dev);
358: if(mp == 0) {
359: print("Cannot access device: %s\n", p);
360: goto done;
361: }
362: tried = boot(mp, flag, file);
363: }
364: done:
365: if(tried == 0 && mode != Manual){
366: flag = Fany;
367: if(mode == Mlocal)
368: flag &= ~Fbootp;
369: if((mp = probe(Tany, flag, Dany)) && mp->type->type != Tfloppy)
370: boot(mp, flag & mp->flag, 0);
371: }
372:
373: def[0] = 0;
374: probe(Tany, Fnone, Dany);
375: if(mode != Manual && (mp = probe(Tfloppy, Fdos, Dany)))
376: sprint(def, "%s!%d!9dos", mp->type->name[Ndos], mp->dev);
377:
378: flag = 0;
379: for(tp = types; tp < &types[NType]; tp++){
380: for(mp = tp->media; mp; mp = mp->next){
381: if(flag == 0){
382: flag = 1;
383: print("Boot devices:");
384: }
385:
386: if(mp->flag & Fbootp)
387: print(" %s!%d", mp->type->name[Nbootp], mp->dev);
388: if(mp->flag & Fdos)
389: print(" %s!%d", mp->type->name[Ndos], mp->dev);
390: if(mp->flag & Fboot)
391: print(" %s!%d", mp->type->name[Nboot], mp->dev);
392: }
393: }
394: if(flag)
395: print("\n");
396:
397: for(;;){
398: if(getstr("boot from", line, sizeof(line), def, def[0]!=0) >= 0){
399: if(parse(line, &type, &flag, &dev, file)){
400: if(mp = probe(type, flag, dev))
401: boot(mp, flag, file);
402: }
403: }
404: def[0] = 0;
405: }
406: }
407:
408: int
409: getfields(char *lp, char **fields, int n, char sep)
410: {
411: int i;
412:
413: for(i=0; lp && *lp && i<n; i++){
414: while(*lp == sep)
415: *lp++=0;
416: if(*lp == 0)
417: break;
418: fields[i]=lp;
419: while(*lp && *lp != sep)
420: lp++;
421: }
422: return i;
423: }
424:
425: void*
426: ialloc(ulong n, int align)
427: {
428:
429: static struct {
430: ulong addr;
431: } palloc;
432: ulong p;
433:
434: if(palloc.addr == 0)
435: palloc.addr = ((ulong)&end)&~KZERO;
436: if(align)
437: palloc.addr = PGROUND(palloc.addr);
438: if((palloc.addr <= 640*1024) && (palloc.addr + n > 640*1024))
439: palloc.addr = 2*1024*1024;
440:
441: memset((void*)(palloc.addr|KZERO), 0, n);
442: p = palloc.addr;
443: palloc.addr += n;
444: if(align)
445: palloc.addr = PGROUND(palloc.addr);
446:
447: return (void*)(p|KZERO);
448: }
449:
450: enum {
451: Paddr= 0x70, /* address port */
452: Pdata= 0x71, /* data port */
453: };
454:
455: uchar
456: nvramread(int offset)
457: {
458: outb(Paddr, offset);
459: return inb(Pdata);
460: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.