xref: /inferno-os/os/boot/pc/load.c (revision 8a8c2d742b51525f66c2210e3c8a251de10022ff)
174a4d8c2SCharles.Forsyth #include "u.h"
274a4d8c2SCharles.Forsyth #include "lib.h"
374a4d8c2SCharles.Forsyth #include "mem.h"
474a4d8c2SCharles.Forsyth #include "dat.h"
574a4d8c2SCharles.Forsyth #include "fns.h"
674a4d8c2SCharles.Forsyth #include "io.h"
7*8a8c2d74SCharles.Forsyth #include "sd.h"
874a4d8c2SCharles.Forsyth #include "fs.h"
974a4d8c2SCharles.Forsyth 
10*8a8c2d74SCharles.Forsyth #ifndef VERBOSE
11*8a8c2d74SCharles.Forsyth #define VERBOSE 0
12*8a8c2d74SCharles.Forsyth #endif
13*8a8c2d74SCharles.Forsyth 
14*8a8c2d74SCharles.Forsyth /*
15*8a8c2d74SCharles.Forsyth  * "cache" must be in this list so that 9load will pass the definition of
16*8a8c2d74SCharles.Forsyth  * the cache partition into the kernel so that the disk named by the `cfs'
17*8a8c2d74SCharles.Forsyth  * variable in plan9.ini can be seen in all circumstances before termrc
18*8a8c2d74SCharles.Forsyth  * sets up all the disk partitions.  In particular, if it's on an odd-ball
19*8a8c2d74SCharles.Forsyth  * disk like sd10 rather than sdC0, this is needed.
20*8a8c2d74SCharles.Forsyth  */
21*8a8c2d74SCharles.Forsyth static char *diskparts[] = {
22*8a8c2d74SCharles.Forsyth 	"dos", "9fat", "fs", "data", "cdboot", "cache", 0
23*8a8c2d74SCharles.Forsyth };
2474a4d8c2SCharles.Forsyth static char *etherparts[] = { "*", 0 };
2574a4d8c2SCharles.Forsyth 
2674a4d8c2SCharles.Forsyth static char *diskinis[] = {
2774a4d8c2SCharles.Forsyth 	"plan9/plan9.ini",
2874a4d8c2SCharles.Forsyth 	"plan9.ini",
2974a4d8c2SCharles.Forsyth 	0
3074a4d8c2SCharles.Forsyth };
3174a4d8c2SCharles.Forsyth static char *etherinis[] = {
3274a4d8c2SCharles.Forsyth 	"/cfg/pxe/%E",
3374a4d8c2SCharles.Forsyth 	0
3474a4d8c2SCharles.Forsyth };
3574a4d8c2SCharles.Forsyth 
36*8a8c2d74SCharles.Forsyth /* ordering: devbios must be called before devsd calls sdbios */
3774a4d8c2SCharles.Forsyth Type types[] = {
3874a4d8c2SCharles.Forsyth 	{	Tfloppy,
3974a4d8c2SCharles.Forsyth 		Fini|Ffs,
4074a4d8c2SCharles.Forsyth 		floppyinit, floppyinitdev,
4174a4d8c2SCharles.Forsyth 		floppygetfspart, 0, floppyboot,
4274a4d8c2SCharles.Forsyth 		floppyprintdevs,
4374a4d8c2SCharles.Forsyth 		diskparts,
4474a4d8c2SCharles.Forsyth 		diskinis,
4574a4d8c2SCharles.Forsyth 	},
4674a4d8c2SCharles.Forsyth 	{	Tether,
4774a4d8c2SCharles.Forsyth 		Fini|Fbootp,
4874a4d8c2SCharles.Forsyth 		etherinit, etherinitdev,
4974a4d8c2SCharles.Forsyth 		pxegetfspart, 0, bootpboot,
5074a4d8c2SCharles.Forsyth 		etherprintdevs,
5174a4d8c2SCharles.Forsyth 		etherparts,
5274a4d8c2SCharles.Forsyth 		etherinis,
5374a4d8c2SCharles.Forsyth 	},
54*8a8c2d74SCharles.Forsyth 	{	Tbios,
55*8a8c2d74SCharles.Forsyth 		Fini|Ffs,
56*8a8c2d74SCharles.Forsyth 		biosinit, biosinitdev,
57*8a8c2d74SCharles.Forsyth 		biosgetfspart, nil, biosboot,
58*8a8c2d74SCharles.Forsyth 		biosprintdevs,
59*8a8c2d74SCharles.Forsyth 		diskparts,
60*8a8c2d74SCharles.Forsyth 		diskinis,
61*8a8c2d74SCharles.Forsyth 	},
62*8a8c2d74SCharles.Forsyth 	{	Tcd,
63*8a8c2d74SCharles.Forsyth 		Fini|Ffs,
64*8a8c2d74SCharles.Forsyth 		cdinit, sdinitdev,
65*8a8c2d74SCharles.Forsyth 		sdgetfspart, sdaddconf, sdboot,
66*8a8c2d74SCharles.Forsyth 		sdprintdevs,
67*8a8c2d74SCharles.Forsyth 		diskparts,
68*8a8c2d74SCharles.Forsyth 		diskinis,
69*8a8c2d74SCharles.Forsyth 	},
7074a4d8c2SCharles.Forsyth 	{	Tsd,
7174a4d8c2SCharles.Forsyth 		Fini|Ffs,
7274a4d8c2SCharles.Forsyth 		sdinit, sdinitdev,
7374a4d8c2SCharles.Forsyth 		sdgetfspart, sdaddconf, sdboot,
7474a4d8c2SCharles.Forsyth 		sdprintdevs,
7574a4d8c2SCharles.Forsyth 		diskparts,
7674a4d8c2SCharles.Forsyth 		diskinis,
7774a4d8c2SCharles.Forsyth 	},
7874a4d8c2SCharles.Forsyth 	{	Tnil,
7974a4d8c2SCharles.Forsyth 		0,
8074a4d8c2SCharles.Forsyth 		nil, nil, nil, nil, nil, nil,
8174a4d8c2SCharles.Forsyth 		nil,
8274a4d8c2SCharles.Forsyth 		nil,
8374a4d8c2SCharles.Forsyth 		0,
8474a4d8c2SCharles.Forsyth 		nil,
8574a4d8c2SCharles.Forsyth 	},
8674a4d8c2SCharles.Forsyth };
8774a4d8c2SCharles.Forsyth 
88*8a8c2d74SCharles.Forsyth static char *typenm[] = {
89*8a8c2d74SCharles.Forsyth 	[Tnil]		"nil",
90*8a8c2d74SCharles.Forsyth 	[Tfloppy]	"floppy",
91*8a8c2d74SCharles.Forsyth 	[Tsd]		"sd",
92*8a8c2d74SCharles.Forsyth 	[Tether]	"ether",
93*8a8c2d74SCharles.Forsyth 	[Tcd]		"cd",
94*8a8c2d74SCharles.Forsyth 	[Tbios]		"bios",
95*8a8c2d74SCharles.Forsyth };
96*8a8c2d74SCharles.Forsyth 
97*8a8c2d74SCharles.Forsyth static char *
typename(int type)98*8a8c2d74SCharles.Forsyth typename(int type)
99*8a8c2d74SCharles.Forsyth {
100*8a8c2d74SCharles.Forsyth 	if (type < 0 || type >= nelem(typenm) || typenm[type] == nil)
101*8a8c2d74SCharles.Forsyth 		return "**gok**";
102*8a8c2d74SCharles.Forsyth 	return typenm[type];
103*8a8c2d74SCharles.Forsyth }
10474a4d8c2SCharles.Forsyth 
10574a4d8c2SCharles.Forsyth extern SDifc sdataifc;
106*8a8c2d74SCharles.Forsyth extern SDifc sdiahciifc;
107*8a8c2d74SCharles.Forsyth extern SDifc sdaoeifc;
108*8a8c2d74SCharles.Forsyth extern SDifc sdbiosifc;
10974a4d8c2SCharles.Forsyth 
11074a4d8c2SCharles.Forsyth #ifdef NOSCSI
11174a4d8c2SCharles.Forsyth 
11274a4d8c2SCharles.Forsyth SDifc* sdifc[] = {
11374a4d8c2SCharles.Forsyth 	&sdataifc,
114*8a8c2d74SCharles.Forsyth 	&sdiahciifc,
115*8a8c2d74SCharles.Forsyth 	&sdbiosifc,
116*8a8c2d74SCharles.Forsyth 	&sdaoeifc,
11774a4d8c2SCharles.Forsyth 	nil,
11874a4d8c2SCharles.Forsyth };
11974a4d8c2SCharles.Forsyth 
12074a4d8c2SCharles.Forsyth #else
12174a4d8c2SCharles.Forsyth 
12274a4d8c2SCharles.Forsyth extern SDifc sdmylexifc;
12374a4d8c2SCharles.Forsyth extern SDifc sd53c8xxifc;
124*8a8c2d74SCharles.Forsyth 
12574a4d8c2SCharles.Forsyth SDifc* sdifc[] = {
12674a4d8c2SCharles.Forsyth 	&sdataifc,
127*8a8c2d74SCharles.Forsyth 	&sdiahciifc,
12874a4d8c2SCharles.Forsyth 	&sdmylexifc,
12974a4d8c2SCharles.Forsyth 	&sd53c8xxifc,
130*8a8c2d74SCharles.Forsyth 	&sdbiosifc,
131*8a8c2d74SCharles.Forsyth 	&sdaoeifc,
13274a4d8c2SCharles.Forsyth 	nil,
13374a4d8c2SCharles.Forsyth };
13474a4d8c2SCharles.Forsyth 
13574a4d8c2SCharles.Forsyth #endif NOSCSI
13674a4d8c2SCharles.Forsyth 
13774a4d8c2SCharles.Forsyth typedef struct Mode Mode;
13874a4d8c2SCharles.Forsyth 
13974a4d8c2SCharles.Forsyth enum {
14074a4d8c2SCharles.Forsyth 	Maxdev		= 7,
14174a4d8c2SCharles.Forsyth 	Dany		= -1,
14274a4d8c2SCharles.Forsyth 	Nmedia		= 16,
14374a4d8c2SCharles.Forsyth 	Nini		= 10,
14474a4d8c2SCharles.Forsyth };
14574a4d8c2SCharles.Forsyth 
14674a4d8c2SCharles.Forsyth enum {					/* mode */
14774a4d8c2SCharles.Forsyth 	Mauto		= 0x00,
14874a4d8c2SCharles.Forsyth 	Mlocal		= 0x01,
14974a4d8c2SCharles.Forsyth 	Manual		= 0x02,
15074a4d8c2SCharles.Forsyth 	NMode		= 0x03,
15174a4d8c2SCharles.Forsyth };
15274a4d8c2SCharles.Forsyth 
15374a4d8c2SCharles.Forsyth typedef struct Medium Medium;
15474a4d8c2SCharles.Forsyth struct Medium {
15574a4d8c2SCharles.Forsyth 	Type*	type;
15674a4d8c2SCharles.Forsyth 	int	flag;
15774a4d8c2SCharles.Forsyth 	int	dev;
15874a4d8c2SCharles.Forsyth 	char name[NAMELEN];
15974a4d8c2SCharles.Forsyth 
16074a4d8c2SCharles.Forsyth 	Fs *inifs;
16174a4d8c2SCharles.Forsyth 	char *part;
16274a4d8c2SCharles.Forsyth 	char *ini;
16374a4d8c2SCharles.Forsyth 
16474a4d8c2SCharles.Forsyth 	Medium*	next;
16574a4d8c2SCharles.Forsyth };
16674a4d8c2SCharles.Forsyth 
16774a4d8c2SCharles.Forsyth typedef struct Mode {
16874a4d8c2SCharles.Forsyth 	char*	name;
16974a4d8c2SCharles.Forsyth 	int	mode;
17074a4d8c2SCharles.Forsyth } Mode;
17174a4d8c2SCharles.Forsyth 
17274a4d8c2SCharles.Forsyth static Medium media[Nmedia];
17374a4d8c2SCharles.Forsyth static Medium *curmedium = media;
17474a4d8c2SCharles.Forsyth 
17574a4d8c2SCharles.Forsyth static Mode modes[NMode+1] = {
17674a4d8c2SCharles.Forsyth 	[Mauto]		{ "auto",   Mauto,  },
17774a4d8c2SCharles.Forsyth 	[Mlocal]	{ "local",  Mlocal, },
17874a4d8c2SCharles.Forsyth 	[Manual]	{ "manual", Manual, },
17974a4d8c2SCharles.Forsyth };
18074a4d8c2SCharles.Forsyth 
18174a4d8c2SCharles.Forsyth char **ini;
18274a4d8c2SCharles.Forsyth 
18374a4d8c2SCharles.Forsyth int scsi0port;
18474a4d8c2SCharles.Forsyth char *defaultpartition;
18574a4d8c2SCharles.Forsyth int iniread;
18674a4d8c2SCharles.Forsyth 
187*8a8c2d74SCharles.Forsyth int debugload;
188*8a8c2d74SCharles.Forsyth 
18974a4d8c2SCharles.Forsyth static Medium*
parse(char * line,char ** file)19074a4d8c2SCharles.Forsyth parse(char *line, char **file)
19174a4d8c2SCharles.Forsyth {
19274a4d8c2SCharles.Forsyth 	char *p;
19374a4d8c2SCharles.Forsyth 	Type *tp;
19474a4d8c2SCharles.Forsyth 	Medium *mp;
19574a4d8c2SCharles.Forsyth 
19674a4d8c2SCharles.Forsyth 	if(p = strchr(line, '!')) {
19774a4d8c2SCharles.Forsyth 		*p++ = 0;
19874a4d8c2SCharles.Forsyth 		*file = p;
19974a4d8c2SCharles.Forsyth 	} else
20074a4d8c2SCharles.Forsyth 		*file = "";
20174a4d8c2SCharles.Forsyth 
20274a4d8c2SCharles.Forsyth 	for(tp = types; tp->type != Tnil; tp++)
20374a4d8c2SCharles.Forsyth 		for(mp = tp->media; mp; mp = mp->next)
20474a4d8c2SCharles.Forsyth 			if(strcmp(mp->name, line) == 0)
20574a4d8c2SCharles.Forsyth 				return mp;
20674a4d8c2SCharles.Forsyth 	if(p)
20774a4d8c2SCharles.Forsyth 		*--p = '!';
20874a4d8c2SCharles.Forsyth 	return nil;
20974a4d8c2SCharles.Forsyth }
21074a4d8c2SCharles.Forsyth 
21174a4d8c2SCharles.Forsyth static int
boot(Medium * mp,char * file)21274a4d8c2SCharles.Forsyth boot(Medium *mp, char *file)
21374a4d8c2SCharles.Forsyth {
21474a4d8c2SCharles.Forsyth 	Type *tp;
21574a4d8c2SCharles.Forsyth 	Medium *xmp;
21674a4d8c2SCharles.Forsyth 	static int didaddconf;
21774a4d8c2SCharles.Forsyth 	Boot b;
21874a4d8c2SCharles.Forsyth 
21974a4d8c2SCharles.Forsyth 	memset(&b, 0, sizeof b);
22074a4d8c2SCharles.Forsyth 	b.state = INITKERNEL;
22174a4d8c2SCharles.Forsyth 
22274a4d8c2SCharles.Forsyth 	if(didaddconf == 0) {
22374a4d8c2SCharles.Forsyth 		didaddconf = 1;
22474a4d8c2SCharles.Forsyth 		for(tp = types; tp->type != Tnil; tp++)
22574a4d8c2SCharles.Forsyth 			if(tp->addconf)
22674a4d8c2SCharles.Forsyth 				for(xmp = tp->media; xmp; xmp = xmp->next)
22774a4d8c2SCharles.Forsyth 					(*tp->addconf)(xmp->dev);
22874a4d8c2SCharles.Forsyth 	}
22974a4d8c2SCharles.Forsyth 
23074a4d8c2SCharles.Forsyth 	sprint(BOOTLINE, "%s!%s", mp->name, file);
231*8a8c2d74SCharles.Forsyth 	print("booting %s!%s\n", mp->name, file);
23274a4d8c2SCharles.Forsyth 	return (*mp->type->boot)(mp->dev, file, &b);
23374a4d8c2SCharles.Forsyth }
23474a4d8c2SCharles.Forsyth 
23574a4d8c2SCharles.Forsyth static Medium*
allocm(Type * tp)23674a4d8c2SCharles.Forsyth allocm(Type *tp)
23774a4d8c2SCharles.Forsyth {
23874a4d8c2SCharles.Forsyth 	Medium **l;
23974a4d8c2SCharles.Forsyth 
24074a4d8c2SCharles.Forsyth 	if(curmedium >= &media[Nmedia])
24174a4d8c2SCharles.Forsyth 		return 0;
24274a4d8c2SCharles.Forsyth 
24374a4d8c2SCharles.Forsyth 	for(l = &tp->media; *l; l = &(*l)->next)
24474a4d8c2SCharles.Forsyth 		;
24574a4d8c2SCharles.Forsyth 	*l = curmedium++;
24674a4d8c2SCharles.Forsyth 	return *l;
24774a4d8c2SCharles.Forsyth }
24874a4d8c2SCharles.Forsyth 
24974a4d8c2SCharles.Forsyth Medium*
probe(int type,int flag,int dev)25074a4d8c2SCharles.Forsyth probe(int type, int flag, int dev)
25174a4d8c2SCharles.Forsyth {
25274a4d8c2SCharles.Forsyth 	Type *tp;
25374a4d8c2SCharles.Forsyth 	int i;
25474a4d8c2SCharles.Forsyth 	Medium *mp;
25574a4d8c2SCharles.Forsyth 	File f;
25674a4d8c2SCharles.Forsyth 	Fs *fs;
25774a4d8c2SCharles.Forsyth 	char **partp;
25874a4d8c2SCharles.Forsyth 
25974a4d8c2SCharles.Forsyth 	for(tp = types; tp->type != Tnil; tp++){
26074a4d8c2SCharles.Forsyth 		if(type != Tany && type != tp->type)
26174a4d8c2SCharles.Forsyth 			continue;
26274a4d8c2SCharles.Forsyth 
26374a4d8c2SCharles.Forsyth 		if(flag != Fnone){
26474a4d8c2SCharles.Forsyth 			for(mp = tp->media; mp; mp = mp->next){
26574a4d8c2SCharles.Forsyth 				if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
26674a4d8c2SCharles.Forsyth 					return mp;
26774a4d8c2SCharles.Forsyth 			}
26874a4d8c2SCharles.Forsyth 		}
269*8a8c2d74SCharles.Forsyth 		if (debugload)
270*8a8c2d74SCharles.Forsyth 			print("probing %s...", typename(tp->type));
27174a4d8c2SCharles.Forsyth 		if((tp->flag & Fprobe) == 0){
27274a4d8c2SCharles.Forsyth 			tp->flag |= Fprobe;
27374a4d8c2SCharles.Forsyth 			tp->mask = (*tp->init)();
27474a4d8c2SCharles.Forsyth 		}
27574a4d8c2SCharles.Forsyth 
27674a4d8c2SCharles.Forsyth 		for(i = 0; tp->mask; i++){
27774a4d8c2SCharles.Forsyth 			if((tp->mask & (1<<i)) == 0)
27874a4d8c2SCharles.Forsyth 				continue;
27974a4d8c2SCharles.Forsyth 			tp->mask &= ~(1<<i);
28074a4d8c2SCharles.Forsyth 
28174a4d8c2SCharles.Forsyth 			if((mp = allocm(tp)) == 0)
28274a4d8c2SCharles.Forsyth 				continue;
28374a4d8c2SCharles.Forsyth 
28474a4d8c2SCharles.Forsyth 			mp->dev = i;
28574a4d8c2SCharles.Forsyth 			mp->flag = tp->flag;
28674a4d8c2SCharles.Forsyth 			mp->type = tp;
28774a4d8c2SCharles.Forsyth 			(*tp->initdev)(i, mp->name);
28874a4d8c2SCharles.Forsyth 
28974a4d8c2SCharles.Forsyth 			if(mp->flag & Fini){
29074a4d8c2SCharles.Forsyth 				mp->flag &= ~Fini;
29174a4d8c2SCharles.Forsyth 				for(partp = tp->parts; *partp; partp++){
29274a4d8c2SCharles.Forsyth 					if((fs = (*tp->getfspart)(i, *partp, 0)) == nil)
29374a4d8c2SCharles.Forsyth 						continue;
29474a4d8c2SCharles.Forsyth 
29574a4d8c2SCharles.Forsyth 					for(ini = tp->inis; *ini; ini++){
29674a4d8c2SCharles.Forsyth 						if(fswalk(fs, *ini, &f) > 0){
29774a4d8c2SCharles.Forsyth 							mp->inifs = fs;
29874a4d8c2SCharles.Forsyth 							mp->part = *partp;
29974a4d8c2SCharles.Forsyth 							mp->ini = f.path;
30074a4d8c2SCharles.Forsyth 							mp->flag |= Fini;
30174a4d8c2SCharles.Forsyth 							goto Break2;
30274a4d8c2SCharles.Forsyth 						}
30374a4d8c2SCharles.Forsyth 					}
30474a4d8c2SCharles.Forsyth 				}
30574a4d8c2SCharles.Forsyth 			}
30674a4d8c2SCharles.Forsyth 		Break2:
30774a4d8c2SCharles.Forsyth 			if((flag & mp->flag) && (dev == Dany || dev == i))
30874a4d8c2SCharles.Forsyth 				return mp;
30974a4d8c2SCharles.Forsyth 		}
31074a4d8c2SCharles.Forsyth 	}
31174a4d8c2SCharles.Forsyth 
31274a4d8c2SCharles.Forsyth 	return 0;
31374a4d8c2SCharles.Forsyth }
31474a4d8c2SCharles.Forsyth 
31574a4d8c2SCharles.Forsyth void
main(void)31674a4d8c2SCharles.Forsyth main(void)
31774a4d8c2SCharles.Forsyth {
31874a4d8c2SCharles.Forsyth 	Medium *mp;
31974a4d8c2SCharles.Forsyth 	int flag, i, mode, tried;
32074a4d8c2SCharles.Forsyth 	char def[2*NAMELEN], line[80], *p, *file;
32174a4d8c2SCharles.Forsyth 	Type *tp;
32274a4d8c2SCharles.Forsyth 
32374a4d8c2SCharles.Forsyth 	i8042a20();
32474a4d8c2SCharles.Forsyth 	memset(m, 0, sizeof(Mach));
32574a4d8c2SCharles.Forsyth 	trapinit();
32674a4d8c2SCharles.Forsyth 	clockinit();
32774a4d8c2SCharles.Forsyth 	alarminit();
32874a4d8c2SCharles.Forsyth 	meminit(0);
32974a4d8c2SCharles.Forsyth 	spllo();
330*8a8c2d74SCharles.Forsyth 	consinit("0", "9600");
33174a4d8c2SCharles.Forsyth 	kbdinit();
33274a4d8c2SCharles.Forsyth 	if((ulong)&end > (KZERO|(640*1024)))
33374a4d8c2SCharles.Forsyth 		panic("i'm too big\n");
33474a4d8c2SCharles.Forsyth 
33574a4d8c2SCharles.Forsyth 	readlsconf();
336*8a8c2d74SCharles.Forsyth 	print("initial probe, to find plan9.ini...");
337*8a8c2d74SCharles.Forsyth 	/* find and read plan9.ini, setting configuration variables */
33874a4d8c2SCharles.Forsyth 	for(tp = types; tp->type != Tnil; tp++){
339*8a8c2d74SCharles.Forsyth 		/* skip bios until we have read plan9.ini */
340*8a8c2d74SCharles.Forsyth 		if(!pxe && tp->type == Tether || tp->type == Tbios)
341*8a8c2d74SCharles.Forsyth 			continue;
342*8a8c2d74SCharles.Forsyth 		if (VERBOSE)
343*8a8c2d74SCharles.Forsyth 			print("probing %s...", typename(tp->type));
34474a4d8c2SCharles.Forsyth 		if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
34574a4d8c2SCharles.Forsyth 			print("using %s!%s!%s\n", mp->name, mp->part, mp->ini);
34674a4d8c2SCharles.Forsyth 			iniread = !dotini(mp->inifs);
34774a4d8c2SCharles.Forsyth 			break;
34874a4d8c2SCharles.Forsyth 		}
34974a4d8c2SCharles.Forsyth 	}
350*8a8c2d74SCharles.Forsyth 	print("\n");
35174a4d8c2SCharles.Forsyth 	apminit();
35274a4d8c2SCharles.Forsyth 
353*8a8c2d74SCharles.Forsyth 	debugload = getconf("*debugload") != nil;
35474a4d8c2SCharles.Forsyth 	if((p = getconf("console")) != nil)
35574a4d8c2SCharles.Forsyth 		consinit(p, getconf("baud"));
356*8a8c2d74SCharles.Forsyth 
35774a4d8c2SCharles.Forsyth 	devpccardlink();
35874a4d8c2SCharles.Forsyth 	devi82365link();
35974a4d8c2SCharles.Forsyth 
36074a4d8c2SCharles.Forsyth 	/*
36174a4d8c2SCharles.Forsyth  	 * Even after we find the ini file, we keep probing disks,
36274a4d8c2SCharles.Forsyth 	 * because we have to collect the partition tables and
36374a4d8c2SCharles.Forsyth 	 * have boot devices for parse.
36474a4d8c2SCharles.Forsyth 	 */
36574a4d8c2SCharles.Forsyth 	probe(Tany, Fnone, Dany);
366*8a8c2d74SCharles.Forsyth 	if (debugload)
367*8a8c2d74SCharles.Forsyth 		print("end disk probe\n");
36874a4d8c2SCharles.Forsyth 	tried = 0;
36974a4d8c2SCharles.Forsyth 	mode = Mauto;
37074a4d8c2SCharles.Forsyth 
37174a4d8c2SCharles.Forsyth 	p = getconf("bootfile");
37274a4d8c2SCharles.Forsyth 
37374a4d8c2SCharles.Forsyth 	if(p != 0) {
37474a4d8c2SCharles.Forsyth 		mode = Manual;
37574a4d8c2SCharles.Forsyth 		for(i = 0; i < NMode; i++){
37674a4d8c2SCharles.Forsyth 			if(strcmp(p, modes[i].name) == 0){
37774a4d8c2SCharles.Forsyth 				mode = modes[i].mode;
37874a4d8c2SCharles.Forsyth 				goto done;
37974a4d8c2SCharles.Forsyth 			}
38074a4d8c2SCharles.Forsyth 		}
38174a4d8c2SCharles.Forsyth 		if((mp = parse(p, &file)) == nil) {
38274a4d8c2SCharles.Forsyth 			print("Unknown boot device: %s\n", p);
38374a4d8c2SCharles.Forsyth 			goto done;
38474a4d8c2SCharles.Forsyth 		}
38574a4d8c2SCharles.Forsyth 		tried = boot(mp, file);
38674a4d8c2SCharles.Forsyth 	}
38774a4d8c2SCharles.Forsyth done:
38874a4d8c2SCharles.Forsyth 	if(tried == 0 && mode != Manual){
38974a4d8c2SCharles.Forsyth 		flag = Fany;
39074a4d8c2SCharles.Forsyth 		if(mode == Mlocal)
39174a4d8c2SCharles.Forsyth 			flag &= ~Fbootp;
39274a4d8c2SCharles.Forsyth 		if((mp = probe(Tany, flag, Dany)) && mp->type->type != Tfloppy)
39374a4d8c2SCharles.Forsyth 			boot(mp, "");
394*8a8c2d74SCharles.Forsyth 		if (debugload)
395*8a8c2d74SCharles.Forsyth 			print("end auto probe\n");
39674a4d8c2SCharles.Forsyth 	}
39774a4d8c2SCharles.Forsyth 
39874a4d8c2SCharles.Forsyth 	def[0] = 0;
39974a4d8c2SCharles.Forsyth 	probe(Tany, Fnone, Dany);
400*8a8c2d74SCharles.Forsyth 	if (debugload)
401*8a8c2d74SCharles.Forsyth 		print("end final probe\n");
40274a4d8c2SCharles.Forsyth 	if(p = getconf("bootdef"))
40374a4d8c2SCharles.Forsyth 		strcpy(def, p);
40474a4d8c2SCharles.Forsyth 
40574a4d8c2SCharles.Forsyth 	flag = 0;
40674a4d8c2SCharles.Forsyth 	for(tp = types; tp->type != Tnil; tp++){
40774a4d8c2SCharles.Forsyth 		for(mp = tp->media; mp; mp = mp->next){
40874a4d8c2SCharles.Forsyth 			if(flag == 0){
40974a4d8c2SCharles.Forsyth 				flag = 1;
41074a4d8c2SCharles.Forsyth 				print("Boot devices:");
41174a4d8c2SCharles.Forsyth 			}
41274a4d8c2SCharles.Forsyth 			(*tp->printdevs)(mp->dev);
41374a4d8c2SCharles.Forsyth 		}
41474a4d8c2SCharles.Forsyth 	}
41574a4d8c2SCharles.Forsyth 	if(flag)
41674a4d8c2SCharles.Forsyth 		print("\n");
41774a4d8c2SCharles.Forsyth 
41874a4d8c2SCharles.Forsyth 	for(;;){
41974a4d8c2SCharles.Forsyth 		if(getstr("boot from", line, sizeof(line), def, (mode != Manual)*15) >= 0)
42074a4d8c2SCharles.Forsyth 			if(mp = parse(line, &file))
42174a4d8c2SCharles.Forsyth 				boot(mp, file);
42274a4d8c2SCharles.Forsyth 		def[0] = 0;
42374a4d8c2SCharles.Forsyth 	}
42474a4d8c2SCharles.Forsyth }
42574a4d8c2SCharles.Forsyth 
42674a4d8c2SCharles.Forsyth int
getfields(char * lp,char ** fields,int n,char sep)42774a4d8c2SCharles.Forsyth getfields(char *lp, char **fields, int n, char sep)
42874a4d8c2SCharles.Forsyth {
42974a4d8c2SCharles.Forsyth 	int i;
43074a4d8c2SCharles.Forsyth 
43174a4d8c2SCharles.Forsyth 	for(i = 0; lp && *lp && i < n; i++){
43274a4d8c2SCharles.Forsyth 		while(*lp == sep)
43374a4d8c2SCharles.Forsyth 			*lp++ = 0;
43474a4d8c2SCharles.Forsyth 		if(*lp == 0)
43574a4d8c2SCharles.Forsyth 			break;
43674a4d8c2SCharles.Forsyth 		fields[i] = lp;
43774a4d8c2SCharles.Forsyth 		while(*lp && *lp != sep){
43874a4d8c2SCharles.Forsyth 			if(*lp == '\\' && *(lp+1) == '\n')
43974a4d8c2SCharles.Forsyth 				*lp++ = ' ';
44074a4d8c2SCharles.Forsyth 			lp++;
44174a4d8c2SCharles.Forsyth 		}
44274a4d8c2SCharles.Forsyth 	}
44374a4d8c2SCharles.Forsyth 	return i;
44474a4d8c2SCharles.Forsyth }
44574a4d8c2SCharles.Forsyth 
44674a4d8c2SCharles.Forsyth int
cistrcmp(char * a,char * b)44774a4d8c2SCharles.Forsyth cistrcmp(char *a, char *b)
44874a4d8c2SCharles.Forsyth {
44974a4d8c2SCharles.Forsyth 	int ac, bc;
45074a4d8c2SCharles.Forsyth 
45174a4d8c2SCharles.Forsyth 	for(;;){
45274a4d8c2SCharles.Forsyth 		ac = *a++;
45374a4d8c2SCharles.Forsyth 		bc = *b++;
45474a4d8c2SCharles.Forsyth 
45574a4d8c2SCharles.Forsyth 		if(ac >= 'A' && ac <= 'Z')
45674a4d8c2SCharles.Forsyth 			ac = 'a' + (ac - 'A');
45774a4d8c2SCharles.Forsyth 		if(bc >= 'A' && bc <= 'Z')
45874a4d8c2SCharles.Forsyth 			bc = 'a' + (bc - 'A');
45974a4d8c2SCharles.Forsyth 		ac -= bc;
46074a4d8c2SCharles.Forsyth 		if(ac)
46174a4d8c2SCharles.Forsyth 			return ac;
46274a4d8c2SCharles.Forsyth 		if(bc == 0)
46374a4d8c2SCharles.Forsyth 			break;
46474a4d8c2SCharles.Forsyth 	}
46574a4d8c2SCharles.Forsyth 	return 0;
46674a4d8c2SCharles.Forsyth }
46774a4d8c2SCharles.Forsyth 
46874a4d8c2SCharles.Forsyth int
cistrncmp(char * a,char * b,int n)46974a4d8c2SCharles.Forsyth cistrncmp(char *a, char *b, int n)
47074a4d8c2SCharles.Forsyth {
47174a4d8c2SCharles.Forsyth 	unsigned ac, bc;
47274a4d8c2SCharles.Forsyth 
47374a4d8c2SCharles.Forsyth 	while(n > 0){
47474a4d8c2SCharles.Forsyth 		ac = *a++;
47574a4d8c2SCharles.Forsyth 		bc = *b++;
47674a4d8c2SCharles.Forsyth 		n--;
47774a4d8c2SCharles.Forsyth 
47874a4d8c2SCharles.Forsyth 		if(ac >= 'A' && ac <= 'Z')
47974a4d8c2SCharles.Forsyth 			ac = 'a' + (ac - 'A');
48074a4d8c2SCharles.Forsyth 		if(bc >= 'A' && bc <= 'Z')
48174a4d8c2SCharles.Forsyth 			bc = 'a' + (bc - 'A');
48274a4d8c2SCharles.Forsyth 
48374a4d8c2SCharles.Forsyth 		ac -= bc;
48474a4d8c2SCharles.Forsyth 		if(ac)
48574a4d8c2SCharles.Forsyth 			return ac;
48674a4d8c2SCharles.Forsyth 		if(bc == 0)
48774a4d8c2SCharles.Forsyth 			break;
48874a4d8c2SCharles.Forsyth 	}
48974a4d8c2SCharles.Forsyth 
49074a4d8c2SCharles.Forsyth 	return 0;
49174a4d8c2SCharles.Forsyth }
49274a4d8c2SCharles.Forsyth 
493*8a8c2d74SCharles.Forsyth #define PSTART		( 8*1024*1024)
49474a4d8c2SCharles.Forsyth #define PEND		(16*1024*1024)
49574a4d8c2SCharles.Forsyth 
49674a4d8c2SCharles.Forsyth ulong palloc = PSTART;
49774a4d8c2SCharles.Forsyth 
49874a4d8c2SCharles.Forsyth void*
ialloc(ulong n,int align)49974a4d8c2SCharles.Forsyth ialloc(ulong n, int align)
50074a4d8c2SCharles.Forsyth {
50174a4d8c2SCharles.Forsyth 	ulong p;
50274a4d8c2SCharles.Forsyth 	int a;
50374a4d8c2SCharles.Forsyth 
50474a4d8c2SCharles.Forsyth 	p = palloc;
50574a4d8c2SCharles.Forsyth 	if(align <= 0)
50674a4d8c2SCharles.Forsyth 		align = 4;
50774a4d8c2SCharles.Forsyth 	if(a = n % align)
50874a4d8c2SCharles.Forsyth 		n += align - a;
50974a4d8c2SCharles.Forsyth 	if(a = p % align)
51074a4d8c2SCharles.Forsyth 		p += align - a;
51174a4d8c2SCharles.Forsyth 
51274a4d8c2SCharles.Forsyth 
51374a4d8c2SCharles.Forsyth 	palloc = p+n;
51474a4d8c2SCharles.Forsyth 	if(palloc > PEND)
515*8a8c2d74SCharles.Forsyth 		panic("ialloc(%lud, %d) called from %#p\n",
51674a4d8c2SCharles.Forsyth 			n, align, getcallerpc(&n));
51774a4d8c2SCharles.Forsyth 	return memset((void*)(p|KZERO), 0, n);
51874a4d8c2SCharles.Forsyth }
51974a4d8c2SCharles.Forsyth 
52074a4d8c2SCharles.Forsyth void*
xspanalloc(ulong size,int align,ulong span)52174a4d8c2SCharles.Forsyth xspanalloc(ulong size, int align, ulong span)
52274a4d8c2SCharles.Forsyth {
52374a4d8c2SCharles.Forsyth 	ulong a, v;
52474a4d8c2SCharles.Forsyth 
52574a4d8c2SCharles.Forsyth 	if((palloc + (size+align+span)) > PEND)
526*8a8c2d74SCharles.Forsyth 		panic("xspanalloc(%lud, %d, 0x%lux) called from %#p\n",
52774a4d8c2SCharles.Forsyth 			size, align, span, getcallerpc(&size));
52874a4d8c2SCharles.Forsyth 
52974a4d8c2SCharles.Forsyth 	a = (ulong)ialloc(size+align+span, 0);
53074a4d8c2SCharles.Forsyth 
53174a4d8c2SCharles.Forsyth 	if(span > 2)
53274a4d8c2SCharles.Forsyth 		v = (a + span) & ~(span-1);
53374a4d8c2SCharles.Forsyth 	else
53474a4d8c2SCharles.Forsyth 		v = a;
53574a4d8c2SCharles.Forsyth 
53674a4d8c2SCharles.Forsyth 	if(align > 1)
53774a4d8c2SCharles.Forsyth 		v = (v + align) & ~(align-1);
53874a4d8c2SCharles.Forsyth 
53974a4d8c2SCharles.Forsyth 	return (void*)v;
54074a4d8c2SCharles.Forsyth }
54174a4d8c2SCharles.Forsyth 
54274a4d8c2SCharles.Forsyth static Block *allocbp;
54374a4d8c2SCharles.Forsyth 
54474a4d8c2SCharles.Forsyth Block*
allocb(int size)54574a4d8c2SCharles.Forsyth allocb(int size)
54674a4d8c2SCharles.Forsyth {
54774a4d8c2SCharles.Forsyth 	Block *bp, **lbp;
54874a4d8c2SCharles.Forsyth 	ulong addr;
54974a4d8c2SCharles.Forsyth 
55074a4d8c2SCharles.Forsyth 	lbp = &allocbp;
55174a4d8c2SCharles.Forsyth 	for(bp = *lbp; bp; bp = bp->next){
55274a4d8c2SCharles.Forsyth 		if((bp->lim - bp->base) >= size){
55374a4d8c2SCharles.Forsyth 			*lbp = bp->next;
55474a4d8c2SCharles.Forsyth 			break;
55574a4d8c2SCharles.Forsyth 		}
55674a4d8c2SCharles.Forsyth 		lbp = &bp->next;
55774a4d8c2SCharles.Forsyth 	}
55874a4d8c2SCharles.Forsyth 	if(bp == 0){
55974a4d8c2SCharles.Forsyth 		if((palloc + (sizeof(Block)+size+64)) > PEND)
560*8a8c2d74SCharles.Forsyth 			panic("allocb(%d) called from %#p\n",
56174a4d8c2SCharles.Forsyth 				size, getcallerpc(&size));
56274a4d8c2SCharles.Forsyth 		bp = ialloc(sizeof(Block)+size+64, 0);
56374a4d8c2SCharles.Forsyth 		addr = (ulong)bp;
56474a4d8c2SCharles.Forsyth 		addr = ROUNDUP(addr + sizeof(Block), 8);
56574a4d8c2SCharles.Forsyth 		bp->base = (uchar*)addr;
56674a4d8c2SCharles.Forsyth 		bp->lim = ((uchar*)bp) + sizeof(Block)+size+64;
56774a4d8c2SCharles.Forsyth 	}
56874a4d8c2SCharles.Forsyth 
56974a4d8c2SCharles.Forsyth 	if(bp->flag)
57074a4d8c2SCharles.Forsyth 		panic("allocb reuse\n");
57174a4d8c2SCharles.Forsyth 
57274a4d8c2SCharles.Forsyth 	bp->rp = bp->base;
57374a4d8c2SCharles.Forsyth 	bp->wp = bp->rp;
57474a4d8c2SCharles.Forsyth 	bp->next = 0;
57574a4d8c2SCharles.Forsyth 	bp->flag = 1;
57674a4d8c2SCharles.Forsyth 
57774a4d8c2SCharles.Forsyth 	return bp;
57874a4d8c2SCharles.Forsyth }
57974a4d8c2SCharles.Forsyth 
58074a4d8c2SCharles.Forsyth void
freeb(Block * bp)58174a4d8c2SCharles.Forsyth freeb(Block* bp)
58274a4d8c2SCharles.Forsyth {
58374a4d8c2SCharles.Forsyth 	bp->next = allocbp;
58474a4d8c2SCharles.Forsyth 	allocbp = bp;
58574a4d8c2SCharles.Forsyth 
58674a4d8c2SCharles.Forsyth 	bp->flag = 0;
58774a4d8c2SCharles.Forsyth }
58874a4d8c2SCharles.Forsyth 
58974a4d8c2SCharles.Forsyth enum {
59074a4d8c2SCharles.Forsyth 	Paddr=		0x70,	/* address port */
59174a4d8c2SCharles.Forsyth 	Pdata=		0x71,	/* data port */
59274a4d8c2SCharles.Forsyth };
59374a4d8c2SCharles.Forsyth 
59474a4d8c2SCharles.Forsyth uchar
nvramread(int offset)59574a4d8c2SCharles.Forsyth nvramread(int offset)
59674a4d8c2SCharles.Forsyth {
59774a4d8c2SCharles.Forsyth 	outb(Paddr, offset);
59874a4d8c2SCharles.Forsyth 	return inb(Pdata);
59974a4d8c2SCharles.Forsyth }
60074a4d8c2SCharles.Forsyth 
60174a4d8c2SCharles.Forsyth void (*etherdetach)(void);
60274a4d8c2SCharles.Forsyth void (*floppydetach)(void);
60374a4d8c2SCharles.Forsyth void (*sddetach)(void);
60474a4d8c2SCharles.Forsyth 
60574a4d8c2SCharles.Forsyth void
warp9(ulong entry)60674a4d8c2SCharles.Forsyth warp9(ulong entry)
60774a4d8c2SCharles.Forsyth {
60874a4d8c2SCharles.Forsyth 	if(etherdetach)
60974a4d8c2SCharles.Forsyth 		etherdetach();
61074a4d8c2SCharles.Forsyth 	if(floppydetach)
61174a4d8c2SCharles.Forsyth 		floppydetach();
61274a4d8c2SCharles.Forsyth 	if(sddetach)
61374a4d8c2SCharles.Forsyth 		sddetach();
61474a4d8c2SCharles.Forsyth 	consdrain();
61574a4d8c2SCharles.Forsyth 
61674a4d8c2SCharles.Forsyth 	splhi();
61774a4d8c2SCharles.Forsyth 	trapdisable();
61874a4d8c2SCharles.Forsyth 
61974a4d8c2SCharles.Forsyth 	/*
62074a4d8c2SCharles.Forsyth 	 * This is where to push things on the stack to
62174a4d8c2SCharles.Forsyth 	 * boot *BSD systems, e.g.
62274a4d8c2SCharles.Forsyth 	(*(void(*)(void*, void*, void*, void*, ulong, ulong))(PADDR(entry)))(0, 0, 0, 0, 8196, 640);
62374a4d8c2SCharles.Forsyth 	 * will enable NetBSD boot (the real memory size needs to
62474a4d8c2SCharles.Forsyth 	 * go in the 5th argument).
62574a4d8c2SCharles.Forsyth 	 */
62674a4d8c2SCharles.Forsyth 	(*(void(*)(void))(PADDR(entry)))();
62774a4d8c2SCharles.Forsyth }
628