xref: /plan9/sys/src/9/boot/local.c (revision a2ede17577e07b9f98ba4ee93647f95654b05966)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <../boot/boot.h>
43e12c5d1SDavid du Colombier 
59a747e4fSDavid du Colombier static char diskname[64];
63e12c5d1SDavid du Colombier static char *disk;
780ee5cbfSDavid du Colombier static char **args;
83e12c5d1SDavid du Colombier 
93e12c5d1SDavid du Colombier void
configlocal(Method * mp)103e12c5d1SDavid du Colombier configlocal(Method *mp)
113e12c5d1SDavid du Colombier {
12ae886fecSDavid du Colombier 	char *p, *inibootdisk;
13219b2ee8SDavid du Colombier 	int n;
14219b2ee8SDavid du Colombier 
15ae886fecSDavid du Colombier 	inibootdisk = getenv("bootdisk");
16219b2ee8SDavid du Colombier 	if(*sys == '/' || *sys == '#'){
17219b2ee8SDavid du Colombier 		/*
18219b2ee8SDavid du Colombier 		 *  if the user specifies the disk in the boot cmd or
19219b2ee8SDavid du Colombier 		 * 'root is from' prompt, use it
20219b2ee8SDavid du Colombier 		 */
213e12c5d1SDavid du Colombier 		disk = sys;
22219b2ee8SDavid du Colombier 	} else if(strncmp(argv0, "dksc(0,", 7) == 0){
23219b2ee8SDavid du Colombier 		/*
24219b2ee8SDavid du Colombier 		 *  on many mips arg0 of the boot command specifies the
25219b2ee8SDavid du Colombier 		 *  scsi logical unit number
26219b2ee8SDavid du Colombier 		 */
27219b2ee8SDavid du Colombier 		p = strchr(argv0, ',');
28219b2ee8SDavid du Colombier 		n = strtoul(p+1, 0, 10);
29219b2ee8SDavid du Colombier 		sprint(diskname, "#w%d/sd%dfs", n, n);
30219b2ee8SDavid du Colombier 		disk = diskname;
31219b2ee8SDavid du Colombier 	} else if(mp->arg){
32219b2ee8SDavid du Colombier 		/*
33ae886fecSDavid du Colombier 		 *  a default is optionally supplied when the kernel is made
34219b2ee8SDavid du Colombier 		 */
353e12c5d1SDavid du Colombier 		disk = mp->arg;
36ae886fecSDavid du Colombier 	} else if(inibootdisk != nil && *inibootdisk)
37ae886fecSDavid du Colombier 		/* plan9.ini overrides default from config file */
38ae886fecSDavid du Colombier 		disk = inibootdisk;
39ae886fecSDavid du Colombier 	else if(bootdisk != nil && *bootdisk){
40219b2ee8SDavid du Colombier 		/*
41219b2ee8SDavid du Colombier 		 *  an environment variable from a pc's plan9.ini or
42219b2ee8SDavid du Colombier 		 *  from the mips nvram or generated by the kernel
43219b2ee8SDavid du Colombier 		 *  is the last resort.
44219b2ee8SDavid du Colombier 		 */
45219b2ee8SDavid du Colombier 		disk = bootdisk;
46219b2ee8SDavid du Colombier 	}
47219b2ee8SDavid du Colombier 
48219b2ee8SDavid du Colombier 	/* if we've decided on one, pass it on to all programs */
49ae886fecSDavid du Colombier 	if(disk) {
50ae886fecSDavid du Colombier 		bootdisk = disk;
51ae886fecSDavid du Colombier 		setenv("bootdisk", bootdisk);
52ae886fecSDavid du Colombier 	}
533e12c5d1SDavid du Colombier }
543e12c5d1SDavid du Colombier 
553e12c5d1SDavid du Colombier int
connectlocalkfs(void)5639734e7eSDavid du Colombier connectlocalkfs(void)
573e12c5d1SDavid du Colombier {
5839734e7eSDavid du Colombier 	int i, pid, fd, p[2];
599a747e4fSDavid du Colombier 	char partition[64];
607dd7cddfSDavid du Colombier 	char *dev;
6180ee5cbfSDavid du Colombier 	char **arg, **argp;
6239734e7eSDavid du Colombier 	Dir *d;
633e12c5d1SDavid du Colombier 
646a9fc400SDavid du Colombier 	if(stat("/boot/kfs", statbuf, sizeof statbuf) < 0)
657dd7cddfSDavid du Colombier 		return -1;
663e12c5d1SDavid du Colombier 
677dd7cddfSDavid du Colombier 	dev = disk ? disk : bootdisk;
689a747e4fSDavid du Colombier 	snprint(partition, sizeof partition, "%sfs", dev);
6939734e7eSDavid du Colombier 	fd = open(partition, OREAD);
7039734e7eSDavid du Colombier 	if(fd < 0){
717dd7cddfSDavid du Colombier 		strcpy(partition, dev);
7239734e7eSDavid du Colombier 		fd = open(partition, OREAD);
7339734e7eSDavid du Colombier 		if(fd < 0)
743e12c5d1SDavid du Colombier 			return -1;
753e12c5d1SDavid du Colombier 	}
7639734e7eSDavid du Colombier 	/*
7739734e7eSDavid du Colombier 	 * can't do this check -- might be some other server posing as kfs.
7839734e7eSDavid du Colombier 	 *
7939734e7eSDavid du Colombier 	memset(buf, 0, sizeof buf);
8039734e7eSDavid du Colombier 	pread(fd, buf, 512, 0);
8139734e7eSDavid du Colombier 	close(fd);
8239734e7eSDavid du Colombier 	if(memcmp(buf+256, "kfs wren device\n", 16) != 0){
8339734e7eSDavid du Colombier 		if(strstr(partition, "/fs"))
8439734e7eSDavid du Colombier 			print("no kfs file system found on %s\n", partition);
857dd7cddfSDavid du Colombier 		return -1;
8639734e7eSDavid du Colombier 	}
8739734e7eSDavid du Colombier 	 *
8839734e7eSDavid du Colombier 	 */
8939734e7eSDavid du Colombier 	d = dirfstat(fd);
9039734e7eSDavid du Colombier 	close(fd);
9139734e7eSDavid du Colombier 	if(d == nil)
9239734e7eSDavid du Colombier 		return -1;
9339734e7eSDavid du Colombier 	if(d->mode&DMDIR){
9439734e7eSDavid du Colombier 		free(d);
9539734e7eSDavid du Colombier 		return -1;
9639734e7eSDavid du Colombier 	}
9739734e7eSDavid du Colombier 	free(d);
983e12c5d1SDavid du Colombier 
997dd7cddfSDavid du Colombier 	print("kfs...");
1003e12c5d1SDavid du Colombier 	if(pipe(p)<0)
1013e12c5d1SDavid du Colombier 		fatal("pipe");
10239734e7eSDavid du Colombier 	switch(pid = fork()){
1033e12c5d1SDavid du Colombier 	case -1:
1043e12c5d1SDavid du Colombier 		fatal("fork");
1053e12c5d1SDavid du Colombier 	case 0:
10680ee5cbfSDavid du Colombier 		arg = malloc((bargc+5)*sizeof(char*));
10780ee5cbfSDavid du Colombier 		argp = arg;
1087dd7cddfSDavid du Colombier 		*argp++ = "kfs";
109219b2ee8SDavid du Colombier 		*argp++ = "-f";
110219b2ee8SDavid du Colombier 		*argp++ = partition;
111219b2ee8SDavid du Colombier 		*argp++ = "-s";
11280ee5cbfSDavid du Colombier 		for(i=1; i<bargc; i++)
11380ee5cbfSDavid du Colombier 			*argp++ = bargv[i];
114219b2ee8SDavid du Colombier 		*argp = 0;
11580ee5cbfSDavid du Colombier 
11680ee5cbfSDavid du Colombier 		dup(p[0], 0);
11780ee5cbfSDavid du Colombier 		dup(p[1], 1);
11880ee5cbfSDavid du Colombier 		close(p[0]);
11980ee5cbfSDavid du Colombier 		close(p[1]);
1206a9fc400SDavid du Colombier 		exec("/boot/kfs", arg);
1217dd7cddfSDavid du Colombier 		fatal("can't exec kfs");
1223e12c5d1SDavid du Colombier 	default:
1233e12c5d1SDavid du Colombier 		break;
1243e12c5d1SDavid du Colombier 	}
12539734e7eSDavid du Colombier 	for(;;){
12639734e7eSDavid du Colombier 		if((i = waitpid()) == -1)
12739734e7eSDavid du Colombier 			fatal("waitpid for kfs failed");
12839734e7eSDavid du Colombier 		if(i == pid)
12939734e7eSDavid du Colombier 			break;
13039734e7eSDavid du Colombier 	}
1313e12c5d1SDavid du Colombier 
1323e12c5d1SDavid du Colombier 	close(p[1]);
1333e12c5d1SDavid du Colombier 	return p[0];
1343e12c5d1SDavid du Colombier }
13539734e7eSDavid du Colombier 
136d1f2e59dSDavid du Colombier void
runv(char ** argv)137ae886fecSDavid du Colombier runv(char **argv)
13839734e7eSDavid du Colombier {
139d1f2e59dSDavid du Colombier 	int i, pid;
14039734e7eSDavid du Colombier 
14139734e7eSDavid du Colombier 	switch(pid = fork()){
14239734e7eSDavid du Colombier 	case -1:
14339734e7eSDavid du Colombier 		fatal("fork");
14439734e7eSDavid du Colombier 	case 0:
145ae886fecSDavid du Colombier 		exec(argv[0], argv);
146ae886fecSDavid du Colombier 		fatal(smprint("can't exec %s: %r", argv[0]));
14739734e7eSDavid du Colombier 	default:
148d1f2e59dSDavid du Colombier 		while ((i = waitpid()) != pid && i != -1)
149d1f2e59dSDavid du Colombier 			;
150d1f2e59dSDavid du Colombier 		if(i == -1)
151ae886fecSDavid du Colombier 			fatal(smprint("wait failed running %s", argv[0]));
15239734e7eSDavid du Colombier 	}
15339734e7eSDavid du Colombier }
15439734e7eSDavid du Colombier 
155ae886fecSDavid du Colombier void
run(char * file,...)156ae886fecSDavid du Colombier run(char *file, ...)
157ae886fecSDavid du Colombier {
158ae886fecSDavid du Colombier 	runv(&file);
159ae886fecSDavid du Colombier }
160ae886fecSDavid du Colombier 
16139734e7eSDavid du Colombier static int
print1(int fd,char * s)16239734e7eSDavid du Colombier print1(int fd, char *s)
16339734e7eSDavid du Colombier {
16439734e7eSDavid du Colombier 	return write(fd, s, strlen(s));
16539734e7eSDavid du Colombier }
16639734e7eSDavid du Colombier 
16739734e7eSDavid du Colombier void
configloopback(void)16839734e7eSDavid du Colombier configloopback(void)
16939734e7eSDavid du Colombier {
17039734e7eSDavid du Colombier 	int fd;
17139734e7eSDavid du Colombier 
17239734e7eSDavid du Colombier 	if((fd = open("/net/ipifc/clone", ORDWR)) < 0){
17339734e7eSDavid du Colombier 		bind("#I", "/net", MAFTER);
17439734e7eSDavid du Colombier 		if((fd = open("/net/ipifc/clone", ORDWR)) < 0)
17539734e7eSDavid du Colombier 			fatal("open /net/ipifc/clone for loopback");
17639734e7eSDavid du Colombier 	}
17739734e7eSDavid du Colombier 	if(print1(fd, "bind loopback /dev/null") < 0
17839734e7eSDavid du Colombier 	|| print1(fd, "add 127.0.0.1 255.255.255.255") < 0)
17939734e7eSDavid du Colombier 		fatal("write /net/ipifc/clone for loopback");
18039734e7eSDavid du Colombier }
18139734e7eSDavid du Colombier 
18239734e7eSDavid du Colombier int
connectlocalfossil(void)18339734e7eSDavid du Colombier connectlocalfossil(void)
18439734e7eSDavid du Colombier {
18539734e7eSDavid du Colombier 	int fd;
186df4c56aeSDavid du Colombier 	char *venti, *f[32], *p;
18739734e7eSDavid du Colombier 	int nf;
18839734e7eSDavid du Colombier 	char partition[128], buf[512];
18939734e7eSDavid du Colombier 	char *dev;
19039734e7eSDavid du Colombier 
19139734e7eSDavid du Colombier 	if(stat("/boot/fossil", statbuf, sizeof statbuf) < 0)
19239734e7eSDavid du Colombier 		return -1;
19339734e7eSDavid du Colombier 
19439734e7eSDavid du Colombier 	/* look for fossil partition */
19539734e7eSDavid du Colombier 	dev = disk ? disk : bootdisk;
19639734e7eSDavid du Colombier 	snprint(partition, sizeof partition, "%sfossil", dev);
19739734e7eSDavid du Colombier 	fd = open(partition, OREAD);
19839734e7eSDavid du Colombier 	if(fd < 0){
19939734e7eSDavid du Colombier 		strcpy(partition, dev);
20039734e7eSDavid du Colombier 		fd = open(partition, OREAD);
20139734e7eSDavid du Colombier 		if(fd < 0)
20239734e7eSDavid du Colombier 			return -1;
20339734e7eSDavid du Colombier 	}
20439734e7eSDavid du Colombier 	memset(buf, 0, sizeof buf);
20539734e7eSDavid du Colombier 	pread(fd, buf, 512, 127*1024);
20639734e7eSDavid du Colombier 	close(fd);
20739734e7eSDavid du Colombier 	if(memcmp(buf, "fossil config\n", 14) != 0){
20839734e7eSDavid du Colombier 		if(strstr(partition, "/fossil"))
20939734e7eSDavid du Colombier 			print("no fossil config found on %s\n", partition);
21039734e7eSDavid du Colombier 		return -1;
21139734e7eSDavid du Colombier 	}
21239734e7eSDavid du Colombier 
21339734e7eSDavid du Colombier 	settime(1, -1, nil);
21439734e7eSDavid du Colombier 
215*a2ede175SDavid du Colombier 	/* make venti available.  give it 20% of free memory. */
21639734e7eSDavid du Colombier 	if((venti = getenv("venti")) && (nf = tokenize(venti, f, nelem(f)))){
21739734e7eSDavid du Colombier 		if((fd = open(f[0], OREAD)) >= 0){
21839734e7eSDavid du Colombier 			print("venti...");
21939734e7eSDavid du Colombier 			memset(buf, 0, sizeof buf);
22039734e7eSDavid du Colombier 			pread(fd, buf, 512, 248*1024);
22139734e7eSDavid du Colombier 			close(fd);
22239734e7eSDavid du Colombier 			if(memcmp(buf, "venti config\n", 13) != 0){
22339734e7eSDavid du Colombier 				print("no venti config found on %s\n", f[0]);
22439734e7eSDavid du Colombier 				return -1;
22539734e7eSDavid du Colombier 			}
22639734e7eSDavid du Colombier 			if(stat("/boot/venti", statbuf, sizeof statbuf) < 0){
22739734e7eSDavid du Colombier 				print("/boot/venti does not exist\n");
22839734e7eSDavid du Colombier 				return -1;
22939734e7eSDavid du Colombier 			}
23039734e7eSDavid du Colombier 			switch(nf){
23139734e7eSDavid du Colombier 			case 1:
23239734e7eSDavid du Colombier 				f[1] = "tcp!127.1!17034";
23339734e7eSDavid du Colombier 			case 2:
23439734e7eSDavid du Colombier 				f[2] = "tcp!127.1!8000";
23539734e7eSDavid du Colombier 			}
23639734e7eSDavid du Colombier 			configloopback();
237*a2ede175SDavid du Colombier 			run("/boot/venti", "-m", "20", "-c", f[0],
238*a2ede175SDavid du Colombier 				"-a", f[1], "-h", f[2], nil);
239df4c56aeSDavid du Colombier 			/*
240df4c56aeSDavid du Colombier 			 * If the announce address is tcp!*!foo, then set
241df4c56aeSDavid du Colombier 			 * $venti to tcp!127.1!foo instead, which is actually dialable.
242df4c56aeSDavid du Colombier 			 */
2437c881178SDavid du Colombier 			if((p = strstr(f[1], "!*!")) != 0){
244df4c56aeSDavid du Colombier 				*p = 0;
245df4c56aeSDavid du Colombier 				snprint(buf, sizeof buf, "%s!127.1!%s", f[1], p+3);
246df4c56aeSDavid du Colombier 				f[1] = buf;
247df4c56aeSDavid du Colombier 			}
24839734e7eSDavid du Colombier 			setenv("venti", f[1]);
24939734e7eSDavid du Colombier 		}else{
25039734e7eSDavid du Colombier 			/* set up the network so we can talk to the venti server */
25139734e7eSDavid du Colombier 			/* this is such a crock. */
25239734e7eSDavid du Colombier 			configip(nf, f, 0);
25339734e7eSDavid du Colombier 			setenv("venti", f[0]);
25439734e7eSDavid du Colombier 		}
25539734e7eSDavid du Colombier 	}
25639734e7eSDavid du Colombier 
257*a2ede175SDavid du Colombier 	/* start fossil.  give it 20% of free memory. */
25839734e7eSDavid du Colombier 	print("fossil(%s)...", partition);
259*a2ede175SDavid du Colombier 	run("/boot/fossil", "-m", "20", "-f", partition,
260*a2ede175SDavid du Colombier 		"-c", "srv -A fboot", "-c", "srv -p fscons", nil);
26139734e7eSDavid du Colombier 	fd = open("#s/fboot", ORDWR);
26239734e7eSDavid du Colombier 	if(fd < 0){
2638c055935SDavid du Colombier 		warning("open #s/fboot");
26439734e7eSDavid du Colombier 		return -1;
26539734e7eSDavid du Colombier 	}
266ae886fecSDavid du Colombier 	remove("#s/fboot");  /* we'll repost fd as #s/boot after fversion(fd) */
26739734e7eSDavid du Colombier 	return fd;
26839734e7eSDavid du Colombier }
26939734e7eSDavid du Colombier 
27039734e7eSDavid du Colombier int
connectlocal(void)27139734e7eSDavid du Colombier connectlocal(void)
27239734e7eSDavid du Colombier {
27339734e7eSDavid du Colombier 	int fd;
27439734e7eSDavid du Colombier 
27539734e7eSDavid du Colombier 	if(bind("#c", "/dev", MREPL) < 0)
27639734e7eSDavid du Colombier 		fatal("bind #c");
27739734e7eSDavid du Colombier 	if(bind("#p", "/proc", MREPL) < 0)
27839734e7eSDavid du Colombier 		fatal("bind #p");
27939734e7eSDavid du Colombier 	bind("#S", "/dev", MAFTER);
280ac020a8fSDavid du Colombier 	bind("#k", "/dev", MAFTER);
2818c055935SDavid du Colombier 	bind("#u", "/dev", MAFTER);
282ac020a8fSDavid du Colombier 	bind("#æ", "/dev", MAFTER);
283ae886fecSDavid du Colombier 	mountusbparts();	/* make partfs partitions visible again */
28439734e7eSDavid du Colombier 
28539734e7eSDavid du Colombier 	if((fd = connectlocalfossil()) < 0)
286ae886fecSDavid du Colombier 		fd = connectlocalkfs();
28739734e7eSDavid du Colombier 	return fd;
28839734e7eSDavid du Colombier }
289