1*da917039SDavid du Colombier #include "include.h"
2*da917039SDavid du Colombier #include "fs.h"
3*da917039SDavid du Colombier
4*da917039SDavid du Colombier enum {
5*da917039SDavid du Colombier Dontprint,
6*da917039SDavid du Colombier Print,
7*da917039SDavid du Colombier
8*da917039SDavid du Colombier Datamagic = 0xfacebabe,
9*da917039SDavid du Colombier };
10*da917039SDavid du Colombier
11*da917039SDavid du Colombier int securemem;
12*da917039SDavid du Colombier
13*da917039SDavid du Colombier static char *etherparts[] = { "*", 0 };
14*da917039SDavid du Colombier static char *etherinis[] = {
15*da917039SDavid du Colombier "/cfg/pxe/%E",
16*da917039SDavid du Colombier 0
17*da917039SDavid du Colombier };
18*da917039SDavid du Colombier
19*da917039SDavid du Colombier Type types[] = {
20*da917039SDavid du Colombier { Tether,
21*da917039SDavid du Colombier Fini|Fbootp,
22*da917039SDavid du Colombier etherinit, etherinitdev,
23*da917039SDavid du Colombier pxegetfspart, 0, bootpboot,
24*da917039SDavid du Colombier etherprintdevs,
25*da917039SDavid du Colombier etherparts,
26*da917039SDavid du Colombier etherinis,
27*da917039SDavid du Colombier },
28*da917039SDavid du Colombier };
29*da917039SDavid du Colombier
30*da917039SDavid du Colombier static char *typenm[] = {
31*da917039SDavid du Colombier [Tether] "ether",
32*da917039SDavid du Colombier };
33*da917039SDavid du Colombier
34*da917039SDavid du Colombier typedef struct Mode Mode;
35*da917039SDavid du Colombier
36*da917039SDavid du Colombier enum {
37*da917039SDavid du Colombier Dany = -1,
38*da917039SDavid du Colombier Nmedia = 2, /* size reduction; was 16 */
39*da917039SDavid du Colombier };
40*da917039SDavid du Colombier
41*da917039SDavid du Colombier enum { /* mode */
42*da917039SDavid du Colombier Mauto,
43*da917039SDavid du Colombier Mlocal,
44*da917039SDavid du Colombier Manual,
45*da917039SDavid du Colombier NMode,
46*da917039SDavid du Colombier };
47*da917039SDavid du Colombier
48*da917039SDavid du Colombier typedef struct Medium Medium;
49*da917039SDavid du Colombier struct Medium {
50*da917039SDavid du Colombier Type* type;
51*da917039SDavid du Colombier ushort flag;
52*da917039SDavid du Colombier ushort dev;
53*da917039SDavid du Colombier char name[NAMELEN];
54*da917039SDavid du Colombier
55*da917039SDavid du Colombier Fs *inifs;
56*da917039SDavid du Colombier char *part;
57*da917039SDavid du Colombier char *ini;
58*da917039SDavid du Colombier
59*da917039SDavid du Colombier Medium* next;
60*da917039SDavid du Colombier };
61*da917039SDavid du Colombier
62*da917039SDavid du Colombier typedef struct Mode {
63*da917039SDavid du Colombier char* name;
64*da917039SDavid du Colombier ushort mode;
65*da917039SDavid du Colombier } Mode;
66*da917039SDavid du Colombier
67*da917039SDavid du Colombier extern char bdata[], edata[], end[], etext[];
68*da917039SDavid du Colombier
69*da917039SDavid du Colombier static Medium media[Nmedia];
70*da917039SDavid du Colombier static Medium *curmedium = media;
71*da917039SDavid du Colombier
72*da917039SDavid du Colombier static Mode modes[NMode+1] = {
73*da917039SDavid du Colombier [Mauto] { "auto", Mauto, },
74*da917039SDavid du Colombier [Mlocal] { "local", Mlocal, },
75*da917039SDavid du Colombier [Manual] { "manual", Manual, },
76*da917039SDavid du Colombier };
77*da917039SDavid du Colombier
78*da917039SDavid du Colombier Mach* machptr[MAXMACH];
79*da917039SDavid du Colombier
80*da917039SDavid du Colombier ulong cpuentry = 0;
81*da917039SDavid du Colombier
82*da917039SDavid du Colombier char **ini;
83*da917039SDavid du Colombier char *defaultpartition;
84*da917039SDavid du Colombier char *persist;
85*da917039SDavid du Colombier
86*da917039SDavid du Colombier int debugload;
87*da917039SDavid du Colombier int iniread;
88*da917039SDavid du Colombier int pxe = 1;
89*da917039SDavid du Colombier int scsi0port;
90*da917039SDavid du Colombier int vga;
91*da917039SDavid du Colombier
92*da917039SDavid du Colombier uintptr memstart; /* set before main called */
93*da917039SDavid du Colombier uintptr vectorbase; /* set before main called */
94*da917039SDavid du Colombier
95*da917039SDavid du Colombier static uintptr memsz;
96*da917039SDavid du Colombier
97*da917039SDavid du Colombier static Medium*
parse(char * line,char ** file)98*da917039SDavid du Colombier parse(char *line, char **file)
99*da917039SDavid du Colombier {
100*da917039SDavid du Colombier char *p;
101*da917039SDavid du Colombier Type *tp;
102*da917039SDavid du Colombier Medium *mp;
103*da917039SDavid du Colombier
104*da917039SDavid du Colombier if(p = strchr(line, '!')) {
105*da917039SDavid du Colombier *p++ = 0;
106*da917039SDavid du Colombier *file = p;
107*da917039SDavid du Colombier } else
108*da917039SDavid du Colombier *file = "";
109*da917039SDavid du Colombier
110*da917039SDavid du Colombier tp = types;
111*da917039SDavid du Colombier for(mp = tp->media; mp; mp = mp->next)
112*da917039SDavid du Colombier if(strcmp(mp->name, line) == 0)
113*da917039SDavid du Colombier return mp;
114*da917039SDavid du Colombier if(p)
115*da917039SDavid du Colombier *--p = '!';
116*da917039SDavid du Colombier return nil;
117*da917039SDavid du Colombier }
118*da917039SDavid du Colombier
119*da917039SDavid du Colombier static int
boot(Medium * mp,char * file)120*da917039SDavid du Colombier boot(Medium *mp, char *file)
121*da917039SDavid du Colombier {
122*da917039SDavid du Colombier Type *tp;
123*da917039SDavid du Colombier Medium *xmp;
124*da917039SDavid du Colombier static int didaddconf;
125*da917039SDavid du Colombier Boot b;
126*da917039SDavid du Colombier
127*da917039SDavid du Colombier memset(&b, 0, sizeof b);
128*da917039SDavid du Colombier b.state = INITKERNEL;
129*da917039SDavid du Colombier
130*da917039SDavid du Colombier if(didaddconf == 0) {
131*da917039SDavid du Colombier didaddconf = 1;
132*da917039SDavid du Colombier tp = types;
133*da917039SDavid du Colombier if(tp->addconf)
134*da917039SDavid du Colombier for(xmp = tp->media; xmp; xmp = xmp->next)
135*da917039SDavid du Colombier (*tp->addconf)(xmp->dev);
136*da917039SDavid du Colombier }
137*da917039SDavid du Colombier
138*da917039SDavid du Colombier seprint(BOOTLINE, BOOTLINE + BOOTLINELEN, "%s!%s", mp->name, file);
139*da917039SDavid du Colombier print("booting %s!%s\n", mp->name, file);
140*da917039SDavid du Colombier return (*mp->type->boot)(mp->dev, file, &b);
141*da917039SDavid du Colombier }
142*da917039SDavid du Colombier
143*da917039SDavid du Colombier static Medium*
allocm(Type * tp)144*da917039SDavid du Colombier allocm(Type *tp)
145*da917039SDavid du Colombier {
146*da917039SDavid du Colombier Medium **l;
147*da917039SDavid du Colombier
148*da917039SDavid du Colombier if(curmedium >= &media[Nmedia])
149*da917039SDavid du Colombier return 0;
150*da917039SDavid du Colombier
151*da917039SDavid du Colombier for(l = &tp->media; *l; l = &(*l)->next)
152*da917039SDavid du Colombier ;
153*da917039SDavid du Colombier *l = curmedium++;
154*da917039SDavid du Colombier return *l;
155*da917039SDavid du Colombier }
156*da917039SDavid du Colombier
157*da917039SDavid du Colombier Medium*
probe(int type,int flag,int dev)158*da917039SDavid du Colombier probe(int type, int flag, int dev)
159*da917039SDavid du Colombier {
160*da917039SDavid du Colombier Type *tp;
161*da917039SDavid du Colombier int i;
162*da917039SDavid du Colombier Medium *mp;
163*da917039SDavid du Colombier File f;
164*da917039SDavid du Colombier Fs *fs;
165*da917039SDavid du Colombier char **partp;
166*da917039SDavid du Colombier
167*da917039SDavid du Colombier tp = types;
168*da917039SDavid du Colombier if(type != Tany && type != tp->type)
169*da917039SDavid du Colombier return 0;
170*da917039SDavid du Colombier
171*da917039SDavid du Colombier if(flag != Fnone)
172*da917039SDavid du Colombier for(mp = tp->media; mp; mp = mp->next)
173*da917039SDavid du Colombier if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
174*da917039SDavid du Colombier return mp;
175*da917039SDavid du Colombier if((tp->flag & Fprobe) == 0){
176*da917039SDavid du Colombier tp->flag |= Fprobe;
177*da917039SDavid du Colombier tp->mask = (*tp->init)();
178*da917039SDavid du Colombier }
179*da917039SDavid du Colombier
180*da917039SDavid du Colombier for(i = 0; tp->mask; i++){
181*da917039SDavid du Colombier if((tp->mask & (1<<i)) == 0)
182*da917039SDavid du Colombier continue;
183*da917039SDavid du Colombier tp->mask &= ~(1<<i);
184*da917039SDavid du Colombier
185*da917039SDavid du Colombier if((mp = allocm(tp)) == 0)
186*da917039SDavid du Colombier continue;
187*da917039SDavid du Colombier
188*da917039SDavid du Colombier mp->dev = i;
189*da917039SDavid du Colombier mp->flag = tp->flag;
190*da917039SDavid du Colombier mp->type = tp;
191*da917039SDavid du Colombier (*tp->initdev)(i, mp->name);
192*da917039SDavid du Colombier
193*da917039SDavid du Colombier if(mp->flag & Fini){
194*da917039SDavid du Colombier mp->flag &= ~Fini;
195*da917039SDavid du Colombier for(partp = tp->parts; *partp; partp++){
196*da917039SDavid du Colombier if((fs = (*tp->getfspart)(i, *partp, 0)) == nil)
197*da917039SDavid du Colombier continue;
198*da917039SDavid du Colombier
199*da917039SDavid du Colombier for(ini = tp->inis; *ini; ini++)
200*da917039SDavid du Colombier if(fswalk(fs, *ini, &f) > 0){
201*da917039SDavid du Colombier mp->inifs = fs;
202*da917039SDavid du Colombier mp->part = *partp;
203*da917039SDavid du Colombier mp->ini = f.path;
204*da917039SDavid du Colombier mp->flag |= Fini;
205*da917039SDavid du Colombier goto Break2;
206*da917039SDavid du Colombier }
207*da917039SDavid du Colombier }
208*da917039SDavid du Colombier }
209*da917039SDavid du Colombier Break2:
210*da917039SDavid du Colombier if((flag & mp->flag) && (dev == Dany || dev == i))
211*da917039SDavid du Colombier return mp;
212*da917039SDavid du Colombier }
213*da917039SDavid du Colombier return 0;
214*da917039SDavid du Colombier }
215*da917039SDavid du Colombier
216*da917039SDavid du Colombier enum {
217*da917039SDavid du Colombier Kilo = 1024,
218*da917039SDavid du Colombier };
219*da917039SDavid du Colombier
220*da917039SDavid du Colombier /* make sure we don't get the write system call from libc */
221*da917039SDavid du Colombier long
write(int fd,void * buf,long nbytes)222*da917039SDavid du Colombier write(int fd, void *buf, long nbytes)
223*da917039SDavid du Colombier {
224*da917039SDavid du Colombier USED(fd);
225*da917039SDavid du Colombier vuartputs(buf, nbytes);
226*da917039SDavid du Colombier return nbytes;
227*da917039SDavid du Colombier }
228*da917039SDavid du Colombier
229*da917039SDavid du Colombier /*
230*da917039SDavid du Colombier * write zero words to an entire cache line (the one containing addr).
231*da917039SDavid du Colombier * does not flush the data cache.
232*da917039SDavid du Colombier */
233*da917039SDavid du Colombier void
cacheline0(uintptr addr)234*da917039SDavid du Colombier cacheline0(uintptr addr)
235*da917039SDavid du Colombier {
236*da917039SDavid du Colombier ulong *sp, *endmem;
237*da917039SDavid du Colombier
238*da917039SDavid du Colombier addr &= ~(DCACHELINESZ - 1);
239*da917039SDavid du Colombier endmem = (ulong *)(addr + DCACHELINESZ);
240*da917039SDavid du Colombier for (sp = (ulong *)addr; sp < endmem; sp++)
241*da917039SDavid du Colombier *sp = 0;
242*da917039SDavid du Colombier // coherence();
243*da917039SDavid du Colombier }
244*da917039SDavid du Colombier
245*da917039SDavid du Colombier /* force the four qtm write buffers to be retired to dram by filling them. */
246*da917039SDavid du Colombier void
flushwrbufs(void)247*da917039SDavid du Colombier flushwrbufs(void)
248*da917039SDavid du Colombier {
249*da917039SDavid du Colombier if (!securemem)
250*da917039SDavid du Colombier return;
251*da917039SDavid du Colombier cacheline0(PHYSDRAM);
252*da917039SDavid du Colombier cacheline0(PHYSDRAM + DCACHELINESZ);
253*da917039SDavid du Colombier cacheline0(PHYSDRAM + 2*DCACHELINESZ);
254*da917039SDavid du Colombier cacheline0(PHYSDRAM + 3*DCACHELINESZ);
255*da917039SDavid du Colombier coherence();
256*da917039SDavid du Colombier }
257*da917039SDavid du Colombier
258*da917039SDavid du Colombier static void
vfyzeros(ulong * addr,ulong * end)259*da917039SDavid du Colombier vfyzeros(ulong *addr, ulong *end)
260*da917039SDavid du Colombier {
261*da917039SDavid du Colombier ulong wd;
262*da917039SDavid du Colombier ulong *sp;
263*da917039SDavid du Colombier
264*da917039SDavid du Colombier for (sp = addr; sp < end; sp++) {
265*da917039SDavid du Colombier wd = *sp;
266*da917039SDavid du Colombier if (wd != 0) {
267*da917039SDavid du Colombier PROG('?')
268*da917039SDavid du Colombier panic("bad dram: %#p read back as %#lux not 0", sp, wd);
269*da917039SDavid du Colombier }
270*da917039SDavid du Colombier }
271*da917039SDavid du Colombier }
272*da917039SDavid du Colombier
273*da917039SDavid du Colombier static int
memreset(void)274*da917039SDavid du Colombier memreset(void)
275*da917039SDavid du Colombier {
276*da917039SDavid du Colombier int i, cnt;
277*da917039SDavid du Colombier uintptr addr, endmem;
278*da917039SDavid du Colombier
279*da917039SDavid du Colombier cnt = 0;
280*da917039SDavid du Colombier if (securemem)
281*da917039SDavid du Colombier cnt = qtmmemreset();
282*da917039SDavid du Colombier else
283*da917039SDavid du Colombier /* normal dram init. should take 100—250 ms. */
284*da917039SDavid du Colombier for (i = 10*1000*1000; i-- > 0; )
285*da917039SDavid du Colombier cnt++;
286*da917039SDavid du Colombier PROG('t')
287*da917039SDavid du Colombier /*
288*da917039SDavid du Colombier * dram must be done initialising now,
289*da917039SDavid du Colombier * but qtm needs us to zero it *all* before any other use,
290*da917039SDavid du Colombier * to set the macs. even for non-qtm dram, it might be wise
291*da917039SDavid du Colombier * to ensure that all the ecc bits are set.
292*da917039SDavid du Colombier */
293*da917039SDavid du Colombier memsz = memsize(); /* may carefully probe qtm dram */
294*da917039SDavid du Colombier qtmerrtest("sizing memory");
295*da917039SDavid du Colombier
296*da917039SDavid du Colombier dcflush(PHYSSRAM, (1ULL << 32) - PHYSSRAM);
297*da917039SDavid du Colombier cachesinvalidate();
298*da917039SDavid du Colombier
299*da917039SDavid du Colombier endmem = PHYSDRAM + memsz;
300*da917039SDavid du Colombier for (addr = PHYSDRAM; addr < endmem; addr += DCACHELINESZ) {
301*da917039SDavid du Colombier cacheline0(addr);
302*da917039SDavid du Colombier qtmerrtestaddr(addr);
303*da917039SDavid du Colombier }
304*da917039SDavid du Colombier assert(addr == endmem);
305*da917039SDavid du Colombier coherence();
306*da917039SDavid du Colombier flushwrbufs();
307*da917039SDavid du Colombier qtmerrtest("zeroing dram");
308*da917039SDavid du Colombier
309*da917039SDavid du Colombier #ifdef PARANOID
310*da917039SDavid du Colombier vfyzeros((ulong *)PHYSDRAM, (ulong *)endmem);
311*da917039SDavid du Colombier #else
312*da917039SDavid du Colombier vfyzeros((ulong *)(endmem - MB), (ulong *)endmem);
313*da917039SDavid du Colombier #endif
314*da917039SDavid du Colombier dcflush(PHYSDRAM, memsz);
315*da917039SDavid du Colombier dcflush(PHYSSRAM, (1ULL << 32) - PHYSSRAM);
316*da917039SDavid du Colombier cachesinvalidate();
317*da917039SDavid du Colombier
318*da917039SDavid du Colombier /*
319*da917039SDavid du Colombier * Hallelujah! We can finally treat qtm dram just like real memory,
320*da917039SDavid du Colombier * except that the last (partial) page is funny and should be avoided
321*da917039SDavid du Colombier * after initialising it.
322*da917039SDavid du Colombier * It happens even with caches off, so it's a bit hard to explain
323*da917039SDavid du Colombier * why it should be funny.
324*da917039SDavid du Colombier */
325*da917039SDavid du Colombier memsz &= ~(BY2PG - 1);
326*da917039SDavid du Colombier endmem = PHYSDRAM + memsz;
327*da917039SDavid du Colombier
328*da917039SDavid du Colombier #ifdef PARANOID
329*da917039SDavid du Colombier vfyzeros((ulong *)PHYSDRAM, (ulong *)endmem);
330*da917039SDavid du Colombier #else
331*da917039SDavid du Colombier vfyzeros((ulong *)PHYSDRAM, (ulong *)(PHYSDRAM + MB));
332*da917039SDavid du Colombier vfyzeros((ulong *)(endmem - MB), (ulong *)endmem);
333*da917039SDavid du Colombier #endif
334*da917039SDavid du Colombier qtmerrtest("reading back dram");
335*da917039SDavid du Colombier return cnt;
336*da917039SDavid du Colombier }
337*da917039SDavid du Colombier
338*da917039SDavid du Colombier static void
memtest(void)339*da917039SDavid du Colombier memtest(void)
340*da917039SDavid du Colombier {
341*da917039SDavid du Colombier ulong wd;
342*da917039SDavid du Colombier ulong *sp, *endmem;
343*da917039SDavid du Colombier
344*da917039SDavid du Colombier /*
345*da917039SDavid du Colombier * verify that (possibly secure) dram is more or less working.
346*da917039SDavid du Colombier * write address of each word into that word.
347*da917039SDavid du Colombier */
348*da917039SDavid du Colombier #ifdef PARANOID
349*da917039SDavid du Colombier endmem = (ulong *)(PHYSDRAM + memsz);
350*da917039SDavid du Colombier #else
351*da917039SDavid du Colombier endmem = (ulong *)(PHYSDRAM + MB); /* just the first MB */
352*da917039SDavid du Colombier #endif
353*da917039SDavid du Colombier for (sp = (ulong *)PHYSDRAM; sp < endmem; sp++)
354*da917039SDavid du Colombier *sp = (ulong)sp;
355*da917039SDavid du Colombier coherence();
356*da917039SDavid du Colombier /* no need to flush caches, caches are off */
357*da917039SDavid du Colombier
358*da917039SDavid du Colombier /*
359*da917039SDavid du Colombier * now verify that each word contains its address.
360*da917039SDavid du Colombier */
361*da917039SDavid du Colombier for (sp = (ulong *)PHYSDRAM; sp < endmem; sp++) {
362*da917039SDavid du Colombier wd = *sp;
363*da917039SDavid du Colombier if (wd != (ulong)sp) {
364*da917039SDavid du Colombier PROG('?')
365*da917039SDavid du Colombier panic("bad dram: %#p read back as %#lux", sp, wd);
366*da917039SDavid du Colombier }
367*da917039SDavid du Colombier }
368*da917039SDavid du Colombier PROG('t')
369*da917039SDavid du Colombier /* memset((void *)PHYSDRAM, 0, memsz); /* good hygiene? */
370*da917039SDavid du Colombier }
371*da917039SDavid du Colombier
372*da917039SDavid du Colombier enum {
373*da917039SDavid du Colombier Testbase = PHYSDRAM + 0x4000,
374*da917039SDavid du Colombier };
375*da917039SDavid du Colombier
376*da917039SDavid du Colombier void
meminit(void)377*da917039SDavid du Colombier meminit(void)
378*da917039SDavid du Colombier {
379*da917039SDavid du Colombier int i;
380*da917039SDavid du Colombier uchar *memc;
381*da917039SDavid du Colombier ulong *mem;
382*da917039SDavid du Colombier
383*da917039SDavid du Colombier // iprint("sanity: writing...");
384*da917039SDavid du Colombier mem = (ulong *)Testbase;
385*da917039SDavid du Colombier memc = (uchar *)Testbase;
386*da917039SDavid du Colombier
387*da917039SDavid du Colombier memset(mem, 0252, Kilo);
388*da917039SDavid du Colombier coherence();
389*da917039SDavid du Colombier dcflush(Testbase, Kilo);
390*da917039SDavid du Colombier
391*da917039SDavid du Colombier // iprint("reading...");
392*da917039SDavid du Colombier for (i = 0; i < Kilo; i++)
393*da917039SDavid du Colombier if (memc[i] != 0252)
394*da917039SDavid du Colombier panic("dram not retaining data");
395*da917039SDavid du Colombier
396*da917039SDavid du Colombier // iprint("zeroing...");
397*da917039SDavid du Colombier memset(mem, '\0', Kilo);
398*da917039SDavid du Colombier coherence();
399*da917039SDavid du Colombier dcflush(Testbase, Kilo);
400*da917039SDavid du Colombier if (*mem)
401*da917039SDavid du Colombier panic("zeroed dram not zero");
402*da917039SDavid du Colombier // iprint("\n");
403*da917039SDavid du Colombier }
404*da917039SDavid du Colombier
405*da917039SDavid du Colombier static int idx;
406*da917039SDavid du Colombier static char numb[32];
407*da917039SDavid du Colombier
408*da917039SDavid du Colombier static void
gendigs(ulong n)409*da917039SDavid du Colombier gendigs(ulong n)
410*da917039SDavid du Colombier {
411*da917039SDavid du Colombier int dig;
412*da917039SDavid du Colombier
413*da917039SDavid du Colombier do {
414*da917039SDavid du Colombier dig = n % 16;
415*da917039SDavid du Colombier if (dig > 9)
416*da917039SDavid du Colombier numb[idx--] = 'A' + dig - 10;
417*da917039SDavid du Colombier else
418*da917039SDavid du Colombier numb[idx--] = '0' + dig;
419*da917039SDavid du Colombier } while ((n /= 16) > 0);
420*da917039SDavid du Colombier }
421*da917039SDavid du Colombier
422*da917039SDavid du Colombier static void
prnum(ulong n)423*da917039SDavid du Colombier prnum(ulong n)
424*da917039SDavid du Colombier {
425*da917039SDavid du Colombier // PROG(' ')
426*da917039SDavid du Colombier idx = nelem(numb) - 1;
427*da917039SDavid du Colombier gendigs(n);
428*da917039SDavid du Colombier for (; idx < nelem(numb); idx++)
429*da917039SDavid du Colombier PROG(numb[idx])
430*da917039SDavid du Colombier PROG('\n')
431*da917039SDavid du Colombier PROG('\r')
432*da917039SDavid du Colombier }
433*da917039SDavid du Colombier
434*da917039SDavid du Colombier extern uintptr vectorbase;
435*da917039SDavid du Colombier
436*da917039SDavid du Colombier void
main(void)437*da917039SDavid du Colombier main(void)
438*da917039SDavid du Colombier {
439*da917039SDavid du Colombier int flag, i, j, mode, tried;
440*da917039SDavid du Colombier char def[2*NAMELEN], line[80], *p, *file;
441*da917039SDavid du Colombier Medium *mp;
442*da917039SDavid du Colombier Type *tp;
443*da917039SDavid du Colombier static int savcnt, caching;
444*da917039SDavid du Colombier static ulong vfy = Datamagic;
445*da917039SDavid du Colombier
446*da917039SDavid du Colombier /*
447*da917039SDavid du Colombier * all cpus start executing at reset address, thus start of sram.
448*da917039SDavid du Colombier * cpu0 loads the kernel;
449*da917039SDavid du Colombier * all others just jump to the (by now) loaded kernel.
450*da917039SDavid du Colombier */
451*da917039SDavid du Colombier /* "\r\nPlan " already printed by l.s */
452*da917039SDavid du Colombier if (getpir() != 0) {
453*da917039SDavid du Colombier for (j = 0; j < 6; j++)
454*da917039SDavid du Colombier for (i = 2*1000*1000*1000; i > 0; i--)
455*da917039SDavid du Colombier ;
456*da917039SDavid du Colombier
457*da917039SDavid du Colombier cachesinvalidate();
458*da917039SDavid du Colombier while(cpuentry == 0)
459*da917039SDavid du Colombier cachesinvalidate();
460*da917039SDavid du Colombier
461*da917039SDavid du Colombier for (j = 0; j < 6; j++)
462*da917039SDavid du Colombier for (i = 2*1000*1000*1000; i > 0; i--)
463*da917039SDavid du Colombier ;
464*da917039SDavid du Colombier warp9(PADDR(cpuentry));
465*da917039SDavid du Colombier }
466*da917039SDavid du Colombier
467*da917039SDavid du Colombier /*
468*da917039SDavid du Colombier * we may have to realign the data segment; apparently ql -R4096
469*da917039SDavid du Colombier * does not pad the text segment.
470*da917039SDavid du Colombier */
471*da917039SDavid du Colombier if (vfy != Datamagic)
472*da917039SDavid du Colombier memmove(bdata, etext, edata - bdata);
473*da917039SDavid du Colombier if (vfy != Datamagic) {
474*da917039SDavid du Colombier PROG('?')
475*da917039SDavid du Colombier panic("misaligned data segment");
476*da917039SDavid du Colombier }
477*da917039SDavid du Colombier // memset(edata, 0, end - edata); /* zero bss */
478*da917039SDavid du Colombier
479*da917039SDavid du Colombier PROG('9')
480*da917039SDavid du Colombier /*
481*da917039SDavid du Colombier * trap vectors are in sram, so we don't have to wait for dram
482*da917039SDavid du Colombier * to become ready to initialise them.
483*da917039SDavid du Colombier */
484*da917039SDavid du Colombier trapinit();
485*da917039SDavid du Colombier PROG(' ')
486*da917039SDavid du Colombier securemem = (probeaddr(Qtm) >= 0);
487*da917039SDavid du Colombier if (securemem)
488*da917039SDavid du Colombier PROG('q')
489*da917039SDavid du Colombier else
490*da917039SDavid du Colombier PROG('n')
491*da917039SDavid du Colombier PROG(' ')
492*da917039SDavid du Colombier
493*da917039SDavid du Colombier /*
494*da917039SDavid du Colombier * the stack is now at top of sram, and entry to main just pushed
495*da917039SDavid du Colombier * stuff onto it. the new stack will be at the top of dram,
496*da917039SDavid du Colombier * when dram finishes initialising itself.
497*da917039SDavid du Colombier */
498*da917039SDavid du Colombier PROG('B')
499*da917039SDavid du Colombier PROG('o')
500*da917039SDavid du Colombier PROG('o')
501*da917039SDavid du Colombier /* do voodoo to make dram usable; prints "t". sets memsz. */
502*da917039SDavid du Colombier savcnt = memreset();
503*da917039SDavid du Colombier PROG('s')
504*da917039SDavid du Colombier memtest(); /* also prints "t" */
505*da917039SDavid du Colombier intrinit();
506*da917039SDavid du Colombier
507*da917039SDavid du Colombier caching = cacheson();
508*da917039SDavid du Colombier
509*da917039SDavid du Colombier /*
510*da917039SDavid du Colombier * switch to the dram stack just below the end of dram.
511*da917039SDavid du Colombier * have to allow enough room for main's local variables,
512*da917039SDavid du Colombier * to avoid address faults.
513*da917039SDavid du Colombier */
514*da917039SDavid du Colombier
515*da917039SDavid du Colombier PROG('r')
516*da917039SDavid du Colombier setsp(memsz - BY2PG);
517*da917039SDavid du Colombier
518*da917039SDavid du Colombier PROG('a')
519*da917039SDavid du Colombier meminit();
520*da917039SDavid du Colombier /* memory is now more or less normal from a software perspective. */
521*da917039SDavid du Colombier
522*da917039SDavid du Colombier memset(m, 0, sizeof(Mach));
523*da917039SDavid du Colombier m->machno = 0;
524*da917039SDavid du Colombier m->up = nil;
525*da917039SDavid du Colombier MACHP(0) = m;
526*da917039SDavid du Colombier
527*da917039SDavid du Colombier /*
528*da917039SDavid du Colombier * the Mach struct is now initialised, so we can print safely.
529*da917039SDavid du Colombier */
530*da917039SDavid du Colombier
531*da917039SDavid du Colombier // print("\nPlan 9 bootstrap"); /* already printed, 1 char at a time */
532*da917039SDavid du Colombier print("p");
533*da917039SDavid du Colombier // print("\n%d iterations waiting for %s init done\n",
534*da917039SDavid du Colombier // savcnt, (securemem? "qtm": "dram"));
535*da917039SDavid du Colombier if (securemem)
536*da917039SDavid du Colombier print("; secure memory");
537*da917039SDavid du Colombier print("; caches %s\n", (caching? "on": "off"));
538*da917039SDavid du Colombier print("\n");
539*da917039SDavid du Colombier if ((uintptr)end < PHYSSRAM)
540*da917039SDavid du Colombier panic("too big; end %#p before sram @ %#ux", end, PHYSSRAM);
541*da917039SDavid du Colombier print("memory found: %,lud (%lux)\n", memsz, memsz);
542*da917039SDavid du Colombier
543*da917039SDavid du Colombier spllo();
544*da917039SDavid du Colombier clockinit();
545*da917039SDavid du Colombier prcpuid();
546*da917039SDavid du Colombier // etherinit(); /* probe() calls this */
547*da917039SDavid du Colombier kbdinit();
548*da917039SDavid du Colombier
549*da917039SDavid du Colombier /*
550*da917039SDavid du Colombier * find and read plan9.ini, setting configuration variables.
551*da917039SDavid du Colombier */
552*da917039SDavid du Colombier tp = types;
553*da917039SDavid du Colombier // debug = debugload = 1; // DEBUG
554*da917039SDavid du Colombier if(pxe && (mp = probe(tp->type, Fini, Dany)) && mp->flag & Fini){
555*da917039SDavid du Colombier if (debug)
556*da917039SDavid du Colombier print("using %s!%s!%s\n", mp->name, mp->part, mp->ini);
557*da917039SDavid du Colombier // iniread = !dotini(mp->inifs);
558*da917039SDavid du Colombier }
559*da917039SDavid du Colombier
560*da917039SDavid du Colombier /*
561*da917039SDavid du Colombier * we should now have read plan9.ini, if any.
562*da917039SDavid du Colombier */
563*da917039SDavid du Colombier persist = getconf("*bootppersist");
564*da917039SDavid du Colombier
565*da917039SDavid du Colombier tried = 0;
566*da917039SDavid du Colombier mode = Mauto;
567*da917039SDavid du Colombier
568*da917039SDavid du Colombier p = getconf("bootfile");
569*da917039SDavid du Colombier if(p != 0) {
570*da917039SDavid du Colombier mode = Manual;
571*da917039SDavid du Colombier for(i = 0; i < NMode; i++){
572*da917039SDavid du Colombier if(strcmp(p, modes[i].name) == 0){
573*da917039SDavid du Colombier mode = modes[i].mode;
574*da917039SDavid du Colombier goto done;
575*da917039SDavid du Colombier }
576*da917039SDavid du Colombier }
577*da917039SDavid du Colombier if((mp = parse(p, &file)) == nil)
578*da917039SDavid du Colombier print("Unknown boot device: %s\n", p);
579*da917039SDavid du Colombier else
580*da917039SDavid du Colombier tried = boot(mp, file);
581*da917039SDavid du Colombier }
582*da917039SDavid du Colombier done:
583*da917039SDavid du Colombier if(tried == 0 && mode != Manual){
584*da917039SDavid du Colombier flag = Fany;
585*da917039SDavid du Colombier if(mode == Mlocal)
586*da917039SDavid du Colombier flag &= ~Fbootp;
587*da917039SDavid du Colombier if((mp = probe(Tany, flag, Dany)))
588*da917039SDavid du Colombier boot(mp, "");
589*da917039SDavid du Colombier if (debugload)
590*da917039SDavid du Colombier print("end auto probe\n");
591*da917039SDavid du Colombier }
592*da917039SDavid du Colombier
593*da917039SDavid du Colombier def[0] = 0;
594*da917039SDavid du Colombier if(p = getconf("bootdef"))
595*da917039SDavid du Colombier strecpy(def, def + sizeof def, p);
596*da917039SDavid du Colombier flag = 0;
597*da917039SDavid du Colombier tp = types;
598*da917039SDavid du Colombier for(mp = tp->media; mp; mp = mp->next){
599*da917039SDavid du Colombier if(flag == 0){
600*da917039SDavid du Colombier flag = 1;
601*da917039SDavid du Colombier print("Boot devices:");
602*da917039SDavid du Colombier }
603*da917039SDavid du Colombier (*tp->printdevs)(mp->dev);
604*da917039SDavid du Colombier }
605*da917039SDavid du Colombier if(flag)
606*da917039SDavid du Colombier print("\n");
607*da917039SDavid du Colombier
608*da917039SDavid du Colombier /*
609*da917039SDavid du Colombier * e.g., *bootppersist=ether0
610*da917039SDavid du Colombier *
611*da917039SDavid du Colombier * previously, we looped in bootpopen if we were pxeload or if
612*da917039SDavid du Colombier * *bootppersist was set. that doesn't work well for pxeload where
613*da917039SDavid du Colombier * bootp will never succeed on the first interface but only on another
614*da917039SDavid du Colombier * interface.
615*da917039SDavid du Colombier */
616*da917039SDavid du Colombier //print("boot mode %s\n", modes[mode].name);
617*da917039SDavid du Colombier if (mode == Mauto && persist != nil &&
618*da917039SDavid du Colombier (mp = parse(persist, &file)) != nil) {
619*da917039SDavid du Colombier boot(mp, file);
620*da917039SDavid du Colombier print("pausing before retry...");
621*da917039SDavid du Colombier delay(30*1000);
622*da917039SDavid du Colombier print("\n");
623*da917039SDavid du Colombier }
624*da917039SDavid du Colombier
625*da917039SDavid du Colombier for(;;){
626*da917039SDavid du Colombier if(getstr("boot from", line, sizeof(line), def,
627*da917039SDavid du Colombier (mode != Manual)*15) >= 0)
628*da917039SDavid du Colombier if(mp = parse(line, &file))
629*da917039SDavid du Colombier boot(mp, file);
630*da917039SDavid du Colombier def[0] = 0;
631*da917039SDavid du Colombier }
632*da917039SDavid du Colombier }
633*da917039SDavid du Colombier
634*da917039SDavid du Colombier int
getfields(char * lp,char ** fields,int n,char sep)635*da917039SDavid du Colombier getfields(char *lp, char **fields, int n, char sep)
636*da917039SDavid du Colombier {
637*da917039SDavid du Colombier int i;
638*da917039SDavid du Colombier
639*da917039SDavid du Colombier for(i = 0; lp && *lp && i < n; i++){
640*da917039SDavid du Colombier while(*lp == sep)
641*da917039SDavid du Colombier *lp++ = 0;
642*da917039SDavid du Colombier if(*lp == 0)
643*da917039SDavid du Colombier break;
644*da917039SDavid du Colombier fields[i] = lp;
645*da917039SDavid du Colombier while(*lp && *lp != sep){
646*da917039SDavid du Colombier if(*lp == '\\' && *(lp+1) == '\n')
647*da917039SDavid du Colombier *lp++ = ' ';
648*da917039SDavid du Colombier lp++;
649*da917039SDavid du Colombier }
650*da917039SDavid du Colombier }
651*da917039SDavid du Colombier return i;
652*da917039SDavid du Colombier }
653*da917039SDavid du Colombier
654*da917039SDavid du Colombier int
cistrcmp(char * a,char * b)655*da917039SDavid du Colombier cistrcmp(char *a, char *b)
656*da917039SDavid du Colombier {
657*da917039SDavid du Colombier int ac, bc;
658*da917039SDavid du Colombier
659*da917039SDavid du Colombier for(;;){
660*da917039SDavid du Colombier ac = *a++;
661*da917039SDavid du Colombier bc = *b++;
662*da917039SDavid du Colombier
663*da917039SDavid du Colombier if(ac >= 'A' && ac <= 'Z')
664*da917039SDavid du Colombier ac = 'a' + (ac - 'A');
665*da917039SDavid du Colombier if(bc >= 'A' && bc <= 'Z')
666*da917039SDavid du Colombier bc = 'a' + (bc - 'A');
667*da917039SDavid du Colombier ac -= bc;
668*da917039SDavid du Colombier if(ac)
669*da917039SDavid du Colombier return ac;
670*da917039SDavid du Colombier if(bc == 0)
671*da917039SDavid du Colombier break;
672*da917039SDavid du Colombier }
673*da917039SDavid du Colombier return 0;
674*da917039SDavid du Colombier }
675*da917039SDavid du Colombier
676*da917039SDavid du Colombier int
cistrncmp(char * a,char * b,int n)677*da917039SDavid du Colombier cistrncmp(char *a, char *b, int n)
678*da917039SDavid du Colombier {
679*da917039SDavid du Colombier unsigned ac, bc;
680*da917039SDavid du Colombier
681*da917039SDavid du Colombier while(n > 0){
682*da917039SDavid du Colombier ac = *a++;
683*da917039SDavid du Colombier bc = *b++;
684*da917039SDavid du Colombier n--;
685*da917039SDavid du Colombier
686*da917039SDavid du Colombier if(ac >= 'A' && ac <= 'Z')
687*da917039SDavid du Colombier ac = 'a' + (ac - 'A');
688*da917039SDavid du Colombier if(bc >= 'A' && bc <= 'Z')
689*da917039SDavid du Colombier bc = 'a' + (bc - 'A');
690*da917039SDavid du Colombier
691*da917039SDavid du Colombier ac -= bc;
692*da917039SDavid du Colombier if(ac)
693*da917039SDavid du Colombier return ac;
694*da917039SDavid du Colombier if(bc == 0)
695*da917039SDavid du Colombier break;
696*da917039SDavid du Colombier }
697*da917039SDavid du Colombier
698*da917039SDavid du Colombier return 0;
699*da917039SDavid du Colombier }
700*da917039SDavid du Colombier
701*da917039SDavid du Colombier #define PSTART (8*MB) /* start allocating here */
702*da917039SDavid du Colombier #define PEND (100*MB) /* below stack */
703*da917039SDavid du Colombier
704*da917039SDavid du Colombier static ulong palloc = PSTART;
705*da917039SDavid du Colombier
706*da917039SDavid du Colombier void*
ialloc(ulong n,int align)707*da917039SDavid du Colombier ialloc(ulong n, int align)
708*da917039SDavid du Colombier {
709*da917039SDavid du Colombier ulong p;
710*da917039SDavid du Colombier int a;
711*da917039SDavid du Colombier
712*da917039SDavid du Colombier assert(palloc >= PSTART);
713*da917039SDavid du Colombier p = palloc;
714*da917039SDavid du Colombier if(align <= 0)
715*da917039SDavid du Colombier align = 4;
716*da917039SDavid du Colombier if(a = n % align)
717*da917039SDavid du Colombier n += align - a;
718*da917039SDavid du Colombier if(a = p % align)
719*da917039SDavid du Colombier p += align - a;
720*da917039SDavid du Colombier
721*da917039SDavid du Colombier palloc = p+n;
722*da917039SDavid du Colombier if(palloc > PEND)
723*da917039SDavid du Colombier panic("ialloc(%lud, %d) called from %#p",
724*da917039SDavid du Colombier n, align, getcallerpc(&n));
725*da917039SDavid du Colombier return memset((void*)p, 0, n);
726*da917039SDavid du Colombier }
727*da917039SDavid du Colombier
728*da917039SDavid du Colombier void*
xspanalloc(ulong size,int align,ulong span)729*da917039SDavid du Colombier xspanalloc(ulong size, int align, ulong span)
730*da917039SDavid du Colombier {
731*da917039SDavid du Colombier ulong a, v;
732*da917039SDavid du Colombier
733*da917039SDavid du Colombier if((palloc + (size+align+span)) > PEND)
734*da917039SDavid du Colombier panic("xspanalloc(%lud, %d, 0x%lux) called from %#p",
735*da917039SDavid du Colombier size, align, span, getcallerpc(&size));
736*da917039SDavid du Colombier
737*da917039SDavid du Colombier a = (ulong)ialloc(size+align+span, 0);
738*da917039SDavid du Colombier
739*da917039SDavid du Colombier if(span > 2)
740*da917039SDavid du Colombier v = (a + span) & ~(span-1);
741*da917039SDavid du Colombier else
742*da917039SDavid du Colombier v = a;
743*da917039SDavid du Colombier
744*da917039SDavid du Colombier if(align > 1)
745*da917039SDavid du Colombier v = (v + align) & ~(align-1);
746*da917039SDavid du Colombier
747*da917039SDavid du Colombier return (void*)v;
748*da917039SDavid du Colombier }
749*da917039SDavid du Colombier
750*da917039SDavid du Colombier static Block *allocbp;
751*da917039SDavid du Colombier
752*da917039SDavid du Colombier Block*
allocb(int size)753*da917039SDavid du Colombier allocb(int size)
754*da917039SDavid du Colombier {
755*da917039SDavid du Colombier Block *bp, **lbp;
756*da917039SDavid du Colombier ulong addr;
757*da917039SDavid du Colombier
758*da917039SDavid du Colombier lbp = &allocbp;
759*da917039SDavid du Colombier for(bp = *lbp; bp; bp = bp->next){
760*da917039SDavid du Colombier if((bp->lim - bp->base) >= size){
761*da917039SDavid du Colombier *lbp = bp->next;
762*da917039SDavid du Colombier break;
763*da917039SDavid du Colombier }
764*da917039SDavid du Colombier lbp = &bp->next;
765*da917039SDavid du Colombier }
766*da917039SDavid du Colombier if(bp == 0){
767*da917039SDavid du Colombier if((palloc + (sizeof(Block)+size+64)) > PEND)
768*da917039SDavid du Colombier panic("allocb(%d) called from %#p",
769*da917039SDavid du Colombier size, getcallerpc(&size));
770*da917039SDavid du Colombier bp = ialloc(sizeof(Block)+size+64, 0);
771*da917039SDavid du Colombier addr = (ulong)bp;
772*da917039SDavid du Colombier addr = ROUNDUP(addr + sizeof(Block), 8);
773*da917039SDavid du Colombier bp->base = (uchar*)addr;
774*da917039SDavid du Colombier bp->lim = ((uchar*)bp) + sizeof(Block)+size+64;
775*da917039SDavid du Colombier }
776*da917039SDavid du Colombier
777*da917039SDavid du Colombier if(bp->flag)
778*da917039SDavid du Colombier panic("allocb reuse");
779*da917039SDavid du Colombier
780*da917039SDavid du Colombier bp->rp = bp->base;
781*da917039SDavid du Colombier bp->wp = bp->rp;
782*da917039SDavid du Colombier bp->next = 0;
783*da917039SDavid du Colombier bp->flag = 1;
784*da917039SDavid du Colombier
785*da917039SDavid du Colombier return bp;
786*da917039SDavid du Colombier }
787*da917039SDavid du Colombier
788*da917039SDavid du Colombier void
freeb(Block * bp)789*da917039SDavid du Colombier freeb(Block* bp)
790*da917039SDavid du Colombier {
791*da917039SDavid du Colombier bp->next = allocbp;
792*da917039SDavid du Colombier allocbp = bp;
793*da917039SDavid du Colombier
794*da917039SDavid du Colombier bp->flag = 0;
795*da917039SDavid du Colombier }
796*da917039SDavid du Colombier
797*da917039SDavid du Colombier void (*etherdetach)(void);
798*da917039SDavid du Colombier
799*da917039SDavid du Colombier void
warp9(ulong entry)800*da917039SDavid du Colombier warp9(ulong entry)
801*da917039SDavid du Colombier {
802*da917039SDavid du Colombier ulong inst;
803*da917039SDavid du Colombier ulong *mem;
804*da917039SDavid du Colombier
805*da917039SDavid du Colombier if(etherdetach)
806*da917039SDavid du Colombier etherdetach();
807*da917039SDavid du Colombier // consdrain();
808*da917039SDavid du Colombier delay(10);
809*da917039SDavid du Colombier
810*da917039SDavid du Colombier splhi();
811*da917039SDavid du Colombier trapdisable();
812*da917039SDavid du Colombier coherence();
813*da917039SDavid du Colombier syncall();
814*da917039SDavid du Colombier
815*da917039SDavid du Colombier qtmerrtest("syncs before kernel entry");
816*da917039SDavid du Colombier syncall();
817*da917039SDavid du Colombier putmsr(getmsr() & ~MSR_ME); /* disable machine check traps */
818*da917039SDavid du Colombier syncall();
819*da917039SDavid du Colombier clrmchk();
820*da917039SDavid du Colombier syncall();
821*da917039SDavid du Colombier
822*da917039SDavid du Colombier mem = (ulong *)PADDR(entry);
823*da917039SDavid du Colombier inst = *mem;
824*da917039SDavid du Colombier if (inst == 0)
825*da917039SDavid du Colombier panic("word at entry addr is zero, kernel not loaded");
826*da917039SDavid du Colombier /*
827*da917039SDavid du Colombier * This is where to push things on the stack to
828*da917039SDavid du Colombier * boot *BSD systems, e.g.
829*da917039SDavid du Colombier * (*((void (*)(void*, void*, void*, void*, ulong, ulong))PADDR(entry)))
830*da917039SDavid du Colombier * (0, 0, 0, 0, 8196, 640);
831*da917039SDavid du Colombier * will enable NetBSD boot (the real memory size needs to
832*da917039SDavid du Colombier * go in the 5th argument).
833*da917039SDavid du Colombier */
834*da917039SDavid du Colombier coherence();
835*da917039SDavid du Colombier syncall();
836*da917039SDavid du Colombier (*(void (*)(void))mem)();
837*da917039SDavid du Colombier
838*da917039SDavid du Colombier for (;;)
839*da917039SDavid du Colombier ;
840*da917039SDavid du Colombier }
841